Bug 16513 – Speed up TemplateInstance.findExistingInstance hash
Status
RESOLVED
Resolution
FIXED
Severity
enhancement
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2016-09-19T23:58:00Z
Last change time
2017-03-22T12:20:54Z
Keywords
pull
Assigned to
nobody
Creator
code
Comments
Comment #0 by code — 2016-09-19T23:58:41Z
We still have a few reports about extremely slow TemplateInstance.findExistingInstance performance. What can be seen in profiles is an excessive amount of TemplateInstance comparisons for lookups in the hash table that eat ~20% of the compilation time.
Maybe we're producing an unsuited hash that isn't order dependent?
Or it's just an extreme number of instances with many arguments?
Still have to investigate further, but since issue 7469 got fixed we might now hash by the mangling of the template (.getIdent) instead of doing an expensive arrayObjectMatch on RootObjects (using a "virtual" match function).
Comment #1 by code — 2016-09-20T10:13:34Z
It's the horrible hash that is causing the performance issue.
Arguments as widely different than
genericIndexOf!(CPPMethods, ushort, int, uint, long, ulong)
genericIndexOf!(VTable, ushort, int, uint, long, ulong)
produce the same hash.
From the 88.3K lookups, 7900 have the hash 1 (one).
The test code that triggered the issue contains 1K instances of
VariableDescriptor!(tonsofsimulatedobjects, SimulatedEntity, "Simulated_Object_1063")
VariableDescriptor!(tonsofsimulatedobjects, SimulatedEntity, "Simulated_Object_1064")
and lots of instances like
IsVariable!(Simulated_Object_963)
IsMemberVariable!(Simulated_Object_973)
isSomeFunction!(Simulated_Object_571)
IsVariable!(Simulated_Object_964)
IsMemberVariable!(Simulated_Object_974)
isSomeFunction!(Simulated_Object_572)
IsVariable!(Simulated_Object_966)
IsMemberVariable!(Simulated_Object_975)
isSomeFunction!(Simulated_Object_573)
all producing the same hash.
With such a crappy hash the behavior degrades back to the old linear search.
I'll try to replace this with the mangling suffix (.getIdent) instead which should be both simpler and effective, given that all mangling bugs are fixed.
Comment #2 by uplink.coder — 2016-09-20T10:40:43Z
Hash collisions will happen!
We need a way to speed up those equals compares in rootObject.
I'll look if I can find a good way to gradually remove the virtual calls.
IsVariable!(Simulated_Object_966)
IsMemberVariable!(Simulated_Object_975)
isSomeFunction!(Simulated_Object_573)
Those SHOULD produce the same hash they work on the same types!
I am of the impression that template-inlining can help here.
Comment #3 by code — 2016-09-20T10:56:56Z
Managed to speed up the test case from 1.8s to 1.2s, almost completely eliminating the lookup cost.
Still need to fix a few issues, the cppmangler thinks member variables are static, we might not want to fill the idPool with unused identifiers (would save some memory to just compute the hash), needs some more testing whether the mangling is really bijective, if so we could only hash the string and ditch the TemplateInstance.compare code.
Comment #4 by code — 2016-09-20T11:02:58Z
(In reply to uplink.coder from comment #2)
> Hash collisions will happen!
> We need a way to speed up those equals compares in rootObject.
> I'll look if I can find a good way to gradually remove the virtual calls.
This whole RootObject hashing/comparison is a kludge when we can cheaply generate a unique string.
> IsVariable!(Simulated_Object_966)
> IsMemberVariable!(Simulated_Object_975)
> isSomeFunction!(Simulated_Object_573)
>
> Those SHOULD produce the same hash they work on the same types!
Yes right, only the arguments are part of the hash.
> I am of the impression that template-inlining can help here.
True for isSomeFunction and it does work, the other 2 take alias parameters (via variadic arguments) and create one instance per object (w/ the same hash).