Build1 distinct publisher3 min readUpdated
A dev.to post sells numpy_cache as 20x faster than np.savez_compressed and half the size of np.save. Its own baselines put the write nearer 1.5 ms per megabyte, and the file format lets you check the rest.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
Start with the arithmetic the post declines to do. Its own fast-path baseline is under 1 ms per megabyte for np.save [3], and the demo array works out to exactly 100,000,000 bytes, the same size in decimal megabytes as the array used for the zlib baseline [13]. On that array, zlib is at least thirty times slower than the raw dump [14]. Being twenty times faster than zlib therefore lands at roughly 150 ms, about 1.5 ms per megabyte, or half again the cost of np.save rather than parity with it [15]. Halving a file for half again the write time is a trade most caching loops would take. It is a different sentence from the one the feature list is written to suggest.
The size claim is the easier of the two to check, because the format hands you the instrument. uncompressed_size sits at byte 0 and compressed_size at byte 8 [20], so the ratio actually achieved on your data is a 16-byte read and one division, with no decompression and no timing harness. Worth noting what the example compresses: float32 output of np.random.randn [12]. Noise-like input is the least friendly case for a byte-level matcher, so the measured figure on quantised or repetitive arrays could go either way from 2x. Ratio is a property of your bytes, not of the library.
Then the header. The fields shown come to 88 bytes: two 8-byte sizes, 64 bytes of shape slots, and two 4-byte words [16]. The declared size is 96 [8] and the excerpt stops after the version field [17], so eight bytes carry whatever encodes dtype and rank, which load() has to recover across int, uint, float and bool [9][10]. Tight, and plausible. The shape block is less thrifty: a 2-D array pays for eight slots and leaves 48 bytes of zeros in every file [21]. Immaterial at 100 MB, visible if the cache holds a million small arrays.
The claim I would read the C for is the lock. The post says offloading to C avoids interpreter overhead and the GIL during serialization [7], with a direct pointer from PyArray_DATA and no copy where the layout allows [6]. Whether the lock is actually dropped around the compression call decides whether a training loop can overlap its cache write with the next batch, and the published excerpt ends before that code [17]. The same gap covers what happens to an array that is not contiguous, where the zero-copy path does not apply by the post's own wording [6].
None of this needs the author's cooperation to settle. The measurement is three writes of your own arrays at both ends of the acceleration range [5], plus the two sizes read out of each header. That is a morning's work, and it produces the number the post left as a bullet point.
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
A dev.to post presenting numpy_cache lists the library as "20x faster than np.savez_compressed()".
The same feature list claims "good compression - 2x smaller than np.save()".
numpy_cache exposes an acceleration parameter from 1 to 16 that trades compression ratio for speed; the documented default is 4, and acceleration=16 is described as reducing the ratio while maximising write speed.
The critical path is a C extension using the Python C-API, with PyArray_DATA giving a direct pointer to the array's contiguous memory block, described as zero-copy where the data structure permits.
The post states that offloading the critical path to C avoids Python interpreter overhead and the Global Interpreter Lock during serialization.
The file layout is a packed header of 96 bytes followed by a compressed data block; the header fields shown are uint64 uncompressed_size, uint64 compressed_size, uint64 shape[8] supporting up to eight dimensions, uint32 magic 0x4C5A4E43 ("LZNC"), and uint32 version, currently 1.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
One self-published post; architecture checkable, numbers not
Everything rests on a single dev.to article by the library's own author. The architectural claims are partly self-evidencing because the packed header struct is published and internally consistent (96 bytes fully accounted for once ndim and dtype are counted), and the derived arithmetic can be checked against the post's own baselines. The performance claims are not: the 20x and 2x figures are bare bullets, the referenced latency comparisons carry no numbers in the published text, the stated test dataset (~1 MB float32 arrays) differs from the 100 MB basis of the speed claim, and no hardware, repetition count or acceleration setting is given. No compression call site is shown, and there is no second source, repository or package artifact to corroborate anything.
No adoption signal beyond the author's own announcement
The only observable event is the author's own dev.to post introducing the library. The supplied material discloses no repository, package index listing, version history, download or star counts, dependent projects, or any third-party deployment or benchmark. There is no basis on which to score adoption, and none should be inferred from a self-published announcement.
Headline multiples outrun the post's own baselines
The framing promises "np.save() speed with good compression" and "20x faster than np.savez_compressed()", but 20x off the post's own 3-second, 100 MB zlib baseline is about 150 ms, roughly 1.5 ms per megabyte, i.e. about 1.5 times the sub-1 ms per megabyte the same post attributes to np.save. The 2x size claim is measured on a different dataset (~1 MB float32 arrays) than the 100 MB basis of the speed claim, no acceleration setting accompanies either figure, and the "no lightweight, specialised solution... until now" framing dismisses HDF5 and Zarr without measurement. Costs are underplayed rather than false: the private LZNC format is unreadable by np.load while .npy is offered as an acceptable extension, single-block files preclude ranged reads, and the zero-copy path does not apply to strided arrays. The gap is overstatement of degree and framing, not fabrication - the architecture described is coherent and the direction of the trade-off is real.
Author marketing own library, unmediated
The source is a promotional post by the library's own author on a self-publishing platform with no editorial mediation. The structure is a marketing one: a manufactured gap ("no lightweight, specialised solution... until now"), a feature list of bare superlatives, dismissal of established alternatives on dependency weight rather than measurement, and a copy-paste adoption path. Nothing in the supplied material indicates commercial monetisation, sponsorship or a vendor relationship, so the incentive is reputational and adoption-seeking rather than financial, which is why this is not scored higher.
Format and arithmetic conclusions solid, performance conclusions weak
Confidence splits by claim type. What the post says, the header layout it publishes, and the arithmetic consequences of its own baselines are stated plainly enough to assess with high confidence, and the format-level derivations (single block, ratio in the first 16 bytes, 64-byte shape field, non-.npy layout) follow directly from the published struct. What the library actually does at runtime is near-unverifiable here: no benchmark table renders, the test dataset does not match the headline basis, no compression call site or GIL-release code is shown, and there is no second source or artifact. One ledger reading about missing header bytes is contradicted by the source text, which further argues for a cautious overall score.
build
Force the tool call, then hand Lightsail a long-lived key1 distinct publisher
build
A cache hit is a quota refund: semantic caching with trigrams and no vector database1 distinct publisher
build
Stop timing your GraphQL tests and start counting loader calls1 distinct publisher
build
Agent memory rots by accumulation, and the missing primitive is a supersession key1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 23, 2026