Skip to content

Hovering over very large lists makes debugging unresponsive because results are not paged #5532

Closed

Description

@jensjoha

Describe the bug (and reproduction)

Say you have this code:

void main() {
  Uint8List data = Uint8List(268435456);
  foo(data);
}

void foo(Uint8List data) {
  print("hello data of size ${data.length}");
}

and has a breakpoint on the foo call.

On the left under "Varaibles" you'll see "Uint8List (268435456 items)" and drop-downs breaks it into smaller chunks before eventually it requests 100 elements via a variables call with option "count":100. This works well.

If instead you place your mouse over the data variable in the source code you're in for a bad time because it requests without any "count" parameter and the VM then happily does what it was asked on all 268435456 elements - eventually (on my machine) running out of memory somewhere in return elements.mapIndexed([...]).toList(); in ProtocolConverter.convertVmInstanceToVariablesList.
Until it fails (after a while) debugging is unresponsive, and the debugging session can't even be stopped (without killing the running dart debug_adapter processing).
I suspect that if we had a size that was small enough that it wouldn't cause out-of-memory on the dart side the IDE would be in for a bad time once it had to receive that data. (Okay, I couldn't help myself: Reducing it to 1mio does indeed make the IDE use lots of CPU and lots of memory. There might even be a memory leak - after doing it with 1 mio 5 times (I think - that is start a debugging session, hover, click "continue" and wait until it actually continues, start the 2nd one etc) the memory consumption of the (remote) vs code according to the chrome task manager is now 2.1+ GB...)

Expected behavior
Either it only shows the first x (100?) entries, or (preferably) it would give the same drop-downs as the variables on the left.

Please complete the following information:

Dart Code extension: 3.112.0
Flutter extension: 3.112.0 (not activated)

App: code-server
App Host: server-distro
Remote: 127.0.0.1:49363
Host Kind: server-distro
Version: linux 1.91.1

Workspace type: Dart (LSP)
Workspace name: profiling

Dart (3.9.0-edge): (my checkout)
Flutter (3.29.3): (my checkout)

