SpatialFeatures::Importers::KML#each_record resolves each geometry's Placemark with feature.ancestors('Placemark').first. Nokogiri::XML::Node#ancestors answers a selector by walking to the document root and then calling root.search(selector) over the whole document, scanning the results for each ancestor (nokogiri/xml/node.rb:1344-1364). The search is not cached, so it runs once per geometry and the import costs geometries x document size.
Files where each Placemark holds one geometry never show it. Files exported from design software do: one Placemark is a <MultiGeometry> of hundreds of small faces, so a few thousand Placemarks become six figures of geometries in a document tens of megabytes wide, and the product dominates the import.
Measured with Nokogiri 1.19.4, on documents built by repeating the test.kml fixture's Placemark:
| Placemarks |
Parts each |
Geometries |
ancestors('Placemark') |
Parent walk |
| 100 |
20 |
2,000 |
0.21s |
0.0031s |
| 250 |
40 |
10,000 |
3.38s |
0.0045s |
| 500 |
40 |
20,000 |
14.44s |
0.0155s |
Geometries rise 10x from the first row to the last and the cost rises 69x, which is the quadratic.
On a 33.8 MB CAD-derived KML from a production deployment holding 75,407 polygons, the same call measures 10.1 ms each, or 758 seconds for that one file. It is roughly half the wall-clock of an import of that record that took 2h05m and held the deployment's only queue worker for the duration.
The nearest enclosing Placemark can be found by walking the parent chain, which is the same answer for a fraction of the cost and no change in behaviour.
🤖 Generated with Claude Code
https://claude.ai/code/session_012b7n8NbLAd6s7c3atii4Mv
SpatialFeatures::Importers::KML#each_recordresolves each geometry's Placemark withfeature.ancestors('Placemark').first.Nokogiri::XML::Node#ancestorsanswers a selector by walking to the document root and then callingroot.search(selector)over the whole document, scanning the results for each ancestor (nokogiri/xml/node.rb:1344-1364). The search is not cached, so it runs once per geometry and the import costs geometries x document size.Files where each Placemark holds one geometry never show it. Files exported from design software do: one Placemark is a
<MultiGeometry>of hundreds of small faces, so a few thousand Placemarks become six figures of geometries in a document tens of megabytes wide, and the product dominates the import.Measured with Nokogiri 1.19.4, on documents built by repeating the
test.kmlfixture's Placemark:ancestors('Placemark')Geometries rise 10x from the first row to the last and the cost rises 69x, which is the quadratic.
On a 33.8 MB CAD-derived KML from a production deployment holding 75,407 polygons, the same call measures 10.1 ms each, or 758 seconds for that one file. It is roughly half the wall-clock of an import of that record that took 2h05m and held the deployment's only queue worker for the duration.
The nearest enclosing Placemark can be found by walking the parent chain, which is the same answer for a fraction of the cost and no change in behaviour.
🤖 Generated with Claude Code
https://claude.ai/code/session_012b7n8NbLAd6s7c3atii4Mv