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

chore: replace vm.Script with vm.compileFunction #12205

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

rthreei
Copy link

@rthreei rthreei commented Dec 31, 2021

Summary

Memory leak is alleviated with vm.compileFunction.

Related to #11956

Inspired by earlier work done earlier #10586

Test plan

Change is covered by existing tests. Below is a before and after of heap usage against a trivial reproduction.

Before (against main branch):

% yarn jest --runInBand --logHeapUsage reproduce
 PASS  reproduce/a19.test.js (49 MB heap size)
 PASS  reproduce/a156.test.js (49 MB heap size)
 PASS  reproduce/a58.test.js (56 MB heap size)
 PASS  reproduce/a39.test.js (55 MB heap size)
 PASS  reproduce/a89.test.js (62 MB heap size)
 PASS  reproduce/a173.test.js (62 MB heap size)
 PASS  reproduce/a190.test.js (69 MB heap size)
 PASS  reproduce/a4.test.js (50 MB heap size)
 PASS  reproduce/a50.test.js (57 MB heap size)
 PASS  reproduce/a169.test.js (58 MB heap size)
 PASS  reproduce/a55.test.js (60 MB heap size)
 PASS  reproduce/a131.test.js (66 MB heap size)
 PASS  reproduce/a179.test.js (73 MB heap size)
 PASS  reproduce/a105.test.js (71 MB heap size)
 PASS  reproduce/a159.test.js (77 MB heap size)
 PASS  reproduce/a111.test.js (77 MB heap size)
 PASS  reproduce/a168.test.js (84 MB heap size)
 PASS  reproduce/a14.test.js (83 MB heap size)
 PASS  reproduce/a41.test.js (90 MB heap size)
 PASS  reproduce/a44.test.js (89 MB heap size)
 PASS  reproduce/a162.test.js (96 MB heap size)
 PASS  reproduce/a98.test.js (95 MB heap size)
 PASS  reproduce/a.test.js (102 MB heap size)
 PASS  reproduce/a16.test.js (101 MB heap size)
 PASS  reproduce/a46.test.js (108 MB heap size)
 PASS  reproduce/a75.test.js (107 MB heap size)
 PASS  reproduce/a91.test.js (95 MB heap size)
 PASS  reproduce/a7.test.js (102 MB heap size)
 PASS  reproduce/a76.test.js (101 MB heap size)
 PASS  reproduce/a49.test.js (108 MB heap size)
 PASS  reproduce/a141.test.js (109 MB heap size)
 PASS  reproduce/a67.test.js (115 MB heap size)
 PASS  reproduce/a135.test.js (115 MB heap size)
 PASS  reproduce/a17.test.js (122 MB heap size)
 PASS  reproduce/a116.test.js (121 MB heap size)
 PASS  reproduce/a129.test.js (128 MB heap size)
 PASS  reproduce/a107.test.js (127 MB heap size)
 PASS  reproduce/a117.test.js (134 MB heap size)
 PASS  reproduce/a30.test.js (133 MB heap size)
 PASS  reproduce/a177.test.js (140 MB heap size)
 PASS  reproduce/a92.test.js (140 MB heap size)
 PASS  reproduce/a32.test.js (146 MB heap size)
 PASS  reproduce/a166.test.js (146 MB heap size)
 PASS  reproduce/a83.test.js (153 MB heap size)
 PASS  reproduce/a10.test.js (152 MB heap size)
 PASS  reproduce/a45.test.js (158 MB heap size)
 PASS  reproduce/a9.test.js (158 MB heap size)
 PASS  reproduce/a61.test.js (165 MB heap size)
 PASS  reproduce/a79.test.js (164 MB heap size)
 PASS  reproduce/a24.test.js (171 MB heap size)
 PASS  reproduce/a165.test.js (170 MB heap size)
 PASS  reproduce/a64.test.js (177 MB heap size)
 PASS  reproduce/a29.test.js (176 MB heap size)
 PASS  reproduce/a80.test.js (183 MB heap size)
 PASS  reproduce/a181.test.js (183 MB heap size)
 PASS  reproduce/a167.test.js (190 MB heap size)
 PASS  reproduce/a123.test.js (189 MB heap size)
 PASS  reproduce/a149.test.js (196 MB heap size)
 PASS  reproduce/a182.test.js (195 MB heap size)
 PASS  reproduce/a62.test.js (202 MB heap size)
 PASS  reproduce/a26.test.js (202 MB heap size)
 PASS  reproduce/a136.test.js (208 MB heap size)
 PASS  reproduce/a97.test.js (208 MB heap size)
 PASS  reproduce/a134.test.js (214 MB heap size)
 PASS  reproduce/a25.test.js (214 MB heap size)
 PASS  reproduce/a84.test.js (220 MB heap size)
 PASS  reproduce/a171.test.js (220 MB heap size)
 PASS  reproduce/a161.test.js (226 MB heap size)
 PASS  reproduce/a178.test.js (226 MB heap size)
 PASS  reproduce/a31.test.js (233 MB heap size)
 PASS  reproduce/a128.test.js (232 MB heap size)
 PASS  reproduce/a121.test.js (238 MB heap size)
 PASS  reproduce/a42.test.js (238 MB heap size)
 PASS  reproduce/a20.test.js (245 MB heap size)
 PASS  reproduce/a115.test.js (244 MB heap size)
 PASS  reproduce/a183.test.js (251 MB heap size)
 PASS  reproduce/a59.test.js (250 MB heap size)
 PASS  reproduce/a158.test.js (257 MB heap size)
 PASS  reproduce/a82.test.js (256 MB heap size)
 PASS  reproduce/a5.test.js (263 MB heap size)
 PASS  reproduce/a148.test.js (263 MB heap size)
 PASS  reproduce/a150.test.js (269 MB heap size)
 PASS  reproduce/a140.test.js (269 MB heap size)
 PASS  reproduce/a23.test.js (275 MB heap size)
 PASS  reproduce/a104.test.js (275 MB heap size)
 PASS  reproduce/a48.test.js (282 MB heap size)
 PASS  reproduce/a93.test.js (281 MB heap size)
 PASS  reproduce/a86.test.js (288 MB heap size)
 PASS  reproduce/a127.test.js (287 MB heap size)
 PASS  reproduce/a1.test.js (294 MB heap size)
 PASS  reproduce/a68.test.js (293 MB heap size)
 PASS  reproduce/a78.test.js (300 MB heap size)
 PASS  reproduce/a56.test.js (299 MB heap size)
 PASS  reproduce/a34.test.js (306 MB heap size)
 PASS  reproduce/a189.test.js (306 MB heap size)
 PASS  reproduce/a139.test.js (312 MB heap size)
 PASS  reproduce/a193.test.js (198 MB heap size)
 PASS  reproduce/a151.test.js (205 MB heap size)
 PASS  reproduce/a40.test.js (212 MB heap size)
 PASS  reproduce/a77.test.js (210 MB heap size)
 PASS  reproduce/a96.test.js (212 MB heap size)
 PASS  reproduce/a36.test.js (219 MB heap size)
 PASS  reproduce/a118.test.js (218 MB heap size)
 PASS  reproduce/a108.test.js (225 MB heap size)
 PASS  reproduce/a37.test.js (225 MB heap size)
 PASS  reproduce/a196.test.js (232 MB heap size)
 PASS  reproduce/a184.test.js (231 MB heap size)
 PASS  reproduce/a147.test.js (238 MB heap size)
 PASS  reproduce/a164.test.js (238 MB heap size)
 PASS  reproduce/a174.test.js (244 MB heap size)
 PASS  reproduce/a188.test.js (244 MB heap size)
 PASS  reproduce/a198.test.js (250 MB heap size)
 PASS  reproduce/a22.test.js (250 MB heap size)
 PASS  reproduce/a133.test.js (257 MB heap size)
 PASS  reproduce/a132.test.js (257 MB heap size)
 PASS  reproduce/a200.test.js (264 MB heap size)
 PASS  reproduce/a176.test.js (264 MB heap size)
 PASS  reproduce/a187.test.js (271 MB heap size)
 PASS  reproduce/a72.test.js (270 MB heap size)
 PASS  reproduce/a145.test.js (276 MB heap size)
 PASS  reproduce/a126.test.js (276 MB heap size)
 PASS  reproduce/a87.test.js (282 MB heap size)
 PASS  reproduce/a47.test.js (282 MB heap size)
 PASS  reproduce/a185.test.js (289 MB heap size)
 PASS  reproduce/a3.test.js (288 MB heap size)
 PASS  reproduce/a53.test.js (295 MB heap size)
 PASS  reproduce/a199.test.js (294 MB heap size)
 PASS  reproduce/a43.test.js (301 MB heap size)
 PASS  reproduce/a142.test.js (300 MB heap size)
 PASS  reproduce/a88.test.js (307 MB heap size)
 PASS  reproduce/a120.test.js (306 MB heap size)
 PASS  reproduce/a21.test.js (313 MB heap size)
 PASS  reproduce/a180.test.js (312 MB heap size)
 PASS  reproduce/a74.test.js (319 MB heap size)
 PASS  reproduce/a90.test.js (319 MB heap size)
 PASS  reproduce/a52.test.js (325 MB heap size)
 PASS  reproduce/a143.test.js (325 MB heap size)
 PASS  reproduce/a153.test.js (331 MB heap size)
 PASS  reproduce/a66.test.js (331 MB heap size)
 PASS  reproduce/a114.test.js (338 MB heap size)
 PASS  reproduce/a192.test.js (337 MB heap size)
 PASS  reproduce/a197.test.js (344 MB heap size)
 PASS  reproduce/a163.test.js (343 MB heap size)
 PASS  reproduce/a155.test.js (350 MB heap size)
 PASS  reproduce/a54.test.js (349 MB heap size)
 PASS  reproduce/a137.test.js (356 MB heap size)
 PASS  reproduce/a154.test.js (355 MB heap size)
 PASS  reproduce/a18.test.js (362 MB heap size)
 PASS  reproduce/a186.test.js (362 MB heap size)
 PASS  reproduce/a109.test.js (368 MB heap size)
 PASS  reproduce/a119.test.js (368 MB heap size)
 PASS  reproduce/a73.test.js (374 MB heap size)
 PASS  reproduce/a63.test.js (374 MB heap size)
 PASS  reproduce/a172.test.js (380 MB heap size)
 PASS  reproduce/a11.test.js (380 MB heap size)
 PASS  reproduce/a57.test.js (386 MB heap size)
 PASS  reproduce/a2.test.js (386 MB heap size)
 PASS  reproduce/a85.test.js (392 MB heap size)
 PASS  reproduce/a194.test.js (392 MB heap size)
 PASS  reproduce/a71.test.js (398 MB heap size)
 PASS  reproduce/a170.test.js (398 MB heap size)
 PASS  reproduce/a102.test.js (405 MB heap size)
 PASS  reproduce/a12.test.js (404 MB heap size)
 PASS  reproduce/a60.test.js (411 MB heap size)
 PASS  reproduce/a103.test.js (410 MB heap size)
 PASS  reproduce/a70.test.js (417 MB heap size)
 PASS  reproduce/a125.test.js (416 MB heap size)
 PASS  reproduce/a6.test.js (306 MB heap size)
 PASS  reproduce/a152.test.js (313 MB heap size)
 PASS  reproduce/a106.test.js (320 MB heap size)
 PASS  reproduce/a65.test.js (318 MB heap size)
 PASS  reproduce/a38.test.js (324 MB heap size)
 PASS  reproduce/a28.test.js (324 MB heap size)
 PASS  reproduce/a81.test.js (331 MB heap size)
 PASS  reproduce/a138.test.js (331 MB heap size)
 PASS  reproduce/a191.test.js (337 MB heap size)
 PASS  reproduce/a99.test.js (337 MB heap size)
 PASS  reproduce/a33.test.js (344 MB heap size)
 PASS  reproduce/a122.test.js (344 MB heap size)
 PASS  reproduce/a15.test.js (350 MB heap size)
 PASS  reproduce/a101.test.js (349 MB heap size)
 PASS  reproduce/a8.test.js (356 MB heap size)
 PASS  reproduce/a27.test.js (356 MB heap size)
 PASS  reproduce/a144.test.js (362 MB heap size)
 PASS  reproduce/a110.test.js (362 MB heap size)
 PASS  reproduce/a100.test.js (368 MB heap size)
 PASS  reproduce/a124.test.js (368 MB heap size)
 PASS  reproduce/a95.test.js (374 MB heap size)
 PASS  reproduce/a160.test.js (374 MB heap size)
 PASS  reproduce/a13.test.js (381 MB heap size)
 PASS  reproduce/a112.test.js (380 MB heap size)
 PASS  reproduce/a195.test.js (387 MB heap size)
 PASS  reproduce/a94.test.js (386 MB heap size)
 PASS  reproduce/a113.test.js (393 MB heap size)
 PASS  reproduce/a157.test.js (392 MB heap size)
 PASS  reproduce/a69.test.js (399 MB heap size)
 PASS  reproduce/a130.test.js (398 MB heap size)
 PASS  reproduce/a175.test.js (405 MB heap size)
 PASS  reproduce/a51.test.js (405 MB heap size)
 PASS  reproduce/a35.test.js (411 MB heap size)
 PASS  reproduce/a146.test.js (411 MB heap size)

