ifcparse: store the GlobalId index in a hash map with inline keys

byguid_ was a std::map<std::string, ...>: a red-black node plus a
heap-allocated 22-character string per rooted instance, and a lookup that
walks ~18 levels of string comparisons on a 200k-entry file.

guid_map keeps keys of up to 23 characters inline in an unordered_map node
(every valid GlobalId is 22), and routes anything longer to an ordered map
so invalid files still work. Same std::string-keyed interface as before.

Parse, C++ file constructor, on top of the previous commits:
  TXG            58 MB   1.08 s -> 1.03 s   341 -> 335 MB
  210_King      148 MB   2.80 s -> 2.72 s   836 -> 830 MB
  OKgate22      232 MB   4.25 s -> 3.94 s  1271 -> 1253 MB

This commit was written by an AI coding tool and has not been verified by
a human.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013wcN7XquTfUi4vsKQ4KchL
This commit is contained in:
Dion Moult
2026-09-11 16:17:18 +10:00
parent e0b6122d17
commit 64805b409f
6 changed files with 127 additions and 26 deletions
@@ -276,3 +276,21 @@ TEST_CASE("Batch deletion prunes surviving referencers and leaves no stale recor
}
CHECK(file.instances_by_reference(doomed_referencer.id()).empty());
}
TEST_CASE("Only a 22-character GlobalId is indexed", "[ifcparse]") {
const std::string data =
"ISO-10303-21;\nHEADER;\nFILE_DESCRIPTION((''),'2;1');\nFILE_NAME('','',(''),(''),'','','');\nFILE_SCHEMA(('IFC4'));\nENDSEC;\nDATA;\n"
"#1=IFCWALL('0YvctVUKr0kugbFTf53O9L',$,$,$,$,$,$,$,$);\n"
"#2=IFCWALL('id',$,$,$,$,$,$,$,$);\n"
"ENDSEC;\nEND-ISO-10303-21;\n";
std::string copy(data);
ifcopenshell::file file(copy.data(), (int)copy.size());
REQUIRE(file.good());
CHECK(file.instance_by_guid("0YvctVUKr0kugbFTf53O9L").id() == 1);
CHECK_THROWS(file.instance_by_guid("id"));
CHECK_THROWS(file.instance_by_guid("0YvctVUKr0kugbFTf53O9M"));
// A wall created after the open follows the same rule.
express::base wall = file.instance_by_id(2);
wall.set_attribute_value(0, std::string("1F$7lN9$r5MOA_lpAoNM52"));
CHECK(file.instance_by_guid("1F$7lN9$r5MOA_lpAoNM52").id() == 2);
}