dlang / visuald

Visual D - Visual Studio extension for the D programming language
http://rainers.github.io/visuald/visuald/StartPage.html
Boost Software License 1.0
288 stars 70 forks source link

__debug[Overview/Expanded/StringView] cause extremely slow debug performance #274

Open TurkeyMan opened 2 months ago

TurkeyMan commented 2 months ago

Hey there!

Today I added some __debug[...] functions to some small structs, defined like this:

    auto __debugOverview() => getString;
    auto __debugExpanded() => getString;
    auto __debugStringView() => getString;

After adding them, the debugger performance takes a massive blow. It takes 10s of seconds after hovering over an instance of this struct (or any aggregate that contains this struct) to pop up a value. Pressing F10 (step) takes 10s of seconds if there's one anywhere near the current scope. Like, if there's none in sight, debug performance is normal, but if I step into a function where one is present, it takes 10s of seconds to step, even if I'm in an outer scope, and this type is only declared at some deep inner scope that I haven't reached yet. It looks like all locals in a function have been flattened out at the top scope, but it seems to be evaluating them long before their lifetime has begin. Any ideas?

I used to use these __debug functions years ago, and they worked well. Something seems to have changed.

rainers commented 2 months ago

Hi. I just tried it with implementing getString() on a simple struct as forwarding to toString(), that didn't seem to trigger the issue (VS 17.11, __debugOverview seems fine, the others don't seem to work as expected, though). Is your getString() anything more involved than that?

What compiler version are you using (I tried dmd 2.108 and 2.109)? I suspect that there might be some incompatibility in the garbage collector that might cause these issues. While executing the __debug functions, the GC is normally replaced with a simple region allocator to not change the state of the normal GC, but that might cause issues e.g. if getString caches data. You can disable switching to the region allocator by unchecking "Switch GC while executing debugger functions" on the Debugger->Mago options page. Does this change the behavior?

TurkeyMan commented 2 months ago

getString() is insidiously simple:

    const(char)[] toString() const pure nothrow @nogc
    {
        return ptr[0 .. length()];
    }

    const(char)* ptr;

    size_t length() const pure nothrow @nogc
    {
        ushort len = ptr[-1];
        if (len < 128)
            return len;
        return ((len << 7) & 0x7F) | (ptr[-2] & 0x7F);
    }

This compact string type just stores the length in the bytes before the pointer.

It's DMD 2.107.1. My app better-c, so there's no garbage being created.

TurkeyMan commented 2 months ago

Also, did you see this: image

When I use the update button to check for DMD updates, it's been saying unavailable lately... maybe the DMD guys changed the URL pattern?

TurkeyMan commented 2 months ago

Okay, so I was trying to isolate what may be affecting it and I rebooted my computer to freshen up all the processes. The __debug* functions seem to be working normally now. Also, goto-definition has started working again. So perhaps whatever reason it is that keeps causing goto-defintion to stop working was also affecting this.

I notice that Visual Studio these days likes to pop up little notification messages on the lower right corner... I wonder if VisualD can also tap into that API to pop up performance messages, and notify about things like the autocomplete engine not responding, or debugger not responding?

rainers commented 2 months ago

When I use the update button to check for DMD updates, it's been saying unavailable lately... maybe the DMD guys changed the URL pattern?

Yes, I noticed too when trying to reproduce the problem here. I'll have to investigate...

So perhaps whatever reason it is that keeps causing goto-defintion to stop working was also affecting this.

I recently experienced the dmdserver process eating most of he 32 GB of RAM and getting rather slow. I suspect that false pointer issues caused the GC to get into trouble. Maybe this happened to you, too.

I notice that Visual Studio these days likes to pop up little notification messages on the lower right corner.

Do you mean the reminders for refreshing your license? I'm not aware of an API for these. Visual D displays notifications at the top (e.g. for showing updates). That's where Visual Studio already warns sometimes about Visual D being slow (I suspect because it is running a longer garbage collection).

rainers commented 1 month ago

When I use the update button to check for DMD updates, it's been saying unavailable lately... maybe the DMD guys changed the URL pattern?

There was a change in the answer received from the server, should be fixed with https://github.com/dlang/visuald/releases/tag/v1.4.0-rc2