Test Suites: 201 passed, 201 total
Tests:       201 passed, 201 total
Snapshots:   0 total
Time:        19.276 s

After (against this branch):

% yarn jest --runInBand --logHeapUsage reproduce
 PASS  reproduce/a19.test.js (49 MB heap size)
 PASS  reproduce/a168.test.js (55 MB heap size)
 PASS  reproduce/a179.test.js (53 MB heap size)
 PASS  reproduce/a169.test.js (58 MB heap size)
 PASS  reproduce/a190.test.js (58 MB heap size)
 PASS  reproduce/a41.test.js (63 MB heap size)
 PASS  reproduce/a156.test.js (63 MB heap size)
 PASS  reproduce/a14.test.js (40 MB heap size)
 PASS  reproduce/a111.test.js (46 MB heap size)
 PASS  reproduce/a135.test.js (52 MB heap size)
 PASS  reproduce/a150.test.js (50 MB heap size)
 PASS  reproduce/a147.test.js (55 MB heap size)
 PASS  reproduce/a107.test.js (55 MB heap size)
 PASS  reproduce/a140.test.js (61 MB heap size)
 PASS  reproduce/a127.test.js (61 MB heap size)
 PASS  reproduce/a37.test.js (67 MB heap size)
 PASS  reproduce/a46.test.js (66 MB heap size)
 PASS  reproduce/a91.test.js (72 MB heap size)
 PASS  reproduce/a44.test.js (72 MB heap size)
 PASS  reproduce/a118.test.js (77 MB heap size)
 PASS  reproduce/a9.test.js (82 MB heap size)
 PASS  reproduce/a79.test.js (82 MB heap size)
 PASS  reproduce/a80.test.js (87 MB heap size)
 PASS  reproduce/a177.test.js (88 MB heap size)
 PASS  reproduce/a59.test.js (93 MB heap size)
 PASS  reproduce/a162.test.js (92 MB heap size)
 PASS  reproduce/a68.test.js (98 MB heap size)
 PASS  reproduce/a75.test.js (98 MB heap size)
 PASS  reproduce/a139.test.js (103 MB heap size)
 PASS  reproduce/a165.test.js (108 MB heap size)
 PASS  reproduce/a29.test.js (108 MB heap size)
 PASS  reproduce/a42.test.js (113 MB heap size)
 PASS  reproduce/a96.test.js (114 MB heap size)
 PASS  reproduce/a184.test.js (119 MB heap size)
 PASS  reproduce/a171.test.js (119 MB heap size)
 PASS  reproduce/a199.test.js (125 MB heap size)
 PASS  reproduce/a98.test.js (125 MB heap size)
 PASS  reproduce/a31.test.js (130 MB heap size)
 PASS  reproduce/a16.test.js (130 MB heap size)
 PASS  reproduce/a39.test.js (135 MB heap size)
 PASS  reproduce/a131.test.js (43 MB heap size)
 PASS  reproduce/a121.test.js (48 MB heap size)
 PASS  reproduce/a153.test.js (54 MB heap size)
 PASS  reproduce/a76.test.js (52 MB heap size)
 PASS  reproduce/a183.test.js (57 MB heap size)
 PASS  reproduce/a23.test.js (58 MB heap size)
 PASS  reproduce/a104.test.js (64 MB heap size)
 PASS  reproduce/a67.test.js (63 MB heap size)
 PASS  reproduce/a163.test.js (68 MB heap size)
 PASS  reproduce/a26.test.js (68 MB heap size)
 PASS  reproduce/a18.test.js (74 MB heap size)
 PASS  reproduce/a196.test.js (79 MB heap size)
 PASS  reproduce/a172.test.js (78 MB heap size)
 PASS  reproduce/a124.test.js (84 MB heap size)
 PASS  reproduce/a2.test.js (84 MB heap size)
 PASS  reproduce/a95.test.js (89 MB heap size)
 PASS  reproduce/a112.test.js (90 MB heap size)
 PASS  reproduce/a94.test.js (95 MB heap size)
 PASS  reproduce/a12.test.js (96 MB heap size)
 PASS  reproduce/a174.test.js (101 MB heap size)
 PASS  reproduce/a.test.js (101 MB heap size)
 PASS  reproduce/a64.test.js (106 MB heap size)
 PASS  reproduce/a117.test.js (106 MB heap size)
 PASS  reproduce/a128.test.js (111 MB heap size)
 PASS  reproduce/a181.test.js (117 MB heap size)
 PASS  reproduce/a115.test.js (116 MB heap size)
 PASS  reproduce/a5.test.js (122 MB heap size)
 PASS  reproduce/a32.test.js (122 MB heap size)
 PASS  reproduce/a22.test.js (127 MB heap size)
 PASS  reproduce/a133.test.js (128 MB heap size)
 PASS  reproduce/a132.test.js (133 MB heap size)
 PASS  reproduce/a182.test.js (133 MB heap size)
 PASS  reproduce/a58.test.js (138 MB heap size)
 PASS  reproduce/a159.test.js (42 MB heap size)
 PASS  reproduce/a197.test.js (48 MB heap size)
 PASS  reproduce/a86.test.js (53 MB heap size)
 PASS  reproduce/a62.test.js (52 MB heap size)
 PASS  reproduce/a72.test.js (57 MB heap size)
 PASS  reproduce/a36.test.js (58 MB heap size)
 PASS  reproduce/a137.test.js (63 MB heap size)
 PASS  reproduce/a136.test.js (62 MB heap size)
 PASS  reproduce/a126.test.js (68 MB heap size)
 PASS  reproduce/a45.test.js (68 MB heap size)
 PASS  reproduce/a109.test.js (73 MB heap size)
 PASS  reproduce/a110.test.js (78 MB heap size)
 PASS  reproduce/a78.test.js (78 MB heap size)
 PASS  reproduce/a185.test.js (83 MB heap size)
 PASS  reproduce/a125.test.js (84 MB heap size)
 PASS  reproduce/a69.test.js (89 MB heap size)
 PASS  reproduce/a130.test.js (90 MB heap size)
 PASS  reproduce/a120.test.js (95 MB heap size)
 PASS  reproduce/a106.test.js (95 MB heap size)
 PASS  reproduce/a65.test.js (101 MB heap size)
 PASS  reproduce/a81.test.js (101 MB heap size)
 PASS  reproduce/a180.test.js (107 MB heap size)
 PASS  reproduce/a74.test.js (107 MB heap size)
 PASS  reproduce/a191.test.js (112 MB heap size)
 PASS  reproduce/a7.test.js (112 MB heap size)
 PASS  reproduce/a188.test.js (117 MB heap size)
 PASS  reproduce/a20.test.js (117 MB heap size)
 PASS  reproduce/a198.test.js (123 MB heap size)
 PASS  reproduce/a143.test.js (128 MB heap size)
 PASS  reproduce/a66.test.js (127 MB heap size)
 PASS  reproduce/a148.test.js (133 MB heap size)
 PASS  reproduce/a151.test.js (133 MB heap size)
 PASS  reproduce/a50.test.js (138 MB heap size)
 PASS  reproduce/a4.test.js (41 MB heap size)
 PASS  reproduce/a15.test.js (47 MB heap size)
 PASS  reproduce/a176.test.js (52 MB heap size)
 PASS  reproduce/a83.test.js (50 MB heap size)
 PASS  reproduce/a8.test.js (55 MB heap size)
 PASS  reproduce/a155.test.js (57 MB heap size)
 PASS  reproduce/a108.test.js (62 MB heap size)
 PASS  reproduce/a1.test.js (61 MB heap size)
 PASS  reproduce/a144.test.js (66 MB heap size)
 PASS  reproduce/a87.test.js (71 MB heap size)
 PASS  reproduce/a11.test.js (71 MB heap size)
 PASS  reproduce/a35.test.js (76 MB heap size)
 PASS  reproduce/a170.test.js (77 MB heap size)
 PASS  reproduce/a13.test.js (82 MB heap size)
 PASS  reproduce/a102.test.js (82 MB heap size)
 PASS  reproduce/a195.test.js (88 MB heap size)
 PASS  reproduce/a161.test.js (87 MB heap size)
 PASS  reproduce/a157.test.js (93 MB heap size)
 PASS  reproduce/a34.test.js (93 MB heap size)
 PASS  reproduce/a6.test.js (98 MB heap size)
 PASS  reproduce/a53.test.js (103 MB heap size)
 PASS  reproduce/a152.test.js (103 MB heap size)
 PASS  reproduce/a21.test.js (108 MB heap size)
 PASS  reproduce/a17.test.js (107 MB heap size)
 PASS  reproduce/a28.test.js (113 MB heap size)
 PASS  reproduce/a129.test.js (113 MB heap size)
 PASS  reproduce/a175.test.js (118 MB heap size)
 PASS  reproduce/a90.test.js (124 MB heap size)
 PASS  reproduce/a52.test.js (123 MB heap size)
 PASS  reproduce/a99.test.js (128 MB heap size)
 PASS  reproduce/a30.test.js (128 MB heap size)
 PASS  reproduce/a89.test.js (133 MB heap size)
 PASS  reproduce/a105.test.js (42 MB heap size)
 PASS  reproduce/a193.test.js (47 MB heap size)
 PASS  reproduce/a158.test.js (53 MB heap size)
 PASS  reproduce/a123.test.js (51 MB heap size)
 PASS  reproduce/a114.test.js (57 MB heap size)
 PASS  reproduce/a77.test.js (57 MB heap size)
 PASS  reproduce/a200.test.js (63 MB heap size)
 PASS  reproduce/a166.test.js (61 MB heap size)
 PASS  reproduce/a192.test.js (67 MB heap size)
 PASS  reproduce/a149.test.js (67 MB heap size)
 PASS  reproduce/a10.test.js (72 MB heap size)
 PASS  reproduce/a145.test.js (78 MB heap size)
 PASS  reproduce/a54.test.js (77 MB heap size)
 PASS  reproduce/a27.test.js (83 MB heap size)
 PASS  reproduce/a154.test.js (83 MB heap size)
 PASS  reproduce/a119.test.js (88 MB heap size)
 PASS  reproduce/a186.test.js (89 MB heap size)
 PASS  reproduce/a63.test.js (94 MB heap size)
 PASS  reproduce/a97.test.js (94 MB heap size)
 PASS  reproduce/a100.test.js (99 MB heap size)
 PASS  reproduce/a25.test.js (99 MB heap size)
 PASS  reproduce/a146.test.js (104 MB heap size)
 PASS  reproduce/a71.test.js (110 MB heap size)
 PASS  reproduce/a103.test.js (109 MB heap size)
 PASS  reproduce/a113.test.js (115 MB heap size)
 PASS  reproduce/a24.test.js (114 MB heap size)
 PASS  reproduce/a3.test.js (119 MB heap size)
 PASS  reproduce/a178.test.js (119 MB heap size)
 PASS  reproduce/a189.test.js (125 MB heap size)
 PASS  reproduce/a142.test.js (130 MB heap size)
 PASS  reproduce/a164.test.js (129 MB heap size)
 PASS  reproduce/a138.test.js (135 MB heap size)
 PASS  reproduce/a49.test.js (134 MB heap size)
 PASS  reproduce/a82.test.js (140 MB heap size)
 PASS  reproduce/a141.test.js (139 MB heap size)
 PASS  reproduce/a51.test.js (145 MB heap size)
 PASS  reproduce/a122.test.js (150 MB heap size)
 PASS  reproduce/a187.test.js (150 MB heap size)
 PASS  reproduce/a173.test.js (155 MB heap size)
 PASS  reproduce/a55.test.js (41 MB heap size)
 PASS  reproduce/a57.test.js (47 MB heap size)
 PASS  reproduce/a160.test.js (52 MB heap size)
 PASS  reproduce/a84.test.js (50 MB heap size)
 PASS  reproduce/a60.test.js (56 MB heap size)
 PASS  reproduce/a70.test.js (57 MB heap size)
 PASS  reproduce/a43.test.js (62 MB heap size)
 PASS  reproduce/a116.test.js (61 MB heap size)
 PASS  reproduce/a38.test.js (66 MB heap size)
 PASS  reproduce/a92.test.js (66 MB heap size)
 PASS  reproduce/a40.test.js (72 MB heap size)
 PASS  reproduce/a33.test.js (77 MB heap size)
 PASS  reproduce/a48.test.js (77 MB heap size)
 PASS  reproduce/a101.test.js (82 MB heap size)
 PASS  reproduce/a93.test.js (82 MB heap size)
 PASS  reproduce/a73.test.js (87 MB heap size)
 PASS  reproduce/a134.test.js (87 MB heap size)
 PASS  reproduce/a47.test.js (93 MB heap size)
 PASS  reproduce/a85.test.js (98 MB heap size)
 PASS  reproduce/a194.test.js (97 MB heap size)
 PASS  reproduce/a61.test.js (102 MB heap size)
 PASS  reproduce/a56.test.js (103 MB heap size)
 PASS  reproduce/a88.test.js (108 MB heap size)
 PASS  reproduce/a167.test.js (108 MB heap size)

