CloudCutter archive · Publication 16

How to Avoid RAM Explosion with 500 GB Point-Cloud Files

The safe architecture is simple to state: never make memory consumption proportional to the complete source cloud.

Rule 1 - Keep preview memory bounded

The preview stores only a controlled number of samples. Memory therefore depends on the global sampling cap or the number of tiles multiplied by the per-tile cap, not directly on the total point count.

if (tileSampleCount[tile] < sampleCapPerTile)
    previewSamples[tile].push_back(point);

Rule 2 - Export from the original full-resolution source

Preview samples are not export data. The safe workflow stores selection definitions, reopens or continues streaming the source, evaluates every point, and writes only selected points.

  1. The user defines tile and height selections.
  2. CloudCutter stores the selection identifiers.
  3. The exporter streams the full-resolution source.
  4. Only points satisfying a selection are written.

This produces full-resolution outputs without storing a full-resolution input cloud.

Rule 3 - Use stable integer tile keys

Tile assignment must handle negative coordinates correctly.

int64_t ix = static_cast<int64_t>(std::floor(point.x / tileSize));
int64_t iy = static_cast<int64_t>(std::floor(point.y / tileSize));

Simple integer conversion truncates toward zero and can place negative coordinates in the wrong tile.

Rule 4 - Write bounded blocks

Some output APIs require arrays, but those arrays should represent a controlled block rather than the entire selected cloud.

constexpr size_t MAX_BLOCK_POINTS = 1'000'000;

if (x.size() >= MAX_BLOCK_POINTS) {
    writeOutputBlock(x, y, z, rgb);
    clearBuffers();
}

RAM usage then depends on block size multiplied by the active fields and outputs.

What later benchmarks revealed

The July architecture prioritized safety and correctness. Later large-file benchmarks confirmed its low-memory behavior but exposed an I/O cost when the source was reread separately for several outputs. The next optimization direction is a single-pass multi-output exporter that preserves bounded memory while routing each streamed point to every matching destination.

Large E57 file runs out of memory — what can you do?

When an E57 is larger than the available RAM, adding virtual memory may allow more data to be addressed but does not automatically create a responsive engineering workflow. The key architectural question is whether the application must retain the complete point set at once.

A bounded-memory workflow keeps only controlled preview samples and working buffers in memory, stores the user's selections separately, and streams the full-resolution source when producing outputs.

Subsample or split?

Subsampling reduces density and is useful when fewer points are acceptable. Splitting preserves the idea of full source resolution inside selected spatial areas and is useful when engineers need the original detail but not the complete project.

For a measured large-file example, see CloudCutter E57 Benchmark 02: 244.54 GiB and 10.81 billion points.