cachetools icon indicating copy to clipboard operation
cachetools copied to clipboard

`Hashmap._Bucket.toString` is very expensive to compile

Open zorael opened this issue 1 year ago • 2 comments

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:

Screenshot_20240118_130309

zorael avatar Jan 18 '24 12:01 zorael

Hello,

If this change

string toString()() const { // <-- added ()

Will not break any - I'm ok with it.

ikod avatar Jan 19 '24 19:01 ikod

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
}

zorael avatar Jan 19 '24 21:01 zorael