vega / vl-convert

Utilities for converting Vega-Lite specs from the command line and Python
BSD 3-Clause "New" or "Revised" License
100 stars 12 forks source link

"Fatal JavaScript out of memory" error when converting an interactive chart #112

Closed btabram closed 1 year ago

btabram commented 1 year ago

Hi, I'm aware this is quite niche but it's taken me a while to investigate this and I thought it was worth making an issue in case it saves someone else time in the future or is something which you think is worth fixing 🙂

Here's a minimal reproduction where I repeatedly create a png from a vega lite spec (5k rows) which was created with Altair, including calling chart.interactive():

import vl_convert as vlc
import json
import psutil

with open("vega.json", "r") as f:
    spec = json.load(f)

for i in range(1000):
    vlc.vegalite_to_png(spec)
    if i % 20 == 0:
        print(
            f"{i}: memory usage is {psutil.Process().memory_info().rss//1_000_000} MB"
        )

The input is vega.json.zip (zipped to upload here) and the output is:

0: memory usage is 109 MB
20: memory usage is 248 MB
40: memory usage is 351 MB
60: memory usage is 440 MB
80: memory usage is 539 MB
100: memory usage is 622 MB
120: memory usage is 715 MB
140: memory usage is 820 MB
160: memory usage is 930 MB
180: memory usage is 992 MB
200: memory usage is 1097 MB
220: memory usage is 1197 MB
240: memory usage is 1260 MB
260: memory usage is 1362 MB
280: memory usage is 1447 MB
300: memory usage is 1543 MB
320: memory usage is 1604 MB

<--- Last few GCs --->

[31153:0x148570000]    17548 ms: Scavenge (reduce) 1397.6 (1431.5) -> 1396.9 (1431.7) MB, 1.79 / 0.00 ms  (average mu = 0.264, current mu = 0.238) allocation failure;
[31153:0x148570000]    17693 ms: Scavenge (reduce) 1397.9 (1431.7) -> 1397.5 (1432.2) MB, 2.79 / 0.00 ms  (average mu = 0.264, current mu = 0.238) allocation failure;
[31153:0x148570000]    17731 ms: Scavenge (reduce) 1398.1 (1432.2) -> 1397.3 (1432.2) MB, 2.12 / 0.00 ms  (average mu = 0.264, current mu = 0.238) allocation failure;

<--- JS stacktrace --->

#
# Fatal JavaScript out of memory: Ineffective mark-compacts near heap limit
#

If I remove the "params" field (which I understand is related to interactivity) from vega.json then the memory usage is stable ~200MB. In my real usecase where there's a lot more data then I'm only able to create ~15 (different) pngs before hitting the out of memory error.

Since realising that interactivity was part of the problem I've removed the .interactive() call from my code and so the impact of this bug is minimal. The .interactive() call was a hang-over from an earlier version of my code and was no longer necessary but I hadn't expected it to cause problems.

Thanks

jonmmease commented 1 year ago

Thanks for the report and for the investigation @btabram. Glad you have a workaround! This is definitely something we should address. Ideally we'll be able to track down the memory leak (probably in Vega), but VlConvert should also track memory usage and potentially restart the runtime when it reaches a certain level to be more robust to this kind of scenario.