Limits of Data.Array.slice for paginating large datasets after full JSON decode
0 reputation · 12 Jan 2022, 15:14 UTC
0 reputation · 12 Jan 2022, 15:14 UTC
Goal: paginate a large dataset fetched via purescript-affjax while minimizing temporary memory allocation during slicing operations.
Constraint: affjax decodes the complete JSON response into an Array before any PureScript processing, so any subsequent take/drop or slice works on an already materialized Array.
Uncertainty: whether using Data.Array.slice (which eagerly copies the requested range) adds significant memory overhead compared to Data.List.take/drop on the same Array, and if any documented PureScript feature enables incremental JSON decoding to avoid full materialization.
Specific questions:
34775 reputation · 12 Jan 2022, 19:47 UTC
PureScript Arrays compile to JavaScript Arrays. Data.Array.slice maps to Array.prototype.slice, which creates a new dense array with copied references. The source array stays alive as long as any reference exists (including the affjax response handler's closure).
Converting to Data.List via fromFoldable or toList builds a linked structure: each element becomes a Cons cell with a pointer to the next. For a 10,000-element page, that's 10,000 additional heap objects.
-- Profile in Chrome DevTools Memory tab:
-- 1. Fetch 100k records via affjax
-- 2. Take heap snapshot
-- 3. Run: slice 0 1000 largeArray
-- 4. Take second snapshot
-- 5. Compare retained size delta
Expect the delta to match roughly sliceLength * pointerSize (8 bytes per reference on 64-bit V8) plus array header overhead.
purescript-virtualized or similar). The full array stays in memory but DOM nodes stay minimal.postMessage (structured clone copies, but keeps main thread responsive).purescript-parsing or purescript-attoparsec that consumes a ReadableStream chunk-by-chunk, emitting decoded records as they complete. Significant effort; only justified for very large payloads.Which JSON decoding library are you using (argonaut, simple-json, foreign-generic, other)? The answer determines whether any experimental streaming support exists or if a custom parser is the only path.
Use comments to ask for clarification. Post a solution as an answer.
34,775 reputation · 12 Jan 2022, 23:29 UTC
Data.Array.slice creates a new JavaScript array whose length equals the requested slice size, but it only copies the references to the existing elements; the elements themselves (whether numbers, strings or objects) are not duplicated. Consequently, the extra memory overhead is proportional to the slice length times the size of a pointer/reference, not to the total size of the payload data. If the elements are large objects, this overhead is usually negligible compared to duplicating the whole Array.