cachetools
cachetools copied to clipboard
`Hashmap._Bucket.toString` is very expensive to compile
EndeavourOS/Arch x86_64, dmd 2.107-beta.1, ldc 1.36.0.
I'm profiling the compilation process of my project which uses requests
, which in turn uses cachetools
.
In an empty app.d
that only imports requests
, HashMap._Bucket.toString()
takes 100 milliseconds to compile, or about one third of the whole compilation process (excluding compiler start-up). It is not a template so it is always compiled.
https://github.com/ikod/cachetools/blob/adc3d53b7bfa459a224b097abf5736855ebc0b5d/source/cachetools/containers/hashmap.d#L108-L121
We can't easily make std.format.format
cheaper, but can we at least make toString
a template? I have no use for it myself and I'd like to avoid the 100ms.
struct _Bucket {
hash_t hash;
StoredKeyType key;
StoredValueType value;
string toString()() const { // <-- added ()
import std.format;
return "%s, hash: %0x,key: %s, value: %s".format([
EMPTY_HASH: "free",
DELETED_HASH: "deleted",
ALLOCATED_HASH: "allocated"
][cast(long)(hash & TYPE_MASK)], hash, key, value);
}
}
The example empty file:
import requests;
void main() {}
Profile viewed in tracy:
Hello,
If this change
string toString()() const { // <-- added ()
Will not break any - I'm ok with it.
It can technically break things that take the address of the function. I'm honestly not sure what the use-case for that would be though.
struct Foo
{
static string toString() { return "not template"; }
static string toString2()() { return "template"; }
}
void main()
{
writeln(Foo.toString());
writeln(Foo.toString2()); // called the same way, transparent change
auto toString = &Foo.toString;
auto toString2 = &Foo.toString2!(); // requires extra !() to compile
}