From 54e82846c3efa49cb78785e2e813c499817e465a Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Tue, 13 Jun 2023 14:49:46 +1000 Subject: [PATCH] Massive dict copying optimisation, read more I simply pre-allocated the new dict to the right size. This skips internal copying logic which was repeated on every expansion. This Should increase scope copying as well. I applied the same logic to arrays, but the increase in speed was tiny. --- scripts/test_copy_speed.toy | 16 ++++++++++++++++ source/toy_literal.c | 19 ++++++++++++++++--- 2 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 scripts/test_copy_speed.toy diff --git a/scripts/test_copy_speed.toy b/scripts/test_copy_speed.toy new file mode 100644 index 0000000..03b04d7 --- /dev/null +++ b/scripts/test_copy_speed.toy @@ -0,0 +1,16 @@ + + +fn identity(x) { + return x; +} + + +var dict: [int:int] = [:]; + +for (var i: int = 0; i < 1000; i++) { + dict[i] = i; +} + +for (var i: int = 0; i < 100_000; i++) { + var x = identity(dict); +} diff --git a/source/toy_literal.c b/source/toy_literal.c index 3598338..dac2ea3 100644 --- a/source/toy_literal.c +++ b/source/toy_literal.c @@ -119,6 +119,10 @@ Toy_Literal Toy_copyLiteral(Toy_Literal original) { Toy_LiteralArray* array = TOY_ALLOCATE(Toy_LiteralArray, 1); Toy_initLiteralArray(array); + //preallocate enough space + array->capacity = TOY_AS_ARRAY(original)->capacity; + array->literals = TOY_GROW_ARRAY(Toy_Literal, array->literals, 0, array->capacity); + //copy each element for (int i = 0; i < TOY_AS_ARRAY(original)->count; i++) { Toy_pushLiteralArray(array, TOY_AS_ARRAY(original)->literals[i]); @@ -131,6 +135,15 @@ Toy_Literal Toy_copyLiteral(Toy_Literal original) { Toy_LiteralDictionary* dictionary = TOY_ALLOCATE(Toy_LiteralDictionary, 1); Toy_initLiteralDictionary(dictionary); + //preallocate enough space + dictionary->capacity = TOY_AS_DICTIONARY(original)->capacity; + dictionary->entries = TOY_ALLOCATE(Toy_private_dictionary_entry, dictionary->capacity); + + for (int i = 0; i < dictionary->capacity; i++) { + dictionary->entries[i].key = TOY_TO_NULL_LITERAL; + dictionary->entries[i].value = TOY_TO_NULL_LITERAL; + } + //copy each entry for (int i = 0; i < TOY_AS_DICTIONARY(original)->capacity; i++) { if ( !TOY_IS_NULL(TOY_AS_DICTIONARY(original)->entries[i].key) ) { @@ -168,7 +181,7 @@ Toy_Literal Toy_copyLiteral(Toy_Literal original) { return original; //literally a shallow copy } - case TOY_LITERAL_ARRAY_INTERMEDIATE: { + case TOY_LITERAL_ARRAY_INTERMEDIATE: { //TODO: efficient preallocation? Toy_LiteralArray* array = TOY_ALLOCATE(Toy_LiteralArray, 1); Toy_initLiteralArray(array); @@ -184,7 +197,7 @@ Toy_Literal Toy_copyLiteral(Toy_Literal original) { return ret; } - case TOY_LITERAL_DICTIONARY_INTERMEDIATE: { + case TOY_LITERAL_DICTIONARY_INTERMEDIATE: { //TODO: efficient preallocation? Toy_LiteralArray* array = TOY_ALLOCATE(Toy_LiteralArray, 1); Toy_initLiteralArray(array); @@ -200,7 +213,7 @@ Toy_Literal Toy_copyLiteral(Toy_Literal original) { return ret; } - case TOY_LITERAL_TYPE_INTERMEDIATE: { + case TOY_LITERAL_TYPE_INTERMEDIATE: { //TODO: efficient preallocation? Toy_LiteralArray* array = TOY_ALLOCATE(Toy_LiteralArray, 1); Toy_initLiteralArray(array);