Tracking: large data (layers over 2 million features, slow hillshade and GeoTIFF writing)
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 25/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- rust, web-dev
- Domain
- backend, data, databases, performance
Research direction
Start by reading the decision section and the linked issues #1105 and #1108; the proposed work spans crates/data/src/source/mod.rs, crates/analysis/src/rasterops.rs, and crates/data/src/raster/cogwrite.rs. The issue asks contributors to first choose between streaming tools and a memory budget, then implement a broad performance plan. Done means the chosen approach and its steps are completed, with the stated correctness and performance goals met.
Written by the indexing model from the issue text.
Description
On real-sized data RustGIS either refuses or is much slower than it needs to be. Measured on one US state (3,212,306 building footprints, 4,562 census block groups, a 9667 × 11947 DEM; rustgis-cli at d58cb8a, i7-6700, single runs, ±15%), with the time an established tool takes on the same files in brackets. This issue tracks fixing that, and has one decision to make first.
What's wrong now
- Layers over 2,000,000 features can't be exported, reprojected or used in tools.
MAX_LIMIT(crates/data/src/source/mod.rs) refuses them: all 3.2M buildings can't be converted, and #1108 is worse, a silent half sample. It's a count, not memory: it refuses 3.2M small polygons that fit in about 1.2 GB, but doesn't stop 2M large ones from exhausting memory. - Exports hold the whole layer, sometimes twice. Converting 1.79M polygons to FlatGeobuf takes 22.7 s and 1.2 GB (8.3 s, 0.26 GB). Reprojection clones the
Dataset, and the FlatGeobuf writer builds the whole file in aVec<u8>. - Hillshade is slow. It takes 59 s (7 s).
gradient()incrates/analysis/src/rasterops.rslooks up the coordinate system for every cell, 115M times here, and runs five trig functions per cell. Its output is written as Float32 although the values are whole numbers 0–255. - Writing GeoTIFFs is slow. The COG export takes 43 s (16–22 s), nearly all of it Deflate at level 6 through
miniz_oxide, about 18 MB/s (crates/data/src/raster/cogwrite.rs). - Summarize Within compares every point with every polygon (#1105): over 28 minutes for 1.79M points (15 s).
Needs a decision: tools on layers bigger than memory
Steps 2 and 3 below happen either way: exports stream, and the count becomes a memory budget. What should tools do past the budget?
- A. Streaming tools (large). Per-feature tools (reproject, buffer, calculate geometry) work a chunk at a time. Tools that compare two layers (count points, spatial join, clip, select by location) index the smaller layer and stream the larger. Outputs go to temporary files added as streamed layers. That means tools on any size, but every tool gets a second execution path, and temporary-file outputs touch undo, project saving and the web app, which has no temporary files.
- B. Stay in memory (small to very large). Tools keep working on a whole layer under the budget, and past it the answer is "clip or filter first". There is one execution path, but a ceiling, lower in the web app. Small changes (boxing the common one-ring polygon, reserving from the known count) might take a feature from about 355 to 250 bytes. A flat, columnar geometry model would roughly halve memory, but touches every crate.
Which fits where RustGIS is heading?
The steps also assume these defaults. Say so if any is wrong:
- hillshade writes Byte;
- threads on the desktop only, with the web app single-threaded as the renderer already is (
threads_for); - a budget of 4 GiB on the desktop and 1 GiB in the web app, adjustable;
- COGs use the floating-point predictor (TIFF Predictor 3), which GDAL, QGIS and the
tiffcrate read.
Plan
1. Correctness (small, independent)
- Refuse instead of sampling (#1108): an incomplete read in
source::materializebecomes an error, checked from the known count before reading. - Index Summarize Within (#1105): the polygons in
ExtentIndex, each point tested against its candidates only.
2. Stream exports and reprojection (medium)
-
visit_chunksfor GeoPackage, FlatGeobuf and GeoParquet. Shapefile already has it (#681). - A writer per format that takes chunks, and
share.exportLayeron a streamed layer reading chunk → reproject → writer. Memory goes from 1.2 GB to about 0.3 GB, and the limit no longer applies to exports. - FlatGeobuf in the web app: its index needs a temporary file, so write it unindexed there.
3. A memory budget instead of MAX_LIMIT (small, after 2)
-
load_allcounts bytes as it reads chunks and refuses past the budget, withtry_reservefor the large vectors.
4. Terrain kernels (small, independent)
- Hillshade, slope and aspect as row passes: constants computed once, three row slices walked with
windows(3)andzip, with no-data and edges on the existing path. A standalone test gave identical output on all 115M cells, 21 s → 4 s on one thread, in the web app too. - Hillshade writes Byte.
5. GeoTIFF writing (small to medium, independent)
- Deflate level 1 with Predictor 3 in
cogwrite.rs: 157 MB/s and 25% smaller on the DEM's tiles; the COG export goes to about 12 s. - The untiled export through the in-house writer:
tiff0.11.3 can't write Predictor 3, and its speed today depends onzipturning onzlib-rs.
6. Threads on the desktop (medium, after 4 and 5)
- Raster kernels in row bands, COG tiles compressed in parallel: about 3× on 4 cores.
7. Tools past the budget (large or skipped, after the decision)
- A: streaming tools, Summarize Within first. B: the small memory savings.
Related
#1105 and #1108 are filed separately because they're bugs whatever is decided here. Step 2 builds on #681's chunked reading. #1065 (layers read in place are read twice on every render) is about drawing, not tools, so it stays separate.
- Dominant language
- Rust
- Stars
- 1.9k
- Forks
- 268
- Avg merge
- 3h 37m
- Merged PRs (30d)
- 818
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from opengeos/RustGIS
-
enhancement
Difficulty 5/5 Over a week Newbie friendliness 25/100
Maintainers usually reply within 1 day
-
[Feature]: Line labels try other places along the line, and sit a distance above or below it. Part 2Openenhancement
Difficulty 4/5 3-5 days Newbie friendliness 45/100
Maintainers usually reply within 1 day
-
[Feature]: Join Field: match a text key with a number key, so Census tables join to TIGER tractsPossibly taken @PawelKra claimed this today. Openenhancement
Difficulty 2/5 1-3 hours Newbie friendliness 35/100
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 45/100
opengeos/RustGIS#1175 · 2 reactions ·
Maintainers usually reply within 1 day
-
enhancement
Difficulty 4/5 3-5 days Newbie friendliness 25/100
Maintainers usually reply within 1 day
All issues in opengeos/RustGIS
Similar issues
-
ai_p2 bug comp-datalake
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
ClickHouse/ClickHouse#128306 · 1 comment ·
Maintainers usually reply within 1 day
-
documentation
Difficulty 1/5 Under an hour Newbie friendliness 85/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
Maintainers usually reply within 1 day
-
bug triage
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Maintainers usually reply within 1 day
-
area:cli bug priority:medium
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day