Notes

HEIC vs JPEG: what the smaller file costs

A grid of forty thousand photographs is not forty thousand photographs. It is forty thousand small copies, written once and kept on disk, because decoding that many RAW files every time you scroll would be hopeless. Listing a folder in Negativo returns 40,000 photo ids in 15 ms. The pictures those ids point at are the slow part, and the cache is the answer to it.

Which means somebody has to decide what those small copies are written in. We had to decide three times, because the cache keeps three sizes: 256, 1024 and 2560 pixels on the long edge. The answer was not the same three times. Why it was not is the most useful thing we can tell you about these two formats.

What we measured, and what we did not

We did not test HEIC against JPEG in the abstract. We tested them at three specific sizes, on our encoder, writing thumbnails. That is a narrow experiment and the numbers below are only worth what that narrowness is worth.

What it does tell you is the shape of the trade, and the shape is the part most comparisons skip. We did not measure what the picture looks like. We measured what the machine has to do to produce the file, and how many bytes it leaves behind. One of those you notice while you wait. The other you notice a year later, when the disk is full.

The small size is JPEG

At 256 px on the long edge, our encoder wrote 737 JPEGs a second. HEIC at the same size managed 140.

That gap is not a detail you can decide to ignore. Run it over an archive and it is the difference between the grid filling in behind you and the grid being something you wait for. So the 256 px thumbnail — the one you scroll past thousands of at a time — is a JPEG, and that rate is the reason.

The two large sizes are HEIC

Across the three sizes, HEIC saves 18% of the disk: 220 KB per photograph against 268 KB.

That gap sounds like nothing on one photograph, and on one photograph it is nothing. Over an archive it is the kind of number that decides whether the cache is something you think about or something you don’t. At the large sizes we took the saving, on the reasoning that a 2560 px version is written once and then read for years, so the encoder time goes somewhere you are not sitting and watching.

That is the whole reasoning behind a cache that is deliberately mixed rather than tidy. Two numbers, pointing in opposite directions, and the size of the image decides which one wins. A single-format cache would have been easier to explain and worse in one direction or the other.

Your disk probably decides this before the format does

Here is the part that changes what the comparison is even for.

Indexing an archive on a 7,200 RPM mechanical disk runs at about 89 files a second — 11.2 ms per file. That is the drive head moving, not the code thinking. On a disk like that, the drive hands over 89 files a second and an encoder that manages 140 is not the thing holding the queue up. The slower format costs you something there, but it is not what you are waiting for.

Move the same archive to an external SSD and indexing runs at 1,200 to 1,460 files a second on a single thread. Now 140 a second is the ceiling, and the format choice is what stands between you and a fast machine.

Same software, same photographs, opposite conclusion. Anyone who tells you which format is faster without telling you what the files are sitting on has answered a question you did not ask.

The benchmark that lies

If you go and measure this yourself, there is one specific way to get a confident wrong answer, and it is easy to walk into.

Run a pass over a folder, then run the same pass again. The second one reports around 20,000 files a second. Nothing got faster. The contents are in the page cache now — the second pass is reading RAM and calling it a disk. Compare two formats that way and both of them will look instant, and you will conclude the choice does not matter.

A comparison that means anything is run cold, on the disk the photographs actually live on, at the size you actually need. Everything else is a measurement of your RAM.

What Negativo does not do to your files

None of this touches your originals. The cache is a separate thing that Negativo writes for itself; your photographs are read and never modified, whatever they were shot as. There is no convert-on-import step, because there is no import step. If your camera writes HEIC, you have HEIC in your archive. If it writes JPEG, you have JPEG. Negativo catalogues what is there.

It will not convert between them for you either. It is not an editor — no exposure slider, no crop, no export presets — so a batch conversion is a job for something else. It is macOS only. It does not catalogue video. It does not read Lightroom or Capture One catalogues, so it is not a migration path.

What the cache does buy you is that the thumbnails and the search keep working with the drive unplugged. The small copies are not on the drive you just put in a drawer; the originals are. That is the practical reason to make these files at all, and the reason the format they are written in is worth more than a minute of thought.

If you are choosing for your own archive

Three things, and none of them is a rule about which format is better.

Decide what you are optimising. Encoder time is paid at write, once per file, while you wait. Bytes are paid at rest, forever, on every drive that holds a copy. Those are different currencies and no ratio converts one into the other for you.

Measure at the size you actually use. The rate we measured is a fact about 256 px thumbnails and about nothing else, and it is not the size the same cache chose HEIC for. A comparison run at one size tells you about that size.

Measure cold, on the real disk. See above.

And if the archive lives on a 7,200 RPM mechanical drive, spend the afternoon on something else. The head is moving at 11.2 ms a file, and the format is not the biggest thing costing you.

Negativo catalogues the photographs already sitting on your disks, in whatever format they arrived in, without importing or copying them — what it is, and what it isn’t, in more detail than a blog post has room for.