Test Suites: 201 passed, 201 total
Tests:       201 passed, 201 total
Snapshots:   0 total
Time:        15.093 s, estimated 18 s

@facebook-github-bot
Copy link
Contributor

Hi @rthreei!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at [email protected]. Thanks!

@codecov-commenter
Copy link

codecov-commenter commented Dec 31, 2021

Codecov Report

Merging #12205 (790a026) into main (0f99ff5) will increase coverage by 0.02%.
The diff coverage is 66.66%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main   #12205      +/-   ##
==========================================
+ Coverage   67.51%   67.54%   +0.02%     
==========================================
  Files         328      328              
  Lines       17246    17228      -18     
  Branches     5071     5067       -4     
==========================================
- Hits        11644    11637       -7     
+ Misses       5569     5556      -13     
- Partials       33       35       +2     
Impacted Files Coverage Δ
packages/jest-runtime/src/index.ts 56.37% <66.66%> (-0.10%) ⬇️
...provider-v8/cjs-native-without-sourcemap/module.js 75.00% <0.00%> (-4.17%) ⬇️
packages/expect/src/utils.ts 96.53% <0.00%> (+0.49%) ⬆️
...e-provider-v8/cjs-with-babel-transformer/module.ts 96.15% <0.00%> (+15.38%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0f99ff5...790a026. Read the comment docs.

@facebook-github-bot
Copy link
Contributor

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

@rthreei rthreei force-pushed the fix/memory-leak branch 4 times, most recently from 2d84b73 to 951de91 Compare January 5, 2022 07:55
Memory leak is alleviated with `vm.compileFunction`. However, implementing `importModuleDynamically` causes memory to leak again, so that has been skipped.

Fixes jestjs#11956
@vanstinator
Copy link

What needs to happen to get this over the finish line?

@Smrtnyk
Copy link

Smrtnyk commented Feb 26, 2022

What needs to happen to get this over the finish line?

I guess @SimenB has some doubts about this?

@SimenB
Copy link
Member

SimenB commented Feb 26, 2022

Main reason is that this will make it much worse for node 12 and 14, and it's really a bug in node

@vanstinator
Copy link

Can we make it an opt-in change with a cli flag? I'm happy to do the work and update the tests. With node 14 going EOL this fall more people are going to be looking to move to 16 (including us at Plex). A cli flag would make the move much less painful. When node fixes their bug we can remove the option from jest again when it makes sense

@SimenB
Copy link
Member

SimenB commented Feb 26, 2022

I don't think we should add a config flag - if we do this we should just detect the version of node inline so people don't have to change anything.

Maybe you could change this to use semver and detect broken versions (>= 16.11.0 I guess?), and if not broken use current code? Sorta similar to https://github.com/facebook/jest/blob/7826a8f15be07b2634add73a50decf73086e5948/packages/test-utils/src/ConditionalTest.ts#L37

@vanstinator
Copy link

vanstinator commented Feb 26, 2022

Sure, that approach works too. I'll open a fresh PR based on this one when I'm ready. Thanks for the quick brainstorm!

@@ -72,7 +72,7 @@ test('import cjs', async () => {
expect(half(4)).toBe(2);
});

test('import esm from cjs', async () => {
test.skip('import esm from cjs', async () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note that this makes the change unacceptable - this needs to work. Since nodejs/node#31860 has been fixed, I assume you can just add the missing importModuleDynamically to the compileFunction call

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fyi - when I had left importModuleDynamically implemented, the memory leak persisted. Another mystery...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting! that might be a separate bug in node 😅

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've replicated this myself locally. I'll see if I can figure out why.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've replicated this myself locally. I'll see if I can figure out why.

Any luck @vanstinator ?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is the only problem holding y'all back to merge this PR, I'd love to hear an update from you @vanstinator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rthreei, the memory leak that occurs when using compileFunction() with importModuleDynamically is tracked here. A fix of that was attempted with this PR a few weeks ago, but had to be reverted again.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rene-leanix Furthermore, it appears progression on this issue may be dependent upon this V8 PR via this comment

@phawxby
Copy link
Contributor

phawxby commented Apr 14, 2022

Is there anything I can do to get this PR moving along again? We generally try to avoid falling too far behind even minor versions

@SimenB
Copy link
Member

SimenB commented Apr 17, 2022

@phawxby nothing new since the last activity, feel free to fix: #12205 (comment)

@phawxby
Copy link
Contributor

phawxby commented Apr 19, 2022

@phawxby nothing new since the last activity, feel free to fix: #12205 (comment)

As you noted in the thread above, the importModuleDynamically issue could be a different bug. Would a way to handle this be to accept this PR but with importModuleDynamically implemented with the memory leak as it's not a regression in performance, for many will be a significant improvement. The importModuleDynamically memory leak issue can then be tackled separately?

@rthreei
Copy link
Author

rthreei commented Apr 19, 2022

@phawxby nothing new since the last activity, feel free to fix: #12205 (comment)

As you noted in the thread above, the importModuleDynamically issue could be a different bug. Would a way to handle this be to accept this PR but with importModuleDynamically implemented with the memory leak as it's not a regression in performance, for many will be a significant improvement. The importModuleDynamically memory leak issue can then be tackled separately?

importModuleDynamically being implemented voids the improvement, so that doesn't help. Unless you're seeing that it does help?

@phawxby
Copy link
Contributor

phawxby commented Apr 19, 2022

@phawxby nothing new since the last activity, feel free to fix: #12205 (comment)

As you noted in the thread above, the importModuleDynamically issue could be a different bug. Would a way to handle this be to accept this PR but with importModuleDynamically implemented with the memory leak as it's not a regression in performance, for many will be a significant improvement. The importModuleDynamically memory leak issue can then be tackled separately?

importModuleDynamically being implemented voids the improvement, so that doesn't help. Unless you're seeing that it does help?

Ah, I misunderstood your comment as the issue only occurs when importing esm from cjs, not in all scenarios. I'm going to have a dig around this afternoon and see if I can find anything but I'm not holding out much hope.

@phawxby
Copy link
Contributor

phawxby commented Apr 19, 2022

A bit more digging and I've found this, which suggests this isn't going to be especially easy to fix.
nodejs/node#25424 (comment)

Which then ties in with this.
https://bugs.chromium.org/p/v8/issues/detail?id=12198

@SimenB
Copy link
Member

SimenB commented Apr 27, 2022

Instead of using a patch, one thing that can be done is to extend the default jest-runtime and override _execModule. It can be passed as runtime in configuration (renamed from moduleLoader in Jest 28).

https://github.com/facebook/jest/blob/f43871e37f8bf6dbe292ad2e52f4781868c4731b/packages/jest-runner/src/runTest.ts#L117-L121

While _execModule is private (by convention), it's not literally private at runtime (i.e. using #), so overriding should be fine.

const {default: JestRuntime} = require('jest-runtime');

module.exports = class CompileFunctionRuntime extends JestRuntime {
  _execModule() {
    // do something
  }
};

This module could then be published as a workaround. Somewhat brittle as _execModule isn't public API, but less brittle than applying a patch 🙂

@blimmer
Copy link
Contributor

blimmer commented Jun 8, 2022

@a88zach has published https://github.com/reside-eng/jest-runtime which does what @SimenB suggested in the last comment. This unblocked us from upgrading to Node > 16.10.

See #11956 (comment).

@Havunen
Copy link

Havunen commented Oct 5, 2023

In NodeJS v18.17.1 the heap increases from 118Mb to 5815MB and total runtime runInBand + logHeapUsage is 187sec
using @side/jest-runtime the heap decreased to 5467 MB and total runtime runInBand + logHeapUsage is 165sec

:/

@SimenB
Copy link
Member

SimenB commented Oct 5, 2023

Node landed a fix for vm.Script a few hours ago. Hopefully it'll be backported all the way to Node 18.

@Havunen
Copy link

Havunen commented Oct 5, 2023

NodeJs v20.8.0 running:

    "test": "cross-env NODE_OPTIONS=--max-old-space-size=8192 node --experimental-vm-modules ./node_modules/jest/bin/jest.js --config=jest.config.js --no-watchman --runInBand --logHeapUsage --ci",
  transform: {
    '\\.ts$': '@swc/jest',
    '\\.vue$': '<rootDir>/node_modules/vue2-swc-jest',
  },
  runtime: '@side/jest-runtime',

Bumps heap size from 125Mb to 5601 MB heap size (execution time 166 sec )

Removing runtime: '@side/jest-runtime', -setting:

Bumps heap size to 5778 MB ( execution time 178sec )

removing the runInBand and logHeapUsage
with runtime: '@side/jest-runtime', 44sec
without runtime: '@side/jest-runtime', 44.613sec

However not having --runInBand the memory usage is even more expensive and in dev ops cheap machines the computer is starwing...
image

@Havunen
Copy link

Havunen commented Oct 5, 2023

I'm starting to feel that there is some other memory leak issue as well, it feels like Jest keeps the test data in memory until the whole run is finished

@ximex
Copy link

ximex commented Oct 5, 2023

@Havunen this fix (nodejs/node#49950 (comment)) isn't in node 20.8.0. next week 20.9.0 should get released. maybe this fixes some of the memory problems

@Havunen
Copy link

Havunen commented Oct 5, 2023

@ximex is the fix available in any nightly / preview release? I would like to test if it solves this issue

@ximex
Copy link

ximex commented Oct 5, 2023

I'm not the expert for this. but i think so if you try the todays nightly version

@SimenB
Copy link
Member

SimenB commented Oct 5, 2023

#11956 (comment)

@Havunen
Copy link

Havunen commented Oct 5, 2023

#11956 (comment)

I tried it but it does not seem to change anything? runtimeSupportsVmModules is true so it always sets the callback anyway?

@SimenB
Copy link
Member

SimenB commented Oct 5, 2023

If you use ESM the fix in Node won't help you, unfortunately - that is for vm.Script that does not use import().

@SimenB
Copy link
Member

SimenB commented Oct 5, 2023

For ESM you probably need to wait for nodejs/node#33439 and/or an upstream v8 proper fix for the code caching

@Havunen
Copy link

Havunen commented Oct 5, 2023

NodeJs 20.8.0

CommonJs - no changes -- 86sec 10GB RAM

NodeJs 20.8.0

CommonJs - +patch for runtimeSupportsVmModules to be undefined - 86sec 10GB RAM

It seems its not yet fixed

@SimenB
Copy link
Member

SimenB commented Oct 5, 2023

The fix is not released yet, you'll need to install the nightly. But I'm not sure if the commit made it in time for the nightly or if you'll have to wait until tomorrow

@Havunen
Copy link

Havunen commented Oct 5, 2023

The fix is not released yet, you'll need to install the nightly. But I'm not sure if the commit made it in time for the nightly or if you'll have to wait until tomorrow

Ok, I will try again tomorrow

@Havunen
Copy link

Havunen commented Oct 5, 2023

For ESM you probably need to wait for nodejs/node#33439 and/or an upstream v8 proper fix for the code caching

Because node js is not GCing dynamic modules, would it make sense to cache every created dynamic module to ensure only one gets created?

@SimenB
Copy link
Member

SimenB commented Oct 5, 2023

That would leak module state between tests

@joyeecheung
Copy link

joyeecheung commented Oct 5, 2023

The current situation in Node.js is:

  1. If you just create a lot of SourceTextModules, they won't leak on their own. They are now GC-able after module: rework of memory management in vm APIs with the importModuleDynamically option nodejs/node#48510
  2. If you use vm.Script without the importModuleDynamically option, it will hit the isolate compilation cache again since vm: use default host-defined options when importModuleDynamically is not set nodejs/node#49950, so won't be 100x slower than 16.x. And there should be no leaks (not that I know of).
  3. If you use vm.Script with the importModuleDynamically option, but you don't actually use --experimental-vm-module which means you probably couldn't do anything useful in that callback anyway, the plan is to ignore that useless callback and throw when import() happens, and keep the script hit the compilation cache when import() isn't actually called.
  4. If you use vm.Script + importModuleDynamically + --experimental-vm-module/SourceTextModule, chances are the issue you are seeing is still unfixed, and it's possibly related to https://bugs.chromium.org/p/v8/issues/detail?id=10284. This needs another simple repro that just uses Node.js with no other dependencies before it can be looked into.

@SimenB
Copy link
Member

SimenB commented Oct 5, 2023

Oooh, number 3 is perfect!

We'll have to try to come up with a minimal reproduction after these fixes are out to avoid conflating issues 👍

@Havunen
Copy link

Havunen commented Oct 5, 2023

I have found an interesting detail, the problem does not occur with plain .js files, but only with compiled files for example .ts. I will create a new ticket and github repo with simple repro. Maybe we can shrink it to plain js node example

edit: nvm its not related to that.

It seems to be related to a json file and we have a lot of those in our app

@Havunen
Copy link

Havunen commented Oct 5, 2023

I created a new issue here: #14605

@joyeecheung
Copy link

joyeecheung commented Oct 9, 2023

FYI you can use --heapsnapshot-near-heap-limit=3 (or a higher value) to generate a bunch of heap snapshots and figure out what is leaking - at least what is leaking on the JS side. --heap-prof might be useful too if heap snapshots take too long to generate. (On how to use the heap snapshots, check out https://developer.chrome.com/docs/devtools/memory-problems/heap-snapshots/ though the UI screenshots are a bit outdated but the general idea stays the same). There are probably also some more up-to-date tutorials on how to use the Chrome DevTools to visualize these things if you search for them.

@SimenB
Copy link
Member

SimenB commented Oct 9, 2023

The reproduction linked above with ESM doesn't leak for me if I remove the importModuleDynamically option passed to new Script (and use the nightly). Dynamic import is not used, so the callback is never invoked. But ESM mode is enabled (so SourceTextModule and SyntheticModule are used), meaning we cannot know if the callback will be needed or not until import() is actually evaluated within the module. Which can happen at any time.

Maybe importModuleDynamically should be behind its own flag (either in Jest or in Node) separately from general ESM support.

Not sure as we're of course back to the same upstream v8 issue the moment it's enabled. But this would allow lots of people who don't need import to be unblocked at least.


Lots of new Script are called for Jest's own sources - there's quite a few module we evaluate within the vm context. We might be able to skip the callback for those sources... I don't think we use dynamic import for anything that's marked as internal

@Havunen
Copy link

Havunen commented Oct 9, 2023

@joyeecheung @SimenB

I have reproduced the issue using nodejs and javascript only, and also found a work around.

Having a shared context between the modules seems to leak the memory. However setting the shared context null manually after function execution it fixes the memory leak. Setting the variable null in JS is non-sense (ref: https://github.com/Havunen/nodejs-memory-leak/blob/main/test.js#L45-L46 ) because it goes out of scope and should be GC'd but it does not seem to happen. So its definetly a nodejs / v8 bug

https://github.com/Havunen/nodejs-memory-leak

@Havunen
Copy link

Havunen commented Oct 10, 2023

I created an issue to nodejs repo: nodejs/node#50113

@SimenB
Copy link
Member

SimenB commented Oct 10, 2023

Fantastic, thanks @Havunen! I also noticed I could get a pure nodejs thing to go OOM only when passing context, but my repro also needed to stick all modules in a Map, or they were GC-ed, so I thought it might be that. Great to see that's not needed

@AlecksJohannes
Copy link

Hey there amazing folks !

I know this PR is here been quite a long time, I just gave this PR a tried on Node 20.10, unfortunately it does not fix the issue. The heap memory usage still keeps piling up for each test files.

@sibelius
Copy link

sibelius commented Oct 1, 2024

can we enable this by an option? a feature flag ?

to be an opt in ?

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

Successfully merging this pull request may close these issues.