Description
Hello. I was going to post this on the original proposal-temporal repo, but since the goal there wasn't about making a polyfill for production use, I decided not to. However, since this polyfill has that goal, it seems like a relevant issue.
When using the polyfill, I ran into a deno memory issue (which I reported in denoland/deno#10721). The root problem is that in the polyfill, there are a lot of new Intl.DateTimeFormat
calls, objects which V8 apparently doesn't clean up as well as it could. After some investigation, I found out node is affected too, albeit some orders of magnitude less.
The issue can be demonstrated in Temporal as follows:
import { Temporal } from '@js-temporal/polyfill';
const { ZonedDateTime } = Temporal;
setInterval(() => {
var a;
for (let i = 0; i < 100; i++) {
a = ZonedDateTime.from("2021-01-01T00:00:00-03:00[America/Sao_Paulo]");
a = Temporal.now.zonedDateTimeISO().toString();
}
}, 1);
Which ranks at ~567M resident memory in node, and ~1033M in (newer) deno.
My solution to this problem originally, was to fork the repo for my personal use and implement a cache for these objects. A Map
caches IntlDateTimeFormat
s at every site they are required, as such:
// ecmascript.mjs
const IntlDateTimeFormatEnUsCache = new Map();
// ...
GetCanonicalTimeZoneIdentifier: (timeZoneIdentifier) => {
// ...
if (!IntlDateTimeFormatEnUsCache.has(String(timeZoneIdentifier))) {
IntlDateTimeFormatEnUsCache.set(String(timeZoneIdentifier), new IntlDateTimeFormat('en-us', {
timeZone: String(timeZoneIdentifier), hour12: false, era: 'short',
year: 'numeric', month: 'numeric', day: 'numeric',
hour: 'numeric', minute: 'numeric', second: 'numeric'
}));
}
const formatter = IntlDateTimeFormatEnUsCache.get(String(timeZoneIdentifier));
Node's memory footprint in that same code above went to ~100K after this change. Deno scored at ~239M (which is about the floor memory usage of deno currently).
This is an issue that V8 could fix, but it can also be done at the library level.