Skip to content

Commit

Permalink
20465: Improves performance of string interning (#216)
Browse files Browse the repository at this point in the history
  • Loading branch information
howsohazard authored Aug 9, 2024
1 parent a12e827 commit 490a68b
Show file tree
Hide file tree
Showing 29 changed files with 948 additions and 845 deletions.
2 changes: 1 addition & 1 deletion src/Amalgam/AmalgamMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ PLATFORM_MAIN_CONSOLE
if(num_strings_used > 0)
{
std::cerr << "ERROR: Num strings still in use: " << num_strings_used << std::endl;
std::vector<std::pair<std::string, int64_t>> in_use = string_intern_pool.GetNonStaticStringsInUse();
std::vector<std::pair<std::string, int64_t>> in_use = string_intern_pool.GetDynamicStringsInUse();
for(auto &[s, count] : in_use)
std::cerr << '"' << s << "\":" << count << std::endl;

Expand Down
6 changes: 3 additions & 3 deletions src/Amalgam/AssetManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ Entity *AssetManager::LoadEntityFromResourcePath(std::string &resource_path, std
new_entity->SetRoot(code, true);

EvaluableNodeReference args = EvaluableNodeReference(new_entity->evaluableNodeManager.AllocNode(ENT_ASSOC), true);
args->SetMappedChildNode(ENBISI_create_new_entity, new_entity->evaluableNodeManager.AllocNode(ENT_FALSE));
args->SetMappedChildNode(GetStringIdFromBuiltInStringId(ENBISI_create_new_entity), new_entity->evaluableNodeManager.AllocNode(ENT_FALSE));
auto call_stack = Interpreter::ConvertArgsToCallStack(args, new_entity->evaluableNodeManager);

new_entity->Execute(StringInternPool::NOT_A_STRING_ID, call_stack, false, calling_interpreter);
Expand All @@ -185,14 +185,14 @@ Entity *AssetManager::LoadEntityFromResourcePath(std::string &resource_path, std
{
if(EvaluableNode::IsAssociativeArray(metadata))
{
EvaluableNode **seed = metadata->GetMappedChildNode(ENBISI_rand_seed);
EvaluableNode **seed = metadata->GetMappedChildNode(GetStringIdFromBuiltInStringId(ENBISI_rand_seed));
if(seed != nullptr)
{
default_random_seed = EvaluableNode::ToStringPreservingOpcodeType(*seed);
new_entity->SetRandomState(default_random_seed, true);
}

EvaluableNode **version = metadata->GetMappedChildNode(ENBISI_version);
EvaluableNode **version = metadata->GetMappedChildNode(GetStringIdFromBuiltInStringId(ENBISI_version));
if(version != nullptr)
{
auto [tostr_success, version_str] = EvaluableNode::ToString(*version);
Expand Down
4 changes: 2 additions & 2 deletions src/Amalgam/AssetManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ class AssetManager
EvaluableNode en_assoc(ENT_ASSOC);
EvaluableNode en_rand_seed(ENT_STRING, entity->GetRandomState());
EvaluableNode en_version(ENT_STRING, AMALGAM_VERSION_STRING);
en_assoc.SetMappedChildNode(ENBISI_rand_seed, &en_rand_seed);
en_assoc.SetMappedChildNode(ENBISI_version, &en_version);
en_assoc.SetMappedChildNode(GetStringIdFromBuiltInStringId(ENBISI_rand_seed), &en_rand_seed);
en_assoc.SetMappedChildNode(GetStringIdFromBuiltInStringId(ENBISI_version), &en_version);

std::string metadata_extension = FILE_EXTENSION_AMLG_METADATA;
//don't reescape the path here, since it has already been done
Expand Down
457 changes: 234 additions & 223 deletions src/Amalgam/Opcodes.cpp

Large diffs are not rendered by default.

40 changes: 31 additions & 9 deletions src/Amalgam/Opcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -612,22 +612,44 @@ enum EvaluableNodeBuiltInStringId
ENBISI_FIRST_DYNAMIC_STRING
};

//returns the string id representing EvaluableNodeBuiltInStringId t
inline StringInternPool::StringID GetStringIdFromBuiltInStringId(EvaluableNodeBuiltInStringId t)
{
if(t >= ENBISI_FIRST_DYNAMIC_STRING)
return string_intern_pool.staticStringsIndexToStringID[ENBISI_NOT_A_STRING];
return string_intern_pool.staticStringsIndexToStringID[t];
}

//returns the EvaluableNodeType for a given string, ENT_NOT_A_BUILT_IN_TYPE if it isn't one
inline EvaluableNodeBuiltInStringId GetBuiltInStringIdFromStringId(StringInternPool::StringID sid)
{
auto found = string_intern_pool.staticStringIDToIndex.find(sid);
if(found == end(string_intern_pool.staticStringIDToIndex))
return ENBISI_NOT_A_STRING;

EvaluableNodeBuiltInStringId bisid = static_cast<EvaluableNodeBuiltInStringId>(found->second);
if(bisid >= ENBISI_FIRST_DYNAMIC_STRING)
return ENBISI_NOT_A_STRING;

return bisid;
}

//returns the string id representing EvaluableNodeType t
constexpr StringInternPool::StringID GetStringIdFromNodeTypeFromString(EvaluableNodeType t)
inline StringInternPool::StringID GetStringIdFromNodeType(EvaluableNodeType t)
{
if(t >= NUM_VALID_ENT_OPCODES)
return ENT_NOT_A_BUILT_IN_TYPE;
return static_cast<StringInternPool::StringID>(t + NUM_ENBISI_SPECIAL_STRING_IDS);
return string_intern_pool.staticStringsIndexToStringID[ENT_NOT_A_BUILT_IN_TYPE];
return string_intern_pool.staticStringsIndexToStringID[t + NUM_ENBISI_SPECIAL_STRING_IDS];
}

//like GetEvaluableNodeTypeFromString but uses a string id
constexpr EvaluableNodeType GetEvaluableNodeTypeFromStringId(StringInternPool::StringID sid)
//returns the EvaluableNodeType for a given string, ENT_NOT_A_BUILT_IN_TYPE if it isn't one
inline EvaluableNodeType GetEvaluableNodeTypeFromStringId(StringInternPool::StringID sid)
{
if(sid <= ENBISI_EMPTY_STRING)
auto found = string_intern_pool.staticStringIDToIndex.find(sid);
if(found == end(string_intern_pool.staticStringIDToIndex))
return ENT_NOT_A_BUILT_IN_TYPE;

size_t type_index = sid - NUM_ENBISI_SPECIAL_STRING_IDS;
size_t type_index = found->second - NUM_ENBISI_SPECIAL_STRING_IDS;
if(type_index >= NUM_VALID_ENT_OPCODES)
return ENT_NOT_A_BUILT_IN_TYPE;

Expand All @@ -647,14 +669,14 @@ inline std::string GetStringFromEvaluableNodeType(EvaluableNodeType t, bool get_
return "";
}

return string_intern_pool.GetStringFromID(GetStringIdFromNodeTypeFromString(t));
return string_intern_pool.GetStringFromID(GetStringIdFromNodeType(t));
}

//returns the enumerated type for the string
inline EvaluableNodeType GetEvaluableNodeTypeFromString(const std::string &s)
{
auto sid = string_intern_pool.GetIDFromString(s);
if(sid == string_intern_pool.NOT_A_STRING_ID || sid == string_intern_pool.EMPTY_STRING_ID)
if(sid == string_intern_pool.NOT_A_STRING_ID || sid == string_intern_pool.emptyStringId)
return ENT_NOT_A_BUILT_IN_TYPE;

return GetEvaluableNodeTypeFromStringId(sid);
Expand Down
2 changes: 1 addition & 1 deletion src/Amalgam/SeparableBoxFilterDataStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -834,7 +834,7 @@ class SeparableBoxFilterDataStore
GetValue(entity_index, feature_attribs.featureIndex).stringID, ENIVT_STRING_ID,
query_feature_index, high_accuracy);
else
return r_dist_eval.ComputeDistanceTermNominal(string_intern_pool.EMPTY_STRING_ID, ENIVT_STRING_ID,
return r_dist_eval.ComputeDistanceTermNominal(string_intern_pool.emptyStringId, ENIVT_STRING_ID,
query_feature_index, high_accuracy);
}

Expand Down
39 changes: 2 additions & 37 deletions src/Amalgam/amlg_code/test.amlg
Original file line number Diff line number Diff line change
@@ -1,39 +1,4 @@
(seq

(print (get
(list
{"a" 3}
;@(get (get (target 0) 0) "a"))
@(get (target 2) [0 "a"])
;(get (target 0) [0 "a"])
)
1)
"\n")


;(create_entities "test"
; (lambda
; ##label_target
; (list
; {"a" 1}
; @(get (get (target 2) 0) "a"))
; )
; )
;)

;(print (flatten_entity "test"))

;(print
; ;(get
; (retrieve_from_entity "test" "label_target)
; ;(list 0 "a")
; ;)
;"\n")

;(store_entity "testsave.amlg" "test")

;(call (flatten_entity "test") {new_entity "test2"})

;(load_entity "testsave.amlg" "test2")
;(print (flatten_entity "test2"))
(print (tail "abcdef" -10) "\n")
(print (tail "") "\n")
)
8 changes: 1 addition & 7 deletions src/Amalgam/entity/Entity.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,18 +348,12 @@ class Entity

StringInternPool::StringID AddContainedEntity(Entity *t, std::string id_string, std::vector<EntityWriteListener *> *write_listeners = nullptr);

inline void AddContainedEntityViaReference(Entity *t, StringInternRef &sir, std::vector<EntityWriteListener *> *write_listeners = nullptr)
inline void AddContainedEntityViaReference(Entity *t, StringRef &sir, std::vector<EntityWriteListener *> *write_listeners = nullptr)
{
StringInternPool::StringID new_sid = AddContainedEntity(t, static_cast<StringInternPool::StringID>(sir), write_listeners);
sir.SetIDAndCreateReference(new_sid);
}

inline void AddContainedEntityViaReference(Entity *t, StringInternWeakRef &siwr, std::vector<EntityWriteListener *> *write_listeners = nullptr)
{
StringInternPool::StringID new_sid = AddContainedEntity(t, static_cast<StringInternPool::StringID>(siwr), write_listeners);
siwr.SetID(new_sid);
}

//Removes the specified id from being contained by this Entity
/// write_listeners is optional, and if specified, will log the event
void RemoveContainedEntity(StringInternPool::StringID id, std::vector<EntityWriteListener *> *write_listeners = nullptr);
Expand Down
33 changes: 18 additions & 15 deletions src/Amalgam/entity/EntityManipulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,8 @@ EvaluableNodeReference EntityManipulation::DifferenceEntities(Interpreter *inter

EvaluableNode *df_assoc = enm->AllocNode(ENT_ASSOC);
difference_function->AppendOrderedChildNode(df_assoc);
df_assoc->SetMappedChildNode(ENBISI__, nullptr);
df_assoc->SetMappedChildNode(ENBISI_new_entity, nullptr);
df_assoc->SetMappedChildNode(GetStringIdFromBuiltInStringId(ENBISI__), nullptr);
df_assoc->SetMappedChildNode(GetStringIdFromBuiltInStringId(ENBISI_new_entity), nullptr);

//find entities that match up, and if no difference, then can shortcut the function
std::vector<Entity *> top_entities_identical;
Expand All @@ -272,8 +272,8 @@ EvaluableNodeReference EntityManipulation::DifferenceEntities(Interpreter *inter
{
EvaluableNode *clone_entity = enm->AllocNode(ENT_CLONE_ENTITIES);
difference_function->AppendOrderedChildNode(clone_entity);
clone_entity->AppendOrderedChildNode(enm->AllocNode(ENT_SYMBOL, ENBISI__));
clone_entity->AppendOrderedChildNode(enm->AllocNode(ENT_SYMBOL, ENBISI_new_entity));
clone_entity->AppendOrderedChildNode(enm->AllocNode(ENT_SYMBOL, GetStringIdFromBuiltInStringId(ENBISI__)));
clone_entity->AppendOrderedChildNode(enm->AllocNode(ENT_SYMBOL, GetStringIdFromBuiltInStringId(ENBISI_new_entity)));
delete root_merged;
return EvaluableNodeReference(difference_function, true);
}
Expand All @@ -282,9 +282,11 @@ EvaluableNodeReference EntityManipulation::DifferenceEntities(Interpreter *inter
// (assign "new_entity" (first (create_entities new_entity
EvaluableNode *assign_new_entity = enm->AllocNode(ENT_ASSIGN);
difference_function->AppendOrderedChildNode(assign_new_entity);
assign_new_entity->AppendOrderedChildNode(enm->AllocNode(ENT_STRING, ENBISI_new_entity));
assign_new_entity->AppendOrderedChildNode(enm->AllocNode(ENT_STRING,
GetStringIdFromBuiltInStringId(ENBISI_new_entity)));
EvaluableNode *create_root_entity = enm->AllocNode(ENT_CREATE_ENTITIES);
create_root_entity->AppendOrderedChildNode(enm->AllocNode(ENT_SYMBOL, ENBISI_new_entity));
create_root_entity->AppendOrderedChildNode(enm->AllocNode(ENT_SYMBOL,
GetStringIdFromBuiltInStringId(ENBISI_new_entity)));
EvaluableNode *first_of_create_entity = enm->AllocNode(ENT_FIRST);
first_of_create_entity->AppendOrderedChildNode(create_root_entity);
assign_new_entity->AppendOrderedChildNode(first_of_create_entity);
Expand All @@ -301,8 +303,8 @@ EvaluableNodeReference EntityManipulation::DifferenceEntities(Interpreter *inter
EvaluableNode *edac_assoc = enm->AllocNode(ENT_ASSOC);
entity_difference_apply_call->AppendOrderedChildNode(edac_assoc);
EvaluableNode *get_entity_code = enm->AllocNode(ENT_RETRIEVE_ENTITY_ROOT);
edac_assoc->SetMappedChildNode(ENBISI__, get_entity_code);
get_entity_code->AppendOrderedChildNode(enm->AllocNode(ENT_SYMBOL, ENBISI__));
edac_assoc->SetMappedChildNode(GetStringIdFromBuiltInStringId(ENBISI__), get_entity_code);
get_entity_code->AppendOrderedChildNode(enm->AllocNode(ENT_SYMBOL, GetStringIdFromBuiltInStringId(ENBISI__)));

//apply difference function for root entities
// make sure to make a copy of each root so don't end up with mixed entity nodes
Expand All @@ -322,12 +324,12 @@ EvaluableNodeReference EntityManipulation::DifferenceEntities(Interpreter *inter
// )
EvaluableNode *src_id_list = GetTraversalIDPathFromAToB(enm, entity2, entity_to_create);
EvaluableNode *src_append = enm->AllocNode(ENT_APPEND);
src_append->AppendOrderedChildNode(enm->AllocNode(ENT_SYMBOL, ENBISI__));
src_append->AppendOrderedChildNode(enm->AllocNode(ENT_SYMBOL, GetStringIdFromBuiltInStringId(ENBISI__)));
src_append->AppendOrderedChildNode(src_id_list);

EvaluableNode *dest_id_list = enm->DeepAllocCopy(src_id_list);
EvaluableNode *dest_append = enm->AllocNode(ENT_APPEND);
dest_append->AppendOrderedChildNode(enm->AllocNode(ENT_SYMBOL, ENBISI_new_entity));
dest_append->AppendOrderedChildNode(enm->AllocNode(ENT_SYMBOL, GetStringIdFromBuiltInStringId(ENBISI_new_entity)));
dest_append->AppendOrderedChildNode(dest_id_list);

EvaluableNode *create_entity = enm->AllocNode(ENT_CREATE_ENTITIES);
Expand Down Expand Up @@ -369,7 +371,7 @@ EvaluableNodeReference EntityManipulation::DifferenceEntities(Interpreter *inter
call_diff->AppendOrderedChildNode(call_assoc);

EvaluableNode *entity_code = enm->AllocNode(ENT_RETRIEVE_ENTITY_ROOT);
call_assoc->SetMappedChildNode(ENBISI__, entity_code);
call_assoc->SetMappedChildNode(GetStringIdFromBuiltInStringId(ENBISI__), entity_code);
entity_code->AppendOrderedChildNode(src_append);
}
}
Expand All @@ -387,20 +389,20 @@ EvaluableNodeReference EntityManipulation::DifferenceEntities(Interpreter *inter

EvaluableNode *src_id_list = GetTraversalIDPathFromAToB(enm, entity2, entity_to_clone);
EvaluableNode *src_append = enm->AllocNode(ENT_APPEND);
src_append->AppendOrderedChildNode(enm->AllocNode(ENT_SYMBOL, ENBISI__));
src_append->AppendOrderedChildNode(enm->AllocNode(ENT_SYMBOL, GetStringIdFromBuiltInStringId(ENBISI__)));
src_append->AppendOrderedChildNode(src_id_list);

EvaluableNode *dest_id_list = enm->DeepAllocCopy(src_id_list);
EvaluableNode *dest_append = enm->AllocNode(ENT_APPEND);
dest_append->AppendOrderedChildNode(enm->AllocNode(ENT_SYMBOL, ENBISI_new_entity));
dest_append->AppendOrderedChildNode(enm->AllocNode(ENT_SYMBOL, GetStringIdFromBuiltInStringId(ENBISI_new_entity)));
dest_append->AppendOrderedChildNode(dest_id_list);

clone_entity->AppendOrderedChildNode(src_append);
clone_entity->AppendOrderedChildNode(dest_append);
}

//add new_entity to return value of let statement to return the newly created id
difference_function->AppendOrderedChildNode(enm->AllocNode(ENT_SYMBOL, ENBISI_new_entity));
difference_function->AppendOrderedChildNode(enm->AllocNode(ENT_SYMBOL, GetStringIdFromBuiltInStringId(ENBISI_new_entity)));

delete root_merged;

Expand Down Expand Up @@ -630,7 +632,8 @@ void EntityManipulation::MergeContainedEntities(EntitiesMergeMethod *mm, Entity
RecursivelyRenameAllEntityReferences(merged_entity, entities_renamed);
}

Entity *EntityManipulation::MutateEntity(Interpreter *interpreter, Entity *entity, double mutation_rate, CompactHashMap<StringInternPool::StringID, double> *mutation_weights, CompactHashMap<EvaluableNodeType, double> *operation_type)
Entity *EntityManipulation::MutateEntity(Interpreter *interpreter, Entity *entity, double mutation_rate,
CompactHashMap<EvaluableNodeBuiltInStringId, double> *mutation_weights, CompactHashMap<EvaluableNodeType, double> *operation_type)
{
if(entity == nullptr)
return nullptr;
Expand Down
Loading

0 comments on commit 490a68b

Please sign in to comment.