From 8b5cc3b4931d974b7c6f0d1257b15837b31d841a Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Wed, 18 Dec 2024 00:40:17 +1100 Subject: [PATCH] Wrote a benchmark to test TOY_BUCKET_IDEAL sizes --- source/toy.h | 4 +- tests/benchmarks/bench_main.c | 98 +++++++++++++++++++++-------------- tests/benchmarks/makefile | 28 +++++----- 3 files changed, 72 insertions(+), 58 deletions(-) diff --git a/source/toy.h b/source/toy.h index 38a3d73..b98b89c 100644 --- a/source/toy.h +++ b/source/toy.h @@ -6,11 +6,11 @@ #include "toy_print.h" //basic structures +#include "toy_bucket.h" +#include "toy_string.h" #include "toy_value.h" #include "toy_array.h" #include "toy_stack.h" -#include "toy_bucket.h" -#include "toy_string.h" #include "toy_table.h" //IR structures and other components diff --git a/tests/benchmarks/bench_main.c b/tests/benchmarks/bench_main.c index 12fb027..5078380 100644 --- a/tests/benchmarks/bench_main.c +++ b/tests/benchmarks/bench_main.c @@ -1,60 +1,78 @@ -#include "toy_table.h" +#include "toy.h" #include +#include -//utils -unsigned int hashUInt(unsigned int x) { - x = ((x >> 16) ^ x) * 0x45d9f3b; - x = ((x >> 16) ^ x) * 0x45d9f3b; - x = (x >> 16) ^ x; - return x; +//generate an immense series of Toy_String instances to fill the buckets, thrn compare the time taken for each possible vale of TOY_BUCKET_IDEAL + +static unsigned int hash(unsigned int x) { + x = ((x >> 16) ^ x) * 0x45d9f3b; + x = ((x >> 16) ^ x) * 0x45d9f3b; + x = ((x >> 16) ^ x); + return x; } -void stress_inserts(unsigned int seed, unsigned int iterations, unsigned int limit) { - //randomly generate a series of key-value pairs (from a seed) and insert them - { - //setup - Toy_Table* table = Toy_allocateTable(); +static unsigned int seed = 42; - for (unsigned int i = 0; i < iterations; i++) { - //next seed - seed = hashUInt(seed); +static unsigned int rng() { + return seed = hash(seed); +} - //don't exceed a certain number of entries - unsigned int masked = seed & (limit-1); //lol +#define MAX 9 +const char* samples[] = { //9 entries + "the", + "quick", + "brown", + "fox", + "jumped", + "over", + "the", + "lazy", + "dog", +}; - //actual values don't matter, as long as they can be recreated - Toy_Value key = TOY_VALUE_FROM_INTEGER(masked); - Toy_Value value = TOY_VALUE_FROM_INTEGER(masked); +void stress_fillBucket(Toy_Bucket** bucketHandle) { + for (unsigned int i = 0; i < 10000000; i++) { + //create some leaf and node strings + Toy_String* a = Toy_createString(bucketHandle, samples[rng() % MAX]); + Toy_String* b = Toy_createString(bucketHandle, samples[rng() % MAX]); + Toy_String* c = Toy_createString(bucketHandle, samples[rng() % MAX]); + Toy_String* d = Toy_createString(bucketHandle, samples[rng() % MAX]); - Toy_insertTable(&table, key, value); - } + Toy_String* l = Toy_concatStrings(bucketHandle, a, b); + Toy_String* r = Toy_concatStrings(bucketHandle, c, d); + Toy_concatStrings(bucketHandle, l, r); - //cleanup - Toy_freeTable(table); +// char* buffer = Toy_getStringRawBuffer(s); +// printf("%s\n", buffer); +// free(buffer); } } -int main(int argc, char* argv[]) { - if (argc != 3) { - printf("Usage: %s iterations limit\n", argv[0]); - return 0; - } +static unsigned long long int measureDepth(Toy_Bucket* bucket) { + return bucket == NULL ? 0 : 1 + measureDepth(bucket->next); +} - unsigned int iterations = 0; - unsigned int limit = 0; +static unsigned long long int measureCapacity(Toy_Bucket* bucket) { + return bucket == NULL ? 0 : bucket->capacity + measureCapacity(bucket->next); +} - sscanf(argv[1], "%u", &iterations); - sscanf(argv[2], "%u", &limit); +static unsigned long long int measureCount(Toy_Bucket* bucket) { + return bucket == NULL ? 0 : bucket->count + measureCount(bucket->next); +} - //limit to 16mb - if (limit * sizeof(Toy_TableEntry) > (1024 * 1024 * 16)) { - printf("Error: limit must be below %u for safety reasons\n", (1024 * 1024 * 16)/sizeof(Toy_TableEntry)); - return 0; - } +int main() { + Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL); - //run the stress test - stress_inserts(42, iterations, limit); + stress_fillBucket(&bucket); + + unsigned long long int depth = measureDepth(bucket); + unsigned long long int capacity = measureCapacity(bucket); + unsigned long long int count = measureCount(bucket); + + printf(TOY_CC_FONT_RED TOY_CC_BACK_YELLOW "Result: %u: %llu, %llu, %llu" TOY_CC_RESET "\n", TOY_BUCKET_IDEAL, depth, capacity, count); + + Toy_freeBucket(&bucket); return 0; } diff --git a/tests/benchmarks/makefile b/tests/benchmarks/makefile index bfca481..6060718 100644 --- a/tests/benchmarks/makefile +++ b/tests/benchmarks/makefile @@ -31,21 +31,18 @@ TEST_CASESFILES=$(wildcard $(TEST_CASESDIR)/bench_*.c) #build the object files, compile the test cases, and run all: clean + $(MAKE) TOY_BUCKET_IDEAL=16372 all-override + $(MAKE) TOY_BUCKET_IDEAL=32756 all-override + $(MAKE) TOY_BUCKET_IDEAL=65524 all-override + $(MAKE) TOY_BUCKET_IDEAL=131060 all-override + $(MAKE) TOY_BUCKET_IDEAL=262132 all-override + +all-override: clean $(MAKE) build-source $(MAKE) build-cases $(MAKE) build-link $(MAKE) build-run -all-override: clean - $(MAKE) TEST_SOURCEFILES='$(subst $(TEST_SOURCEDIR)/$(OVERRIDE),$(OVERRIDE),$(TEST_SOURCEFILES))' build-source-override - $(MAKE) build-cases - $(MAKE) build-link - $(MAKE) build-run - -.PHONY: build-source-override -build-source-override: $(TEST_OUTDIR) $(TEST_OBJDIR) $(addprefix $(TEST_OBJDIR)/,$(notdir $(TEST_SOURCEFILES:.c=.o))) - $(CC) -c -o $(TEST_OBJDIR)/$(OVERRIDE:.c=.o) $(OVERRIDE) $(addprefix -I,$(TEST_SOURCEDIR)) $(CFLAGS) -fdata-sections -ffunction-sections - #targets for each step .PHONY: build-source build-source: $(TEST_OUTDIR) $(TEST_OBJDIR) $(addprefix $(TEST_OBJDIR)/,$(notdir $(TEST_SOURCEFILES:.c=.o))) @@ -61,19 +58,18 @@ build-run: $(addprefix $(TEST_OUTDIR)/,$(notdir $(TEST_CASESFILES:%.c=%.exe))) $ #compilation steps $(TEST_OBJDIR)/%.o: $(TEST_SOURCEDIR)/%.c - $(CC) -c -o $@ $< $(addprefix -I,$(TEST_SOURCEDIR)) $(CFLAGS) -fdata-sections -ffunction-sections + $(CC) -DTOY_BUCKET_IDEAL=$(TOY_BUCKET_IDEAL) -c -o $@ $< $(addprefix -I,$(TEST_SOURCEDIR)) $(CFLAGS) -fdata-sections -ffunction-sections $(TEST_OBJDIR)/%.o: $(TEST_CASESDIR)/%.c - $(CC) -c -o $@ $< $(addprefix -I,$(TEST_SOURCEDIR) $(TEST_CASESDIR)) $(CFLAGS) -fdata-sections -ffunction-sections + $(CC) -DTOY_BUCKET_IDEAL=$(TOY_BUCKET_IDEAL) -c -o $@ $< $(addprefix -I,$(TEST_SOURCEDIR) $(TEST_CASESDIR)) $(CFLAGS) -fdata-sections -ffunction-sections $(TEST_OUTDIR)/%.exe: $(TEST_OBJDIR)/%.o - @$(CC) -o $@ $< $(addprefix $(TEST_OBJDIR)/,$(notdir $(TEST_SOURCEFILES:.c=.o))) $(CFLAGS) $(LIBS) $(LDFLAGS) + @$(CC) -DTOY_BUCKET_IDEAL=$(TOY_BUCKET_IDEAL) -o $@ $< $(addprefix $(TEST_OBJDIR)/,$(notdir $(TEST_SOURCEFILES:.c=.o))) $(CFLAGS) $(LIBS) $(LDFLAGS) + strip $@ .PRECIOUS: $(TEST_OUTDIR)/%.run $(TEST_OUTDIR)/%.run: $(TEST_OUTDIR)/%.exe - @/usr/bin/time --format "%C; $(OVERRIDE)\nUser System\n%U %E" $< 100000000 512 - @/usr/bin/time --format "%C; $(OVERRIDE)\nUser System\n%U %E" $< 100000000 1024 - @/usr/bin/time --format "%C; $(OVERRIDE)\nUser System\n%U %E" $< 100000000 4096 + @/usr/bin/time --format "User System\n%U %E" $< #util targets $(TEST_OUTDIR):