Reduce memory use of GridIndex (#2362)

This commit is contained in:
Tim Sylvester
2024-05-06 16:45:26 -07:00
committed by GitHub
parent db1f47ab11
commit a0a2a513b2
6 changed files with 37 additions and 17 deletions

View File

@@ -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);

View File

@@ -138,6 +138,16 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
const std::size_t startVertex = vertices.elements();
std::vector<TriangleElement> 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<PLV, PS>::generate(const GeometryCoordinates& coordinates
assert(segment.vertexLength <= std::numeric_limits<uint16_t>::max());
const uint16_t index = static_cast<uint16_t>(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<PLV, PS>::addCurrentVertex(const GeometryCoordinate& curr
std::vector<TriangleElement>& triangleStore,
std::optional<PolylineGeneratorDistances> lineDistances) {
Point<double> 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,

View File

@@ -178,7 +178,7 @@ public:
void setPatternParameters(const std::optional<ImagePosition>&,
const std::optional<ImagePosition>&,
const CrossfadeParameters&) override {};
const CrossfadeParameters&) override {}
std::tuple<float> interpolationFactor(float) const override { return std::tuple<float>{0.0f}; }
@@ -272,7 +272,7 @@ public:
void setPatternParameters(const std::optional<ImagePosition>&,
const std::optional<ImagePosition>&,
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<ImagePosition>&,
const std::optional<ImagePosition>&,
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});
}

View File

@@ -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<int64_t> TileLayerIndex::getScaledCoordinates(SymbolInstance& symbolInstance,
Point<int64_t> 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;

View File

@@ -36,7 +36,7 @@ public:
uint32_t bucketInstanceId,
std::string bucketLeaderId);
Point<int64_t> getScaledCoordinates(SymbolInstance&, const OverscaledTileID&) const;
Point<int64_t> getScaledCoordinates(const SymbolInstance&, const OverscaledTileID&) const;
void findMatches(SymbolBucket&, const OverscaledTileID&, std::set<uint32_t>&) const;
OverscaledTileID coord;

View File

@@ -4,14 +4,14 @@
#include <mapbox/geometry/box.hpp>
#include <mbgl/math/minmax.hpp>
#include <unordered_set>
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstddef>
#include <vector>
#include <cstdint>
#include <functional>
#include <optional>
#include <cassert>
#include <unordered_set>
#include <vector>
namespace mbgl {
@@ -103,8 +103,8 @@ private:
std::vector<std::pair<T, BBox>> boxElements;
std::vector<std::pair<T, BCircle>> circleElements;
std::vector<std::vector<size_t>> boxCells;
std::vector<std::vector<size_t>> circleCells;
std::vector<std::vector<uint32_t>> boxCells;
std::vector<std::vector<uint32_t>> circleCells;
};
template <class T>
@@ -123,7 +123,8 @@ GridIndex<T>::GridIndex(const float width_, const float height_, const uint32_t
template <class T>
void GridIndex<T>::insert(T&& t, const BBox& bbox) {
const size_t uid = boxElements.size();
assert(boxElements.size() < std::numeric_limits<uint32_t>::max());
const auto uid = static_cast<uint32_t>(boxElements.size());
const auto cx1 = convertToXCellCoord(bbox.min.x);
const auto cy1 = convertToYCellCoord(bbox.min.y);
@@ -145,7 +146,8 @@ void GridIndex<T>::insert(T&& t, const BBox& bbox) {
template <class T>
void GridIndex<T>::insert(T&& t, const BCircle& bcircle) {
const size_t uid = circleElements.size();
assert(circleElements.size() < std::numeric_limits<uint32_t>::max());
const auto uid = static_cast<uint32_t>(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<T>::BBox GridIndex<T>::convertToBox(const BCircle& circle) co
template <class T>
void GridIndex<T>::query(const BBox& queryBBox, std::function<bool(const T&, const BBox&)> resultFn) const {
std::unordered_set<size_t> seenBoxes;
std::unordered_set<size_t> seenCircles;
std::unordered_set<uint32_t> seenBoxes;
std::unordered_set<uint32_t> seenCircles;
if (noIntersection(queryBBox)) {
return;