misc performance improvements

This commit is contained in:
hippoz 2023-01-19 22:47:47 +02:00
parent d2ee4cb71d
commit e744f4afed
Signed by: hippoz
GPG key ID: 56C4E02A85F2FBED
3 changed files with 88 additions and 50 deletions

View file

@ -5,6 +5,7 @@
#include <stdint.h>
#include <sys/socket.h>
#include <sys/fcntl.h>
#include <sys/uio.h>
#include <sys/un.h>
#include <unistd.h>
#include <string.h>
@ -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;
}

80
wire.c
View file

@ -1,6 +1,7 @@
#include <string.h>
#include <stdio.h>
#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;
}

32
wire.h
View file

@ -5,6 +5,7 @@
#include <stdint.h>
#include <stdbool.h>
#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);