Visual Studio Code takes 13% of CPU resources due to cursor flicker



    The fun problem # 22900 this week has attracted particular attention from Github users.

    A detailed description of the problem is in the repository of the Visual Studio Code Editor ( vscode ). Open source developer Joe Liss (Jo Liss) is known as the creator of Broccoli and other free libraries. On the project page, she noticed that Visual Studio Code uses 13% of the processor’s computational resources if the window is in focus. Because of this, the battery on the laptop is wasted. What could be the reason for such a strange behavior of the program?

    Joe Liss suggested that the CPU activity is associated with rendering the cursor flicker - the cursor state changes twice a second, that is, every 500 ms (2 fps).

    To reproduce the problem, do the following steps:

    1. Close all Visual Studio Code windows.
    2. Open a new window (File → New Window).
    3. Open a new tab with an empty file (File → New Tab). The cursor is blinking.
    4. In the resource monitor, you will see a non-zero consumption of computing resources (13% on a weak laptop with OS X, about 5-7% on the powerful GNOME Shell with Wayland (Ivy Bridge Graphics)).
    5. Switch to another application window (Cmd + Tab). The cursor is no longer visible.
    6. CPU consumption by the Visual Studio Code is reduced to almost zero.

    Someone needs it, here are the Timeline records in the Developer Tools: TimelineRawData-20170321T114212.json.zip (see screenshot above).

    If you bring one frame closer, you can see that despite the flicker frequency of 2 fps, the main thread does some work at 60 fps, that is, it renders something every 16 ms.



    If you bring more closer, then you can see the concrete big work that the cursor renders at 60 frames / s. These are “Update Layer Tree” / “Paint” / “Composite Layers” periodic cycles, that is, updating the layer tree.



    The developer notes that in other macOS Sierra 10.12.3 applications, including Chrome and TextEdit, the cursor blinks without noticeable resource consumption. CPU.

    Users of the Visual Studio Code Editor can disable cursor flickering in the program. In this case, the CPU consumption is reduced to 0%. The "Update Layer Tree" / "Paint" / "Composite Layers" cycles still work, but only every 500 ms, not every 16 ms.

    "editor.cursorBlinking": "solid"

    This funny glitch in Visual Studio Code resembles the classic problem with the brake indicator in npm. In the npm version 3.5.2, with the progress indicator turned on, this operation was performed approximately 50% slower than without the indicator.

    $ rm -r node_modules
    $ npm set progress=false
    $ time npm install
    npm install19.91s user2.66s system71% cpu 31.667 total
    $ rm -r node_modules
    $ npm set progress=true
    $ time npm install
    npm install33.26s user3.19s system74% cpu 48.733 total

    What is the reason


    Of course, the consumption of CPU resources when the cursor is blinking has completely different reasons than slowing down npm with an active progress indicator. The reasons for the problems with the cursor can be guessed if you look at almost the same bug with the animation of the CSS keyframe in the Chrome browser. There, the developers write that in JavaScript the flickering cursor takes away the normal 1.2% of CPU resources, and in CSS for some reason is 6 times more, that is, 7-8%.

    The code seems to be correct:

    @keyframes monaco-cursor-blink {
    	50% {
    		opacity: 0;
    	}
    	100% {
    		opacity: 1;
    	}
    }
    .cursor-blink {
    	animation: monaco-cursor-blink 1s step-start 0s infinite;
    }

    But the problem is that the Chromium engine forcibly translates this animation at 60 fps, forcing it to perform work every 16 ms.

    So, Visual Studio Code Editor, obviously, uses the most logical approach to implement the flickering cursor function: this is a function stepwith animation of a keyframe of CSS. But this bug in Chromium has not yet been completely fixed , although it has been dragging on for more than two years. So Chrome performs a full rendering cycle every 16 ms, as it should be for 60 frames per second. Perhaps the current discussion will draw attention to the old bug - and the developers finally get their hands on it.

    Visual Studio Code Developers admittedthat this feature was originally implemented in JavaScript, but about a year ago they switched to CSS. In the current implementation, if the window is out of focus, then the animation is deactivated and there is no excessive consumption of processor resources, but the actual window is really a problem. The developers believe that in such a situation, it makes sense to go back with CSS back to JS.

    Colleagues are advised to think also about how to implement the cursor in the form of an animated gif. You can generate such a file automatically, depending on the color of the editor. True, there may be difficulty with zooming: still, raster graphics will become blurry when zooming.

    But in the end, the developers at Microsoft decided to return to the good old JS-method setInterval for cursor flicker - and the CPU consumption immediately decreased several times .

    Also popular now: