Skip to content

Decrease number of memory reallocations #1496

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions olp-cpp-sdk-dataservice-read/src/QueryMetadataJob.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 HERE Europe B.V.
* Copyright (C) 2020-2024 HERE Europe B.V.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -42,7 +42,7 @@ using QueryItemsFunc =
std::function<QueryResponseType(QueryType, client::CancellationContext)>;

template <typename QueryResponseType>
using FilterItemsFunc = std::function<QueryResponseType(QueryResponseType)>;
using FilterItemsFunc = std::function<void(QueryResponseType&)>;

using VectorOfTokens = std::vector<olp::client::CancellationToken>;

Expand Down Expand Up @@ -99,9 +99,13 @@ class QueryMetadataJob {
accumulated_statistics_ += GetNetworkStatistics(response);

if (response.IsSuccessful()) {
auto items = response.MoveResult();
std::move(items.begin(), items.end(),
std::inserter(query_result_, query_result_.begin()));
if (query_result_.empty()) {
query_result_ = response.MoveResult();
} else {
auto items = response.MoveResult();
std::move(items.begin(), items.end(),
std::inserter(query_result_, query_result_.begin()));
}
} else {
const auto& error = response.GetError();
if (error.GetErrorCode() == client::ErrorCode::Cancelled) {
Expand All @@ -125,7 +129,7 @@ class QueryMetadataJob {
}

if (filter_) {
query_result_ = filter_(std::move(query_result_));
filter_(query_result_);
}

if (query_result_.empty()) {
Expand Down
14 changes: 10 additions & 4 deletions olp-cpp-sdk-dataservice-read/src/VersionedLayerClientImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,11 +499,12 @@ client::CancellationToken VersionedLayerClientImpl::PrefetchTiles(

const bool aggregation_enabled = request.GetDataAggregationEnabled();

auto filter = [=](repository::SubQuadsResult tiles) mutable {
auto filter = [=](repository::SubQuadsResult& tiles) {
if (request_only_input_tiles) {
return repository.FilterTilesByList(request, std::move(tiles));
repository.FilterTilesByList(request, tiles);
} else {
repository.FilterTilesByLevel(request, tiles);
}
return repository.FilterTilesByLevel(request, std::move(tiles));
};

auto query = [=](geo::TileKey root,
Expand All @@ -512,8 +513,13 @@ client::CancellationToken VersionedLayerClientImpl::PrefetchTiles(
root, kQuadTreeDepth, version, inner_context);

if (response.IsSuccessful() && aggregation_enabled) {
const auto& tiles = response.GetResult();
auto network_stats = repository.LoadAggregatedSubQuads(
root, filter(response.GetResult()), version, inner_context);
root,
request_only_input_tiles
? repository.FilterTileKeysByList(request, tiles)
: repository.FilterTileKeysByLevel(request, tiles),
version, inner_context);

// append network statistics
network_stats += GetNetworkStatistics(response);
Expand Down
8 changes: 4 additions & 4 deletions olp-cpp-sdk-dataservice-read/src/VolatileLayerClientImpl.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2021 HERE Europe B.V.
* Copyright (C) 2019-2024 HERE Europe B.V.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -226,11 +226,11 @@ client::CancellationToken VolatileLayerClientImpl::PrefetchTiles(
inner_context);
};

auto filter = [=](repository::SubQuadsResult tiles) mutable {
auto filter = [=](repository::SubQuadsResult& tiles) {
if (request_only_input_tiles) {
return repository.FilterTilesByList(request, std::move(tiles));
repository.FilterTilesByList(request, tiles);
} else {
return repository.FilterTilesByLevel(request, std::move(tiles));
repository.FilterTilesByLevel(request, tiles);
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,14 @@ constexpr std::uint32_t kMaxQuadTreeIndexDepth = 4u;
SubQuadsResult FlattenTree(const QuadTreeIndex& tree) {
SubQuadsResult result;
auto index_data = tree.GetIndexData();
std::transform(index_data.begin(), index_data.end(),
std::inserter(result, result.end()),
[](const QuadTreeIndex::IndexData& data) {
return std::make_pair(data.tile_key, data.data_handle);
});
for (auto& data : index_data) {
const auto it = result.lower_bound(data.tile_key);
if (it == result.end() || result.key_comp()(data.tile_key, it->first)) {
result.emplace_hint(it, std::piecewise_construct,
std::forward_as_tuple(data.tile_key),
std::forward_as_tuple(std::move(data.data_handle)));
}
}
return result;
}

Expand Down Expand Up @@ -173,8 +176,8 @@ RootTilesForRequest PrefetchTilesRepository::GetSlicedTiles(
}

client::NetworkStatistics PrefetchTilesRepository::LoadAggregatedSubQuads(
geo::TileKey root, const SubQuadsResult& tiles, std::int64_t version,
client::CancellationContext context) {
geo::TileKey root, const std::vector<geo::TileKey>& tiles,
std::int64_t version, client::CancellationContext context) {
// if quad tree isn't cached, no reason to download additional quads
QuadTreeIndex quad_tree;
client::NetworkStatistics network_stats;
Expand All @@ -191,7 +194,7 @@ client::NetworkStatistics PrefetchTilesRepository::LoadAggregatedSubQuads(
// found in subtiles. In this way we make sure that all tiles within requested
// tree have aggregated parent downloaded and cached. This may cause
// additional or duplicate download request.
auto root_index = quad_tree.Find(highest_tile_it->first, true);
auto root_index = quad_tree.Find(*highest_tile_it, true);
if (root_index) {
const auto& aggregated_tile_key = root_index->tile_key;

Expand Down Expand Up @@ -316,89 +319,113 @@ SubQuadsResponse PrefetchTilesRepository::GetVolatileSubQuads(
return result;
}

SubQuadsResult PrefetchTilesRepository::FilterTilesByLevel(
const PrefetchTilesRequest& request, SubQuadsResult tiles) {
const auto& tile_keys = request.GetTileKeys();

auto skip_tile = [&](const geo::TileKey& tile_key) {
if (tile_key.Level() < request.GetMinLevel()) {
return true;
}

if (tile_key.Level() > request.GetMaxLevel()) {
return true;
}

return std::find_if(tile_keys.begin(), tile_keys.end(),
[&tile_key](const geo::TileKey& root_key) {
return (root_key.IsParentOf(tile_key) ||
tile_key.IsParentOf(root_key) ||
root_key == tile_key);
}) == tile_keys.end();
};
static bool skip_tile(const PrefetchTilesRequest& request,
const geo::TileKey& tile_key) {
if (tile_key.Level() < request.GetMinLevel() ||
tile_key.Level() > request.GetMaxLevel()) {
return true;
}
for (const geo::TileKey& root_key : request.GetTileKeys()) {
if (root_key == tile_key || root_key.IsParentOf(tile_key) ||
tile_key.IsParentOf(root_key))
return false;
}
return true;
}

void PrefetchTilesRepository::FilterTilesByLevel(
const PrefetchTilesRequest& request, SubQuadsResult& tiles) const {
for (auto sub_quad_it = tiles.begin(); sub_quad_it != tiles.end();) {
if (skip_tile(sub_quad_it->first)) {
if (skip_tile(request, sub_quad_it->first)) {
sub_quad_it = tiles.erase(sub_quad_it);
} else {
++sub_quad_it;
}
}
}

return tiles;
std::vector<geo::TileKey> PrefetchTilesRepository::FilterTileKeysByLevel(
const PrefetchTilesRequest& request, const SubQuadsResult& tiles) const {
std::vector<geo::TileKey> result;
for (const auto& tile : tiles) {
if (!skip_tile(request, tile.first)) {
result.emplace_back(tile.first);
}
}
return result;
}

SubQuadsResult PrefetchTilesRepository::FilterTilesByList(
const PrefetchTilesRequest& request, SubQuadsResult tiles) {
const bool aggregation_enabled = request.GetDataAggregationEnabled();
void PrefetchTilesRepository::FilterTilesByList(
const PrefetchTilesRequest& request, SubQuadsResult& tiles) const {
SubQuadsResult result;

const bool aggregation_enabled = request.GetDataAggregationEnabled();
const auto& tile_keys = request.GetTileKeys();

if (!aggregation_enabled) {
for (auto it = tiles.begin(); it != tiles.end();) {
if (std::find(tile_keys.begin(), tile_keys.end(), it->first) ==
tile_keys.end()) {
it = tiles.erase(it);
} else {
++it;
for (const auto& tile : tile_keys) {
const auto it = tiles.find(tile);
auto& new_tile = result[tile];
if (it != tiles.end()) {
new_tile = std::move(it->second);
tiles.erase(it);
}
}
} else {
auto append_tile = [&](const geo::TileKey& key) {
const auto it = tiles.find(key);
if (it != tiles.end()) {
result.emplace(key, std::move(it->second));
return true;
} else {
return result.find(key) != result.end();
}
};

for (const auto& tile : tile_keys) {
if (tiles.find(tile) == tiles.end()) {
tiles[tile] = "";
auto aggregated_tile = tile;

while (aggregated_tile.IsValid() && !append_tile(aggregated_tile)) {
aggregated_tile = aggregated_tile.Parent();
}

if (!aggregated_tile.IsValid()) {
result[tile].clear(); // To generate Not Found error
}
}
}
tiles.swap(result);
}

} else {
SubQuadsResult result;
std::vector<geo::TileKey> PrefetchTilesRepository::FilterTileKeysByList(
const PrefetchTilesRequest& request, const SubQuadsResult& tiles) const {
std::vector<geo::TileKey> result;

auto append_tile = [&](const geo::TileKey& key) {
auto tile_it = tiles.find(key);
if (tile_it != tiles.end()) {
result[tile_it->first] = tile_it->second;
if (!request.GetDataAggregationEnabled()) {
result = request.GetTileKeys();
} else {
auto append_tile = [&tiles, &result](const geo::TileKey& key) {
if (tiles.count(key) == 1) {
result.emplace_back(key);
return true;
} else {
return false;
return std::find(result.begin(), result.end(), key) != result.end();
}
};

for (const auto& tile : tile_keys) {
for (const auto& tile : request.GetTileKeys()) {
auto aggregated_tile = tile;

while (aggregated_tile.IsValid() && !append_tile(aggregated_tile)) {
aggregated_tile = aggregated_tile.Parent();
}

if (!aggregated_tile.IsValid()) {
result[tile] = ""; // To generate Not Found error
result.emplace_back(tile); // To generate Not Found error
}
}

tiles.swap(result);
}

return tiles;
return result;
}

PrefetchTilesRepository::QuadTreeResponse
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2021 HERE Europe B.V.
* Copyright (C) 2019-2024 HERE Europe B.V.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -21,6 +21,7 @@

#include <map>
#include <string>
#include <vector>

#include <olp/core/client/ApiError.h>
#include <olp/core/client/ApiLookupClient.h>
Expand Down Expand Up @@ -71,6 +72,18 @@ class PrefetchTilesRepository {
RootTilesForRequest GetSlicedTiles(const std::vector<geo::TileKey>& tile_keys,
std::uint32_t min, std::uint32_t max);

/**
* @brief Filters the input tiles according to the request.
*
* Removes tiles that do not belong to the minimum and maximum levels.
* Removes tiles that are not a child or a parent of the requested tiles.
*
* @param request Your request.
* @param tiles The input tiles.
*/
void FilterTilesByLevel(const PrefetchTilesRequest& request,
SubQuadsResult& tiles) const;

/**
* @brief Filters the input tiles according to the request.
*
Expand All @@ -80,10 +93,10 @@ class PrefetchTilesRepository {
* @param request Your request.
* @param tiles The input tiles.
*
* @returns The modified tiles.
* @returns Tile keys matching the request.
*/
SubQuadsResult FilterTilesByLevel(const PrefetchTilesRequest& request,
SubQuadsResult tiles);
std::vector<geo::TileKey> FilterTileKeysByLevel(
const PrefetchTilesRequest& request, const SubQuadsResult& tiles) const;

/**
* @brief Filters the input tiles according to the request.
Expand All @@ -94,15 +107,28 @@ class PrefetchTilesRepository {
*
* @param request Your request.
* @param tiles The input tiles.
*/
void FilterTilesByList(const PrefetchTilesRequest& request,
SubQuadsResult& tiles) const;

/**
* @brief Filters the input tiles according to the request.
*
* Removes tile keys that are not requested.
* Adds tile keys that are missing (to notify you that they are not found).
* If aggregated tiles were requested, scans for parents.
*
* @returns The modified tiles.
* @param request Your request.
* @param tiles The input tiles.
*
* @returns Tile keys matching the request.
*/
SubQuadsResult FilterTilesByList(const PrefetchTilesRequest& request,
SubQuadsResult tiles);
std::vector<geo::TileKey> FilterTileKeysByList(
const PrefetchTilesRequest& request, const SubQuadsResult& tiles) const;

client::NetworkStatistics LoadAggregatedSubQuads(
geo::TileKey tile, const SubQuadsResult& tiles, std::int64_t version,
client::CancellationContext context);
geo::TileKey tile, const std::vector<geo::TileKey>& tiles,
std::int64_t version, client::CancellationContext context);

SubQuadsResponse GetVersionedSubQuads(geo::TileKey tile, int32_t depth,
std::int64_t version,
Expand Down
Loading
Loading