Activity

  1. added
    in debuggingRelates to the debug adapter or process of running debug sessions
    on Jun 4, 2025
  2. added this to the v3.114.0 milestone on Jun 4, 2025
  3. DanTup commented on Jun 4, 2025

    @DanTup
    Member

    Thanks for the detailed info! I can reproduce this, and can see from the logs that when you perf an evaluation (hover or typing into the debug console), we don't include information required for VS Code to handle paging like we do when we return the variables for scopes (the "Variables") pane.

    // VS Code asks for scopes - returns "locals" with ref=3
    [10:27:49 AM] [DAP] [Info] ==> {"command":"scopes","arguments":{"frameId":2},"type":"request","seq":11}
    [10:27:49 AM] [DAP] [Info] <== {"seq":100,"type":"response","body":{"scopes":[{"expensive":false,"name":"Locals","presentationHint":"locals","variablesReference":3}]},"command":"scopes","request_seq":11,"success":true}
    
    // VS Code asks for variables for ref=3, result includes a response with indexedVariables=100000
    [10:27:49 AM] [DAP] [Info] ==> {"command":"variables","arguments":{"variablesReference":3,"format":{"hex":false}},"type":"request","seq":12}
    [10:27:49 AM] [DAP] [Info] <== {"seq":101,"type":"response","body":{"variables":[{"evaluateName":"data","indexedVariables":100000,"name":"data","value":"Uint8List (100000 items)","variablesReference":5}]},"command":"variables","request_seq":12,"success":true}
    
    // VS Code asks for 0-100 of the variables
    [10:27:57 AM] [DAP] [Info] ==> {"command":"variables","arguments":{"variablesReference":5,"filter":"indexed","start":0,"count":100,"format":{"hex":false}},"type":"request","seq":15}
    [10:27:57 AM] [DAP] [Info] <== {"seq":110,"type":"response","body":{"variables":[{"evaluateName":"data[0]","name":"[0]","value":"0","variablesReference":0},{"evaluateName":"data[1]","name":"[1]","value":"0","variablesReference":0},{"evaluateName":"data[2]","name":"[2]","value":"0","variablesReference":0},{"evaluateName":"data[3]","name":"[3]","value":"0","variablesReference":0},{"evaluateName":"data[4]","name":"[4]","value":"0","variablesReference":0},{"evaluateName":"data[5]","name":"[5]","value":"0","variablesReference":0},{"evaluateName":"data[6]","name":"[6]","value":"0","variablesReference":0},{"evaluateName":"data[7]","name":"[7]","value":"0","variablesReference":0},{"evaluateName":"data[8]","name":"[8]","value":"0","variablesReference":0},{"evaluateName":"data[9]","name":"[9]","value":"0","variablesReference":0},{"evaluateName":"data[10]","name":"[10]","value":"0","variablesReference":0},{"evaluateName":"data[11]","name":"[11]","value":"0","variablesReference":0},{"evaluateName":"data[12]","name":"[12]","value":"0","variablesReference":0},{"evaluateName":"data[13]","name":"[13]","value":"0","variablesReference":0},{"evaluateName":"data[14]","name":"[14]","value":"0","variablesReference":0},{"evaluateName":"data[15]","name":"[15]","value":"0","variablesReference":0},{"evaluateName":"data[16]","name":"[16]","value":"0","variablesReference":0},{"evaluateName":"data[17]","name":"[17]","value":"0","variablesReference":0},{"evaluateName":"data[18]","name":"[18]","value":"0","variablesReference":0},{"evaluateName":"data[19]","name":"[19]","value":"0","variablesReference":0},{"evaluateName":"data[20]","name":"[20]","value":"0","variablesReference":0},{"evaluateName":"data[21]","name":"[21]","value":"0","variablesReference":0},{"evaluateName":"data[22]","name":"[22]","value":"0","variablesReference":0},{"evaluateName":"data[23]","name":"[23]","value":"0","variablesReference":0},{"evaluateName":"data[24]","name":"[24]","value":"0","variablesReference":0},{"evaluateName":"data[25]","name":"[25]","value":"0","variablesReference":0},{"evaluateName":"data[26]","name":"[26]","value":"0","variablesReference":0},{"evaluateName":"data[27]","name":"[27]","value":"0","variablesReference":0},{"evaluateName":"data[28]","name":"[28]","value":"0","variablesReference":0},{"evaluateName":"data[29]","name":"[29]","value":"0","variablesReference":0},{"evaluateName":"data[30]","name":"[30]","value":"0","variablesReference":0},{"evaluateName":"data[31]","name":"[31]","value":"0","variablesReference":0},{"evaluateName":"data[32]","name":"[32]","value":"0","variablesReference":0},{"evaluateName":"data[33]","name":"[33]","value":"0","variablesReference":0},{"evaluateName":"data[34]","name":"[34]","value":"0","variablesReference":0},{"evaluateName":"data[35]","name":"[35]","value":"0","variablesReference":0},{"evaluateName":"data[36]","name":"[36]","value":"0","variablesReference":0},{"evaluateName":"data[37]","name":"[37]","value":"0","variablesReference":0},{"evaluateName":"data[38]","name":"[38]","value":"0","variablesReference":0},{"evaluateName":"data[39]","name":"[39]","value":"0","variablesReference":0},{"evaluateName":"data[40]","name":"[40]","value":"0","variablesReference":0},{"evaluateName":"data[41]","name":"[41]","value":"0","variablesReference":0},{"evaluateName":"data[42]","name":"[42]","value":"0","variablesReference":0},{"evaluateName":"data[43]","name":"[43]","value":"0","variablesReference":0},{"evaluateName":"data[44]","name":"[44]","value":"0","variablesReference":0},{"evaluateName":"data[45]","name":"[45]","value":"0","variablesReference":0},{"evaluateName":"data[46]","name":"[46]","value":"0","variablesReference":0},{"evaluateName":"data[47]","name":"[47]","value":"0","variablesReference":0},{"evaluateName":"data[48]","name":"[48]","value":"0","variablesReference":0},{"evaluateName":"data[49]","name":"[49]","value":"0","variablesReference":0},{"evaluateName":"data[50]","name":"[50]","value":"0","variablesReference":0},{"evaluateName":"data[51]","name":"[51]","value":"0","variablesReference":0},{"evaluateName":"data[52]","name":"[52]","value":"0","variablesReference":0},{"evaluateName":"data[53]","name":"[53]","value":"0","variablesReference":0},{"evaluateName":"data[54]","name":"[54]","value":"0","variablesReference":0},{"evaluateName":"data[55]","name":"[55]","value":"0","variablesReference":0},{"evaluateName":"data[56]","name":"[56]","value":"0","variablesReference":0},{"evaluateName":"data[57]","name":"[57]","value":"0","variablesReference":0},{"evaluateName":"data[58]","name":"[58]","value":"0","variablesReference":0},{"evaluateName":"data[59]","name":"[59]","value":"0","variablesReference":0},{"evaluateName":"data[60]","name":"[60]","value":"0","variablesReference":0},{"evaluateName":"data[61]","name":"[61]","value":"0","variablesReference":0},{"evaluateName":"data[62]","name":"[62]","value":"0","variablesReference":0},{"evaluateName":"data[63]","name":"[63]","value":"0","variablesReference":0},{"evaluateName":"data[64]","name":"[64]","value":"0","variablesReference":0},{"evaluateName":"data[65]","name":"[65]","value":"0","variablesReference":0},{"evaluateName":"data[66]","name":"[66]","value":"0","variablesReference":0},{"evaluateName":"data[67]","name":"[67]","value":"0","variablesReference":0},{"evaluateName":"data[68]","name":"[68]","value":"0","variablesReference":0},{"evaluateName":"data[69]","name":"[69]","value":"0","variablesReference":0},{"evaluateName":"data[70]","name":"[70]","value":"0","variablesReference":0},{"evaluateName":"data[71]","name":"[71]","value":"0","variablesReference":0},{"evaluateName":"data[72]","name":"[72]","value":"0","variablesReference":0},{"evaluateName":"data[73]","name":"[73]","value":"0","variablesReference":0},{"evaluateName":"data[74]","name":"[74]","value":"0","variablesReference":0},{"evaluateName":"data[75]","name":"[75]","value":"0","variablesReference":0},{"evaluateName":"data[76]","name":"[76]","value":"0","variablesReference":0},{"evaluateName":"data[77]","name":"[77]","value":"0","variablesReference":0},{"evaluateName":"data[78]","name":"[78]","value":"0","variablesReference":0},{"evaluateName":"data[79]","name":"[79]","value":"0","variablesReference":0},{"evaluateName":"data[80]","name":"[80]","value":"0","variablesReference":0},{"evaluateName":"data[81]","name":"[81]","value":"0","variablesReference":0},{"evaluateName":"data[82]","name":"[82]","value":"0","variablesReference":0},{"evaluateName":"data[83]","name":"[83]","value":"0","variablesReference":0},{"evaluateName":"data[84]","name":"[84]","value":"0","variablesReference":0},{"evaluateName":"data[85]","name":"[85]","value":"0","variablesReference":0},{"evaluateName":"data[86]","name":"[86]","value":"0","variablesReference":0},{"evaluateName":"data[87]","name":"[87]","value":"0","variablesReference":0},{"evaluateName":"data[88]","name":"[88]","value":"0","variablesReference":0},{"evaluateName":"data[89]","name":"[89]","value":"0","variablesReference":0},{"evaluateName":"data[90]","name":"[90]","value":"0","variablesReference":0},{"evaluateName":"data[91]","name":"[91]","value":"0","variablesReference":0},{"evaluateName":"data[92]","name":"[92]","value":"0","variablesReference":0},{"evaluateName":"data[93]","name":"[93]","value":"0","variablesReference":0},{"evaluateName":"data[94]","name":"[94]","value":"0","variablesReference":0},{"evaluateName":"data[95]","name":"[95]","value":"0","variablesReference":0},{"evaluateName":"data[96]","name":"[96]","value":"0","variablesReference":0},{"evaluateName":"data[97]","name":"[97]","value":"0","variablesReference":0},{"evaluateName":"data[98]","name":"[98]","value":"0","variablesReference":0},{"evaluateName":"data[99]","name":"[99]","value":"0","variablesReference":0}]},"command":"variables","request_seq":15,"success":true}
    
    // VS Code asks to evaluate "data", result does _not_ include indexedVariables=
    [10:28:00 AM] [DAP] [Info] ==> {"command":"evaluate","arguments":{"expression":"data","frameId":2,"context":"hover","line":5,"column":7,"format":{"hex":false}},"type":"request","seq":16}
    [10:28:00 AM] [DAP] [Info] <== {"seq":115,"type":"response","body":{"result":"Uint8List (100000 items)","variablesReference":8},"command":"evaluate","request_seq":16,"success":true}
    
    // Therefore VS Code asks for all
    [10:28:00 AM] [DAP] [Info] ==> {"command":"variables","arguments":{"variablesReference":8,"format":{"hex":false}},"type":"request","seq":17}
    [10:28:00 AM] [DAP] [Info] <== {"seq":118,"type":"response","body":{"variables":[{"evaluateName":"data[0]","name":"[0]","value":"0","variablesReference":0},{"evaluateName":"data[1]","name":"[1]","value":"0","variablesReference":0} ...
    

    Edit: The same is true for normal lists, not only Uint8List.

  4. changed the title [-]Hovering a large Uint8List makes debugging unresponsive[/-] [+]Hovering over very large lists makes debugging unresponsive because results are not paged[/+] on Jun 4, 2025
  5. DanTup commented on Jun 4, 2025

    @DanTup
    Member

    I've a fix open at https://dart-review.googlesource.com/c/sdk/+/432941. With that change, the lists are paged like this (in both Hovers and Debug Console):

    Image

  6. added
    relies on sdk changesSomething that requires changes in the Dart/Flutter SDK to ship before it will become available
    on Jun 4, 2025
  7. DanTup commented on Jun 4, 2025

    @DanTup
    Member

    Fixed by dart-lang/sdk@9756ab9. The fix will show up in a future SDK release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    in debuggingRelates to the debug adapter or process of running debug sessionsis bugrelies on sdk changesSomething that requires changes in the Dart/Flutter SDK to ship before it will become available

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions