Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hashmap._Bucket.toString is very expensive to compile #17

Open
zorael opened this issue Jan 18, 2024 · 2 comments
Open

Hashmap._Bucket.toString is very expensive to compile #17

zorael opened this issue Jan 18, 2024 · 2 comments

Comments

@zorael
Copy link

zorael commented Jan 18, 2024

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.

struct _Bucket {
hash_t hash;
StoredKeyType key;
StoredValueType value;
string toString() const {
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);
}
}

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

@ikod
Copy link
Owner

ikod commented Jan 19, 2024

Hello,

If this change

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

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

@zorael
Copy link
Author

zorael commented Jan 19, 2024

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
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants