113 lines
4.8 KiB
C
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;
|
|
}
|