From e744f4afedb094d34e690e14992b3c9c07f08a46 Mon Sep 17 00:00:00 2001 From: hippoz <10706925-hippoz@users.noreply.gitlab.com> Date: Thu, 19 Jan 2023 22:47:47 +0200 Subject: [PATCH] misc performance improvements --- server.c | 26 ++++++++++++------ wire.c | 80 ++++++++++++++++++++++++++++++++++++++++++++------------ wire.h | 32 +++++------------------ 3 files changed, 88 insertions(+), 50 deletions(-) diff --git a/server.c b/server.c index b5df0ee..467f7b1 100644 --- a/server.c +++ b/server.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -18,13 +19,13 @@ // https://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function#FNV-1a_hash -uint64_t hashmap_hash(const char *bytes, size_t bytes_n, size_t map_len) +uint64_t hashmap_hash(const char *bytes, size_t map_len) { uint64_t hash = 0xcbf29ce484222325; - for (size_t i = 0; i < bytes_n; i++) { + while (*bytes++) { hash *= 0x100000001b3; - hash ^= bytes[i]; + hash ^= *bytes; } return (hash % map_len); @@ -140,7 +141,7 @@ int bus_client_add(Bus *s, int fd) int bus_name_find(Bus *s, char *name) { - int bucket = hashmap_hash(name, strlen(name), BUS_MAX_NAMES); + int bucket = hashmap_hash(name, BUS_MAX_NAMES); for (int i = bucket; i < bucket + 12 && i < BUS_MAX_NAMES; i++) { if (s->names[i].name && strcmp(s->names[i].name, name) == 0) { @@ -175,7 +176,7 @@ BusName *bus_name_add(Bus *s, char *name, BusClient *client) return NULL; } - int bucket = hashmap_hash(name, strlen(name), BUS_MAX_NAMES); + int bucket = hashmap_hash(name, BUS_MAX_NAMES); for (int i = bucket; i < bucket + 12 && i < BUS_MAX_NAMES; i++) { if (!s->names[i].client) { @@ -326,7 +327,7 @@ int bus_broadcast_message(Bus *s, BusClient *sender_client, WireMsg *msg, WireCt uint32_t previous_cursor = ctx->byte_cursor; if (match_rule_check(sender_client, c->matches[j], msg, ctx) >= 0) { - TRYST(wire_compose_unicast_reply(reply_ctx, ctx, msg, sender_client->unique_name->name)); + TRYST(wire_compose_unicast_reply(reply_ctx, ctx, msg, sender_client->unique_name->name, false)); TRYST(send(c->fd, reply_ctx->data, reply_ctx->byte_cursor, 0)); // TODO? memset(reply_ctx->data, 0, reply_ctx->data_len); @@ -374,8 +375,17 @@ int bus_broadcast_signal(Bus *s, BusClient *client, WireCtx *ctx, WireMsg *msg) int bus_unicast_message(Bus *s, WireMsg *msg, WireCtx *ctx, char *target_name, char *sender_unique_name, WireCtx *reply_ctx) { BusClient *target = TRYPTR(bus_name_find_client(s, target_name)); - TRYST(wire_compose_unicast_reply(reply_ctx, ctx, msg, sender_unique_name)); - TRYST(send(target->fd, reply_ctx->data, reply_ctx->byte_cursor, 0)); + TRYST(wire_compose_unicast_reply(reply_ctx, ctx, msg, sender_unique_name, true)); + + struct iovec bufs[] = { + { reply_ctx->data, reply_ctx->byte_cursor }, /* header made by wire_compose_unicast_reply */ + { ctx->data + reply_ctx->byte_cursor, msg->body_length } /* body */ + }; + + ctx->byte_cursor += msg->body_length; + reply_ctx->byte_cursor += msg->body_length; + + TRYST(writev(target->fd, bufs, sizeof(bufs) / sizeof(bufs[0]))); return 0; } diff --git a/wire.c b/wire.c index 4023d7e..9773015 100644 --- a/wire.c +++ b/wire.c @@ -1,6 +1,7 @@ #include #include #include "try.h" +#include "util.h" #include "wire.h" #include "log.h" @@ -13,6 +14,51 @@ _WIRE_DEF_TYPE(i32, int32_t, 4) _WIRE_DEF_TYPE(u32, uint32_t, 4) _WIRE_DEF_TYPE(boolean, uint32_t, 4) +bool wire_write_align(WireCtx *c, uint32_t alignment) +{ + // Thanks: https://github.com/c-util/c-stdaux/blob/ed5fee49a3ec13fe79f30324b23c73cd41805514/src/c-stdaux-gnuc.h#L431 + uint32_t new_cursor = ((c->byte_cursor) + (alignment) - 1) & ~((alignment) - 1); + + if (unlikely(new_cursor >= c->data_len || new_cursor < c->byte_cursor)) { + return false; + } + while (c->byte_cursor < new_cursor) { + c->data[c->byte_cursor++] = '\0'; + } + return true; +} + +bool wire_align(WireCtx *c, uint32_t alignment) +{ + // Thanks: https://github.com/c-util/c-stdaux/blob/ed5fee49a3ec13fe79f30324b23c73cd41805514/src/c-stdaux-gnuc.h#L431 + uint32_t new_cursor = ((c->byte_cursor) + (alignment) - 1) & ~((alignment) - 1); + + if (unlikely(new_cursor >= c->data_len || new_cursor < c->byte_cursor)) { + return false; + } + c->byte_cursor = new_cursor; + return true; +} + +char *wire_set_signature_single_char(WireCtx *c, const char s) +{ + TRYPTR_NIL(wire_set_u8(c, 1)); + + uint32_t new_cursor = c->byte_cursor + 2; /* + 2 because of the extra null termination that strings have */ + if (unlikely(new_cursor >= c->data_len)) { + return NULL; + } + + // TODO? + char *dest = (char*)&c->data[c->byte_cursor]; + dest[0] = s; + dest[1] = '\0'; + + c->byte_cursor = new_cursor; + + return dest; +} + char *wire_get_string_impl(WireCtx *c, bool as_signature) { uint32_t len = 0; @@ -366,7 +412,7 @@ int wire_compose_error(WireCtx *c, WireMsg *msg, const char *error_name) return 0; } -int wire_compose_unicast_reply(WireCtx *c, WireCtx *msg_c, WireMsg *msg, char *sender_unique_name) +int wire_compose_unicast_reply(WireCtx *c, WireCtx *msg_c, WireMsg *msg, char *sender_unique_name, bool partial) { TRYPTR(wire_set_u8(c, msg->endianness)); /* endianness */ TRYPTR(wire_set_u8(c, msg->type)); /* type */ @@ -392,29 +438,29 @@ int wire_compose_unicast_reply(WireCtx *c, WireCtx *msg_c, WireMsg *msg, char *s } TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_PATH)); - TRYPTR(wire_set_signature(c, "o")); + TRYPTR(wire_set_signature_single_char(c, 'o')); TRYPTR(wire_set_string(c, path_field->t.str)); TRYPTR(wire_write_align(c, 8)); TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_INTERFACE)); - TRYPTR(wire_set_signature(c, "s")); + TRYPTR(wire_set_signature_single_char(c, 's')); TRYPTR(wire_set_string(c, interface_field->t.str)); TRYPTR(wire_write_align(c, 8)); TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_MEMBER)); - TRYPTR(wire_set_signature(c, "s")); + TRYPTR(wire_set_signature_single_char(c, 's')); TRYPTR(wire_set_string(c, member_field->t.str)); TRYPTR(wire_write_align(c, 8)); if (signature_field->present) { TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_SIGNATURE)); - TRYPTR(wire_set_signature(c, "g")); + TRYPTR(wire_set_signature_single_char(c, 'g')); TRYPTR(wire_set_signature(c, signature_field->t.str)); TRYPTR(wire_write_align(c, 8)); } TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_SENDER)); - TRYPTR(wire_set_signature(c, "s")); + TRYPTR(wire_set_signature_single_char(c, 's')); TRYPTR(wire_set_string(c, sender_unique_name)); // last element, don't align } break; @@ -426,20 +472,20 @@ int wire_compose_unicast_reply(WireCtx *c, WireCtx *msg_c, WireMsg *msg, char *s } TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_REPLY_SERIAL)); - TRYPTR(wire_set_signature(c, "u")); + TRYPTR(wire_set_signature_single_char(c, 'u')); TRYPTR(wire_set_u32(c, reply_serial_field->t.u32)); TRYPTR(wire_write_align(c, 8)); WireMsgField *signature_field = &msg->fields[DBUS_HEADER_FIELD_SIGNATURE]; if (signature_field->present) { TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_SIGNATURE)); - TRYPTR(wire_set_signature(c, "g")); + TRYPTR(wire_set_signature_single_char(c, 'g')); TRYPTR(wire_set_signature(c, signature_field->t.str)); TRYPTR(wire_write_align(c, 8)); } TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_SENDER)); - TRYPTR(wire_set_signature(c, "s")); + TRYPTR(wire_set_signature_single_char(c, 's')); TRYPTR(wire_set_string(c, sender_unique_name)); // last element, don't align } break; @@ -452,25 +498,25 @@ int wire_compose_unicast_reply(WireCtx *c, WireCtx *msg_c, WireMsg *msg, char *s } TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_REPLY_SERIAL)); - TRYPTR(wire_set_signature(c, "u")); + TRYPTR(wire_set_signature_single_char(c, 'u')); TRYPTR(wire_set_u32(c, reply_serial_field->t.u32)); TRYPTR(wire_write_align(c, 8)); WireMsgField *signature_field = &msg->fields[DBUS_HEADER_FIELD_SIGNATURE]; if (signature_field->present) { TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_SIGNATURE)); - TRYPTR(wire_set_signature(c, "g")); + TRYPTR(wire_set_signature_single_char(c, 'g')); TRYPTR(wire_set_signature(c, signature_field->t.str)); TRYPTR(wire_write_align(c, 8)); } TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_ERROR_NAME)); - TRYPTR(wire_set_signature(c, "s")); + TRYPTR(wire_set_signature_single_char(c, 's')); TRYPTR(wire_set_string(c, error_name_field->t.str)); TRYPTR(wire_write_align(c, 8)); TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_SENDER)); - TRYPTR(wire_set_signature(c, "s")); + TRYPTR(wire_set_signature_single_char(c, 's')); TRYPTR(wire_set_string(c, sender_unique_name)); // last element, don't align } break; @@ -489,9 +535,11 @@ int wire_compose_unicast_reply(WireCtx *c, WireCtx *msg_c, WireMsg *msg, char *s return -1; } - memcpy(&c->data[c->byte_cursor], &msg_c->data[msg_c->byte_cursor], msg->body_length); - c->byte_cursor += msg->body_length; - msg_c->byte_cursor += msg->body_length; + if (!partial) { + memcpy(&c->data[c->byte_cursor], &msg_c->data[msg_c->byte_cursor], msg->body_length); + c->byte_cursor += msg->body_length; + msg_c->byte_cursor += msg->body_length; + } return 0; } diff --git a/wire.h b/wire.h index 6dc0e83..4eb1ace 100644 --- a/wire.h +++ b/wire.h @@ -5,6 +5,7 @@ #include #include #include "util.h" +#include "try.h" #define DBUS_PROTOCOL_VERSION 1 @@ -65,31 +66,8 @@ typedef struct { char *str; } WireMsgBodyString; -static inline bool wire_write_align(WireCtx *c, uint32_t alignment) -{ - // Thanks: https://github.com/c-util/c-stdaux/blob/ed5fee49a3ec13fe79f30324b23c73cd41805514/src/c-stdaux-gnuc.h#L431 - uint32_t new_cursor = ((c->byte_cursor) + (alignment) - 1) & ~((alignment) - 1); - - if (unlikely(new_cursor >= c->data_len || new_cursor < c->byte_cursor)) { - return false; - } - while (c->byte_cursor < new_cursor) { - c->data[c->byte_cursor++] = '\0'; - } - return true; -} - -static inline bool wire_align(WireCtx *c, uint32_t alignment) -{ - // Thanks: https://github.com/c-util/c-stdaux/blob/ed5fee49a3ec13fe79f30324b23c73cd41805514/src/c-stdaux-gnuc.h#L431 - uint32_t new_cursor = ((c->byte_cursor) + (alignment) - 1) & ~((alignment) - 1); - - if (unlikely(new_cursor >= c->data_len || new_cursor < c->byte_cursor)) { - return false; - } - c->byte_cursor = new_cursor; - return true; -} +bool wire_write_align(WireCtx *c, uint32_t alignment); +bool wire_align(WireCtx *c, uint32_t alignment); #define _WIRE_DECL_BYTE_TYPE(M_mnemonic, M_type) \ M_type *wire_get_##M_mnemonic(WireCtx *c); \ @@ -150,7 +128,7 @@ char *wire_get_string_check(WireCtx *c, int min_length, int max_length); int wire_parse_message(WireCtx *c, WireMsg *msg); int wire_compose_reply(WireCtx *c, WireMsg *msg, const char *signature, uint32_t **out_body_length); int wire_compose_error(WireCtx *c, WireMsg *msg, const char *error_name); -int wire_compose_unicast_reply(WireCtx *c, WireCtx *msg_c, WireMsg *msg, char *sender_unique_name); +int wire_compose_unicast_reply(WireCtx *c, WireCtx *msg_c, WireMsg *msg, char *sender_unique_name, bool partial); int wire_compose_signal(WireCtx *c, WireMsg *out_msg, const char *signature, const char *member, uint32_t **out_body_length); int wire_collect_strings(WireCtx *c, WireMsg *msg, WireMsgBodyString *strings, int strings_count); @@ -170,6 +148,8 @@ static inline char *wire_set_string(WireCtx *c, const char *str) { return wire_set_string_impl(c, str, false); } +char *wire_set_signature_single_char(WireCtx *c, const char s); + // maximum name length is 255 static inline char *wire_get_name_string(WireCtx *c) { return wire_get_string_check(c, 1, 255);