Skip to content

Commit

Permalink
ref: Optimize jsonwriter to allocate less in some cases (#500)
Browse files Browse the repository at this point in the history
  • Loading branch information
Swatinem authored Mar 24, 2021
1 parent 1b151d1 commit 757a7b8
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 68 deletions.
2 changes: 1 addition & 1 deletion src/sentry_database.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ bool
sentry__run_write_session(
const sentry_run_t *run, const sentry_session_t *session)
{
sentry_jsonwriter_t *jw = sentry__jsonwriter_new_in_memory();
sentry_jsonwriter_t *jw = sentry__jsonwriter_new(NULL);
if (!jw) {
return false;
}
Expand Down
31 changes: 22 additions & 9 deletions src/sentry_envelope.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,11 +212,17 @@ sentry__envelope_add_event(sentry_envelope_t *envelope, sentry_value_t event)
return NULL;
}

sentry_jsonwriter_t *jw = sentry__jsonwriter_new(NULL);
if (!jw) {
return NULL;
}

sentry_value_t event_id = sentry__ensure_event_id(event, NULL);

item->event = event;
item->payload = sentry_value_to_json(event);
item->payload_len = strlen(item->payload);
sentry__jsonwriter_write_value(jw, event);
item->payload = sentry__jsonwriter_into_string(jw, &item->payload_len);

sentry__envelope_item_set_header(
item, "type", sentry_value_new_string("event"));
sentry_value_t length = sentry_value_new_int32((int32_t)item->payload_len);
Expand All @@ -235,7 +241,7 @@ sentry__envelope_add_session(
if (!envelope || !session) {
return NULL;
}
sentry_jsonwriter_t *jw = sentry__jsonwriter_new_in_memory();
sentry_jsonwriter_t *jw = sentry__jsonwriter_new(NULL);
if (!jw) {
return NULL;
}
Expand Down Expand Up @@ -281,20 +287,27 @@ static void
sentry__envelope_serialize_headers_into_stringbuilder(
const sentry_envelope_t *envelope, sentry_stringbuilder_t *sb)
{
char *buf = sentry_value_to_json(envelope->contents.items.headers);
sentry__stringbuilder_append(sb, buf);
sentry_free(buf);
sentry_jsonwriter_t *jw = sentry__jsonwriter_new(sb);
if (jw) {
sentry__jsonwriter_write_value(jw, envelope->contents.items.headers);
sentry__jsonwriter_free(jw);
}
}

static void
sentry__envelope_serialize_item_into_stringbuilder(
const sentry_envelope_item_t *item, sentry_stringbuilder_t *sb)
{
sentry_jsonwriter_t *jw = sentry__jsonwriter_new(sb);
if (!jw) {
return;
}
sentry__stringbuilder_append_char(sb, '\n');
char *buf = sentry_value_to_json(item->headers);
sentry__stringbuilder_append(sb, buf);

sentry__jsonwriter_write_value(jw, item->headers);
sentry__jsonwriter_free(jw);

sentry__stringbuilder_append_char(sb, '\n');
sentry_free(buf);

sentry__stringbuilder_append_buf(sb, item->payload, item->payload_len);
}
Expand Down
73 changes: 24 additions & 49 deletions src/sentry_json.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,36 @@
#include "sentry_utils.h"
#include "sentry_value.h"

#define DST_MODE_SB 1

struct sentry_jsonwriter_s {
union {
sentry_stringbuilder_t *sb;
} dst;
sentry_stringbuilder_t *sb;
uint64_t want_comma;
uint32_t depth;
bool last_was_key;
char dst_mode;
bool owns_sb;
};

sentry_jsonwriter_t *
sentry__jsonwriter_new_in_memory(void)
sentry__jsonwriter_new(sentry_stringbuilder_t *sb)
{
sentry_jsonwriter_t *rv = SENTRY_MAKE(sentry_jsonwriter_t);
if (!rv) {
bool owns_sb = false;
if (!sb) {
sb = SENTRY_MAKE(sentry_stringbuilder_t);
owns_sb = true;
sentry__stringbuilder_init(sb);
}
if (!sb) {
return NULL;
}
rv->dst.sb = SENTRY_MAKE(sentry_stringbuilder_t);
if (!rv->dst.sb) {
sentry_free(rv);
sentry_jsonwriter_t *rv = SENTRY_MAKE(sentry_jsonwriter_t);
if (!rv) {
return NULL;
}
sentry__stringbuilder_init(rv->dst.sb);
rv->dst_mode = DST_MODE_SB;

rv->sb = sb;
rv->want_comma = 0;
rv->depth = 0;
rv->last_was_key = 0;
rv->owns_sb = owns_sb;
return rv;
}

Expand All @@ -49,42 +50,22 @@ sentry__jsonwriter_free(sentry_jsonwriter_t *jw)
if (!jw) {
return;
}
switch (jw->dst_mode) {
case DST_MODE_SB:
sentry__stringbuilder_cleanup(jw->dst.sb);
sentry_free(jw->dst.sb);
break;
if (jw->owns_sb) {
sentry__stringbuilder_cleanup(jw->sb);
sentry_free(jw->sb);
}
sentry_free(jw);
}

size_t
sentry__jsonwriter_get_length(const sentry_jsonwriter_t *jw)
{
switch (jw->dst_mode) {
case DST_MODE_SB: {
const sentry_stringbuilder_t *sb = jw->dst.sb;
return sb->len;
}
default:
return 0;
}
}

char *
sentry__jsonwriter_into_string(sentry_jsonwriter_t *jw, size_t *len_out)
{
char *rv = NULL;
switch (jw->dst_mode) {
case DST_MODE_SB: {
sentry_stringbuilder_t *sb = jw->dst.sb;
if (len_out) {
*len_out = sb->len;
}
rv = sentry__stringbuilder_into_string(sb);
break;
}
sentry_stringbuilder_t *sb = jw->sb;
if (len_out) {
*len_out = sb->len;
}
rv = sentry__stringbuilder_into_string(sb);
sentry__jsonwriter_free(jw);
return rv;
}
Expand All @@ -111,19 +92,13 @@ set_comma(sentry_jsonwriter_t *jw, bool val)
static void
write_char(sentry_jsonwriter_t *jw, char c)
{
switch (jw->dst_mode) {
case DST_MODE_SB:
sentry__stringbuilder_append_char(jw->dst.sb, c);
}
sentry__stringbuilder_append_char(jw->sb, c);
}

static void
write_str(sentry_jsonwriter_t *jw, const char *str)
{
switch (jw->dst_mode) {
case DST_MODE_SB:
sentry__stringbuilder_append(jw->dst.sb, str);
}
sentry__stringbuilder_append(jw->sb, str);
}

static void
Expand Down
9 changes: 6 additions & 3 deletions src/sentry_json.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@

#include "sentry_boot.h"

struct sentry_jsonwriter_s;
typedef struct sentry_stringbuilder_s sentry_stringbuilder_t;
typedef struct sentry_jsonwriter_s sentry_jsonwriter_t;

/**
* This creates a new in-memory JSON writer, based on `sentry_stringbuilder_s`.
* This creates a new JSON writer.
*
* It will use an existing `sentry_stringbuilder_t` as its output if one is
* provided, otherwise it will allocate a new one.
*/
sentry_jsonwriter_t *sentry__jsonwriter_new_in_memory(void);
sentry_jsonwriter_t *sentry__jsonwriter_new(sentry_stringbuilder_t *sb);

/**
* Deallocates a JSON writer.
Expand Down
15 changes: 9 additions & 6 deletions src/sentry_value.c
Original file line number Diff line number Diff line change
Expand Up @@ -794,8 +794,8 @@ sentry_value_is_null(sentry_value_t value)
return value._bits == CONST_NULL;
}

static void
value_to_json(sentry_jsonwriter_t *jw, sentry_value_t value)
void
sentry__jsonwriter_write_value(sentry_jsonwriter_t *jw, sentry_value_t value)
{
switch (sentry_value_get_type(value)) {
case SENTRY_VALUE_TYPE_NULL:
Expand All @@ -817,7 +817,7 @@ value_to_json(sentry_jsonwriter_t *jw, sentry_value_t value)
const list_t *l = value_as_thing(value)->payload._ptr;
sentry__jsonwriter_write_list_start(jw);
for (size_t i = 0; i < l->len; i++) {
value_to_json(jw, l->items[i]);
sentry__jsonwriter_write_value(jw, l->items[i]);
}
sentry__jsonwriter_write_list_end(jw);
break;
Expand All @@ -827,7 +827,7 @@ value_to_json(sentry_jsonwriter_t *jw, sentry_value_t value)
sentry__jsonwriter_write_object_start(jw);
for (size_t i = 0; i < o->len; i++) {
sentry__jsonwriter_write_key(jw, o->pairs[i].k);
value_to_json(jw, o->pairs[i].v);
sentry__jsonwriter_write_value(jw, o->pairs[i].v);
}
sentry__jsonwriter_write_object_end(jw);
break;
Expand All @@ -838,8 +838,11 @@ value_to_json(sentry_jsonwriter_t *jw, sentry_value_t value)
char *
sentry_value_to_json(sentry_value_t value)
{
sentry_jsonwriter_t *jw = sentry__jsonwriter_new_in_memory();
value_to_json(jw, value);
sentry_jsonwriter_t *jw = sentry__jsonwriter_new(NULL);
if (!jw) {
return NULL;
}
sentry__jsonwriter_write_value(jw, value);
return sentry__jsonwriter_into_string(jw, NULL);
}

Expand Down
8 changes: 8 additions & 0 deletions src/sentry_value.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,12 @@ int sentry__value_append_bounded(
*/
sentry_value_t sentry__value_from_json(const char *buf, size_t buflen);

typedef struct sentry_jsonwriter_s sentry_jsonwriter_t;

/**
* Writes the given `value` into the `jsonwriter`.
*/
void sentry__jsonwriter_write_value(
sentry_jsonwriter_t *jw, sentry_value_t value);

#endif

0 comments on commit 757a7b8

Please sign in to comment.