From a0a2a513b2116dc25e8bafdf91e02fa142f6cddd Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Mon, 6 May 2024 16:45:26 -0700 Subject: [PATCH] Reduce memory use of `GridIndex` (#2362) --- src/mbgl/gfx/index_vector.hpp | 2 ++ src/mbgl/gfx/polyline_generator.cpp | 15 +++++++++++++- src/mbgl/renderer/paint_property_binder.hpp | 9 ++++++--- src/mbgl/text/cross_tile_symbol_index.cpp | 4 ++-- src/mbgl/text/cross_tile_symbol_index.hpp | 2 +- src/mbgl/util/grid_index.hpp | 22 +++++++++++---------- 6 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/mbgl/gfx/index_vector.hpp b/src/mbgl/gfx/index_vector.hpp index 4f67ab053..3f20c8076 100644 --- a/src/mbgl/gfx/index_vector.hpp +++ b/src/mbgl/gfx/index_vector.hpp @@ -45,6 +45,8 @@ public: bool isReleased() const { return released; } + void reserve(std::size_t count) { v.reserve(count); } + void extend(std::size_t n, const uint16_t val) { assert(!released); v.resize(v.size() + n, val); diff --git a/src/mbgl/gfx/polyline_generator.cpp b/src/mbgl/gfx/polyline_generator.cpp index beac5d577..7a7ac7b84 100644 --- a/src/mbgl/gfx/polyline_generator.cpp +++ b/src/mbgl/gfx/polyline_generator.cpp @@ -138,6 +138,16 @@ void PolylineGenerator::generate(const GeometryCoordinates& coordinates const std::size_t startVertex = vertices.elements(); std::vector triangleStore; + // Pre-allocate for triangles based on measuring benchmark execution + constexpr auto approxTrianglesPerSegment = 6; + triangleStore.reserve((len - first) * approxTrianglesPerSegment); + + // Vertex count depends on length rather than segment count, and two elements often generates + // thousands of vertices, so we allocate some extra memory to skip the next 10 allocations. + if (vertices.empty()) { + vertices.reserve(1 << 10); + } + for (std::size_t i = first; i < len; ++i) { if (options.type == FeatureType::Polygon && i == len - 1) { // if the line is closed, we treat the last vertex like the first @@ -533,6 +543,9 @@ void PolylineGenerator::generate(const GeometryCoordinates& coordinates assert(segment.vertexLength <= std::numeric_limits::max()); const uint16_t index = static_cast(segment.vertexLength); + if (indexes.empty()) { + indexes.reserve(triangleStore.size() * 3); + } for (const auto& triangle : triangleStore) { indexes.emplace_back(index + triangle.a, index + triangle.b, index + triangle.c); } @@ -552,7 +565,7 @@ void PolylineGenerator::addCurrentVertex(const GeometryCoordinate& curr std::vector& triangleStore, std::optional lineDistances) { Point extrude = normal; - double scaledDistance = lineDistances ? lineDistances->scaleToMaxLineDistance(distance) : distance; + const double scaledDistance = lineDistances ? lineDistances->scaleToMaxLineDistance(distance) : distance; if (endLeft) extrude = extrude - (util::perp(normal) * endLeft); vertices.emplace_back(layoutVertex(currentCoordinate, diff --git a/src/mbgl/renderer/paint_property_binder.hpp b/src/mbgl/renderer/paint_property_binder.hpp index 0c9b89ce9..3a2cadcf4 100644 --- a/src/mbgl/renderer/paint_property_binder.hpp +++ b/src/mbgl/renderer/paint_property_binder.hpp @@ -178,7 +178,7 @@ public: void setPatternParameters(const std::optional&, const std::optional&, - const CrossfadeParameters&) override {}; + const CrossfadeParameters&) override {} std::tuple interpolationFactor(float) const override { return std::tuple{0.0f}; } @@ -272,7 +272,7 @@ public: void setPatternParameters(const std::optional&, const std::optional&, - const CrossfadeParameters&) override {}; + const CrossfadeParameters&) override {} void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, std::size_t index, @@ -391,7 +391,7 @@ public: void setPatternParameters(const std::optional&, const std::optional&, - const CrossfadeParameters&) override {}; + const CrossfadeParameters&) override {} void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, std::size_t index, @@ -415,6 +415,9 @@ public: const AttributeValue value = zoomInterpolatedAttributeValue(attributeValue(range.min), attributeValue(range.max)); const auto elements = vertexVector.elements(); + if (vertexVector.empty()) { + vertexVector.reserve(length); + } for (std::size_t i = elements; i < length; ++i) { vertexVector.emplace_back(Vertex{value}); } diff --git a/src/mbgl/text/cross_tile_symbol_index.cpp b/src/mbgl/text/cross_tile_symbol_index.cpp index f2b137da4..a0906a98c 100644 --- a/src/mbgl/text/cross_tile_symbol_index.cpp +++ b/src/mbgl/text/cross_tile_symbol_index.cpp @@ -13,14 +13,14 @@ TileLayerIndex::TileLayerIndex(OverscaledTileID coord_, : coord(coord_), bucketInstanceId(bucketInstanceId_), bucketLeaderId(std::move(bucketLeaderId_)) { - for (SymbolInstance& symbolInstance : symbolInstances) { + for (const SymbolInstance& symbolInstance : symbolInstances) { if (symbolInstance.crossTileID == SymbolInstance::invalidCrossTileID()) continue; indexedSymbolInstances[symbolInstance.key].emplace_back(symbolInstance.crossTileID, getScaledCoordinates(symbolInstance, coord)); } } -Point TileLayerIndex::getScaledCoordinates(SymbolInstance& symbolInstance, +Point TileLayerIndex::getScaledCoordinates(const SymbolInstance& symbolInstance, const OverscaledTileID& childTileCoord) const { // Round anchor positions to roughly 4 pixel grid const double roundingFactor = 512.0 / util::EXTENT / 2.0; diff --git a/src/mbgl/text/cross_tile_symbol_index.hpp b/src/mbgl/text/cross_tile_symbol_index.hpp index 8869e1781..ae7d40fc3 100644 --- a/src/mbgl/text/cross_tile_symbol_index.hpp +++ b/src/mbgl/text/cross_tile_symbol_index.hpp @@ -36,7 +36,7 @@ public: uint32_t bucketInstanceId, std::string bucketLeaderId); - Point getScaledCoordinates(SymbolInstance&, const OverscaledTileID&) const; + Point getScaledCoordinates(const SymbolInstance&, const OverscaledTileID&) const; void findMatches(SymbolBucket&, const OverscaledTileID&, std::set&) const; OverscaledTileID coord; diff --git a/src/mbgl/util/grid_index.hpp b/src/mbgl/util/grid_index.hpp index 6e987d7b7..f7426e4b8 100644 --- a/src/mbgl/util/grid_index.hpp +++ b/src/mbgl/util/grid_index.hpp @@ -4,14 +4,14 @@ #include #include -#include +#include #include -#include #include -#include +#include #include #include -#include +#include +#include namespace mbgl { @@ -103,8 +103,8 @@ private: std::vector> boxElements; std::vector> circleElements; - std::vector> boxCells; - std::vector> circleCells; + std::vector> boxCells; + std::vector> circleCells; }; template @@ -123,7 +123,8 @@ GridIndex::GridIndex(const float width_, const float height_, const uint32_t template void GridIndex::insert(T&& t, const BBox& bbox) { - const size_t uid = boxElements.size(); + assert(boxElements.size() < std::numeric_limits::max()); + const auto uid = static_cast(boxElements.size()); const auto cx1 = convertToXCellCoord(bbox.min.x); const auto cy1 = convertToYCellCoord(bbox.min.y); @@ -145,7 +146,8 @@ void GridIndex::insert(T&& t, const BBox& bbox) { template void GridIndex::insert(T&& t, const BCircle& bcircle) { - const size_t uid = circleElements.size(); + assert(circleElements.size() < std::numeric_limits::max()); + const auto uid = static_cast(circleElements.size()); const auto cx1 = convertToXCellCoord(bcircle.center.x - bcircle.radius); const auto cy1 = convertToYCellCoord(bcircle.center.y - bcircle.radius); @@ -231,8 +233,8 @@ typename GridIndex::BBox GridIndex::convertToBox(const BCircle& circle) co template void GridIndex::query(const BBox& queryBBox, std::function resultFn) const { - std::unordered_set seenBoxes; - std::unordered_set seenCircles; + std::unordered_set seenBoxes; + std::unordered_set seenCircles; if (noIntersection(queryBBox)) { return;