Files
core/test/performance/fixtures/api-json/wire-input.c
T
2026-11-03 03:32:07 +00:00

113 lines
4.8 KiB
C

#define _POSIX_C_SOURCE 200809L
#include "runtime.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
extern long long dever_test_allocations(void);
static void text_clone(const void *source, void *target) {
*(void **)target = dever_rt_v1_text_retain(*(void *const *)source);
}
static void text_drop(void *value) {
dever_rt_v1_text_release(*(void **)value);
*(void **)value = NULL;
}
static uint8_t text_equal(const void *left, const void *right) {
return dever_rt_v1_text_equal(*(void *const *)left, *(void *const *)right);
}
static const DeverRtType text_type = {
sizeof(void *), _Alignof(void *), text_clone, text_drop, text_equal, NULL
};
static uint32_t input_field(void *inputs, void *out, DeverRtBuffer *error) {
const DeverRtWireName name = {(const uint8_t *)"source", 6};
uint8_t present = 0;
return dever_rt_v1_cmd_input_field(inputs, &name, 1, out, &present, error);
}
static uint32_t decode(const void *reader, void *out, DeverRtBuffer *error) {
return dever_rt_v1_wire_read_raw(reader, out, error);
}
static uint32_t encode(const void *value, void *encoder, DeverRtBuffer *error) {
return dever_rt_v1_wire_encoder_json(encoder, *(void *const *)value, error);
}
static uint32_t operation(unsigned phase, void *body, void *source, void **out, DeverRtBuffer *error) {
if (phase == 0) return dever_rt_v1_cmd_decode(body, &text_type, input_field, out, error);
if (phase == 1) return dever_rt_v1_wire_decode(source, &text_type, decode, out, error);
if (phase == 2) return dever_rt_v1_wire_encode(&source, &text_type, encode, out, error);
return dever_rt_v1_json_from_text(source, out, error);
}
int dever_test_run(void) {
const char *setting = getenv("DEVER_WIRE_BENCH_ROWS");
size_t rows = setting == NULL ? 128 : (size_t)strtoul(setting, NULL, 10);
int wide = getenv("DEVER_WIRE_BENCH_WIDE") != NULL;
if (rows != 1 && rows != 16 && rows != 128 && !(wide && rows == 1024)) return 1;
const char *row = "{\"id\":9007199254740993,\"text\":\"雪😀\\n\\\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\"weight\":1.25,\"note\":null}";
const char *suffix = "],\"raw\":{\"large\":123456789012345678901234567890}}";
size_t capacity = rows * (strlen(row) + 1) + strlen(suffix) + 64;
char *raw = malloc(capacity);
if (raw == NULL) return 2;
strcpy(raw, wide ? "{" : "{\"rows\":[");
for (size_t index = 0; index < rows; ++index) {
if (index != 0) strcat(raw, ",");
if (wide) {
char field[64];
snprintf(field, sizeof(field), "\"field_%zu\":%zu", index, index);
strcat(raw, field);
} else {
strcat(raw, row);
}
}
strcat(raw, wide ? "}" : suffix);
size_t length = strlen(raw);
DeverRtBuffer error = {0};
void *source = NULL, *body = NULL;
if (dever_rt_v1_text_new((const uint8_t *)raw, length, &source, &error)) return 3;
if (getenv("DEVER_WIRE_BENCH_VALIDATED") != NULL) {
void *validated = NULL;
if (dever_rt_v1_wire_decode(source, &text_type, decode, &validated, &error)) return 11;
dever_rt_v1_text_release(source);
source = validated;
}
char *request = malloc(length + 12);
if (request == NULL) return 4;
snprintf(request, length + 12, "{\"source\":%s}", raw);
if (dever_rt_v1_text_new((const uint8_t *)request, strlen(request), &body, &error)) return 5;
free(request);
for (unsigned phase = 0; phase < 4; ++phase) {
void *output = NULL;
if (operation(phase, body, source, &output, &error)) return 6;
DeverRtBuffer bytes = {0};
if (dever_rt_v1_text_export(output, &bytes) || bytes.len != length || memcmp(bytes.ptr, raw, length) != 0) return 7;
dever_rt_v1_buffer_free(bytes.ptr, bytes.len);
dever_rt_v1_text_release(output);
struct timespec started, finished;
if (clock_gettime(CLOCK_MONOTONIC, &started)) return 8;
long long allocations = dever_test_allocations();
const size_t iterations = 500;
for (size_t iteration = 0; iteration < iterations; ++iteration) {
if (operation(phase, body, source, &output, &error)) return 9;
dever_rt_v1_text_release(output);
}
allocations = dever_test_allocations() - allocations;
if (clock_gettime(CLOCK_MONOTONIC, &finished)) return 10;
int64_t elapsed = (int64_t)(finished.tv_sec - started.tv_sec) * INT64_C(1000000000)
+ finished.tv_nsec - started.tv_nsec;
printf("{\"phase\":%u,\"rows\":%zu,\"iterations\":%zu,\"elapsed_ns\":%lld,\"allocations\":%lld}\n",
phase, rows, iterations, (long long)elapsed, allocations);
}
dever_rt_v1_text_release(source);
dever_rt_v1_text_release(body);
free(raw);
return 0;
}