Caches iterators instead of invoking function calls on every iteration.

This caches iterators, i.e. especially the end iterator when possible.

The problem:

    for (auto it = begin(seq); it != end(seq); ++it)

this has to call `end(seq)` on every iteration, since the compiler is
not able to reason about the call's site effects (to bad, huh).

Instead do it like this:

    for (auto it = begin(seq), end = end(seq); it != end; ++it)

caching the end iterator.

Of course, still better would be:

    for (auto&& each : seq)

if all you want is value semantics.

Why `auto&&` you may ask? Because it binds to everything and never copies!

Skim the referenced proposal (that was rejected, but nevertheless) for a
detailed explanation on range-based for loops and why `auto&&` is great.

Reference:

- http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3853.htm
This commit is contained in:
Daniel J. Hofmann 2015-09-15 01:13:31 +02:00
parent 8e02263084
commit 94af9b7f13
7 changed files with 66 additions and 56 deletions

View File

@ -312,7 +312,7 @@ class Contractor
tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, InitGrainSize), tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, InitGrainSize),
[&remaining_nodes](const tbb::blocked_range<int> &range) [&remaining_nodes](const tbb::blocked_range<int> &range)
{ {
for (int x = range.begin(); x != range.end(); ++x) for (int x = range.begin(), end = range.end(); x != end; ++x)
{ {
remaining_nodes[x].id = x; remaining_nodes[x].id = x;
} }
@ -324,7 +324,7 @@ class Contractor
const tbb::blocked_range<int> &range) const tbb::blocked_range<int> &range)
{ {
ContractorThreadData *data = thread_data_list.getThreadData(); ContractorThreadData *data = thread_data_list.getThreadData();
for (int x = range.begin(); x != range.end(); ++x) for (int x = range.begin(), end = range.end(); x != end; ++x)
{ {
node_priorities[x] = node_priorities[x] =
this->EvaluateNodePriority(data, &node_data[x], x); this->EvaluateNodePriority(data, &node_data[x], x);
@ -430,7 +430,7 @@ class Contractor
{ {
ContractorThreadData *data = thread_data_list.getThreadData(); ContractorThreadData *data = thread_data_list.getThreadData();
// determine independent node set // determine independent node set
for (int i = range.begin(); i != range.end(); ++i) for (int i = range.begin(), end = range.end(); i != end; ++i)
{ {
const NodeID node = remaining_nodes[i].id; const NodeID node = remaining_nodes[i].id;
remaining_nodes[i].is_independent = remaining_nodes[i].is_independent =
@ -451,7 +451,7 @@ class Contractor
[this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int> &range) [this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int> &range)
{ {
ContractorThreadData *data = thread_data_list.getThreadData(); ContractorThreadData *data = thread_data_list.getThreadData();
for (int position = range.begin(); position != range.end(); ++position) for (int position = range.begin(), end = range.end(); position != end; ++position)
{ {
const NodeID x = remaining_nodes[position].id; const NodeID x = remaining_nodes[position].id;
this->ContractNode<false>(data, x); this->ContractNode<false>(data, x);
@ -470,7 +470,7 @@ class Contractor
[this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int> &range) [this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int> &range)
{ {
ContractorThreadData *data = thread_data_list.getThreadData(); ContractorThreadData *data = thread_data_list.getThreadData();
for (int position = range.begin(); position != range.end(); ++position) for (int position = range.begin(), end = range.end(); position != end; ++position)
{ {
const NodeID x = remaining_nodes[position].id; const NodeID x = remaining_nodes[position].id;
this->DeleteIncomingEdges(data, x); this->DeleteIncomingEdges(data, x);
@ -508,7 +508,7 @@ class Contractor
const tbb::blocked_range<int> &range) const tbb::blocked_range<int> &range)
{ {
ContractorThreadData *data = thread_data_list.getThreadData(); ContractorThreadData *data = thread_data_list.getThreadData();
for (int position = range.begin(); position != range.end(); ++position) for (int position = range.begin(), end = range.end(); position != end; ++position)
{ {
NodeID x = remaining_nodes[position].id; NodeID x = remaining_nodes[position].id;
this->UpdateNodeNeighbours(node_priorities, node_data, data, x); this->UpdateNodeNeighbours(node_priorities, node_data, data, x);

View File

@ -365,8 +365,8 @@ class StaticRTree
[&input_data_vector, &input_wrapper_vector, &get_hilbert_number, &coordinate_list]( [&input_data_vector, &input_wrapper_vector, &get_hilbert_number, &coordinate_list](
const tbb::blocked_range<uint64_t> &range) const tbb::blocked_range<uint64_t> &range)
{ {
for (uint64_t element_counter = range.begin(); element_counter != range.end(); for (uint64_t element_counter = range.begin(), end = range.end();
++element_counter) element_counter != end; ++element_counter)
{ {
WrappedInputElement &current_wrapper = input_wrapper_vector[element_counter]; WrappedInputElement &current_wrapper = input_wrapper_vector[element_counter];
current_wrapper.m_array_index = element_counter; current_wrapper.m_array_index = element_counter;
@ -476,7 +476,7 @@ class StaticRTree
tbb::parallel_for(tbb::blocked_range<uint32_t>(0, search_tree_size), tbb::parallel_for(tbb::blocked_range<uint32_t>(0, search_tree_size),
[this, &search_tree_size](const tbb::blocked_range<uint32_t> &range) [this, &search_tree_size](const tbb::blocked_range<uint32_t> &range)
{ {
for (uint32_t i = range.begin(); i != range.end(); ++i) for (uint32_t i = range.begin(), end = range.end(); i != end; ++i)
{ {
TreeNode &current_tree_node = this->m_search_tree[i]; TreeNode &current_tree_node = this->m_search_tree[i];
for (uint32_t j = 0; j < current_tree_node.child_count; ++j) for (uint32_t j = 0; j < current_tree_node.child_count; ++j)
@ -664,7 +664,8 @@ class StaticRTree
while (!traversal_queue.empty()) while (!traversal_queue.empty())
{ {
const IncrementalQueryCandidate current_query_node = traversal_queue.top(); const IncrementalQueryCandidate current_query_node = traversal_queue.top();
if (current_query_node.min_dist > max_distance && inspected_elements > max_checked_elements) if (current_query_node.min_dist > max_distance &&
inspected_elements > max_checked_elements)
{ {
break; break;
} }
@ -760,7 +761,7 @@ class StaticRTree
// stop the search by flushing the queue // stop the search by flushing the queue
if (result_phantom_node_vector.size() >= max_number_of_phantom_nodes && if (result_phantom_node_vector.size() >= max_number_of_phantom_nodes &&
number_of_elements_from_big_cc > 0) number_of_elements_from_big_cc > 0)
{ {
traversal_queue = std::priority_queue<IncrementalQueryCandidate>{}; traversal_queue = std::priority_queue<IncrementalQueryCandidate>{};
} }
@ -804,7 +805,8 @@ class StaticRTree
const IncrementalQueryCandidate current_query_node = traversal_queue.top(); const IncrementalQueryCandidate current_query_node = traversal_queue.top();
traversal_queue.pop(); traversal_queue.pop();
if (current_query_node.min_dist > max_distance || inspected_elements >= max_checked_elements) if (current_query_node.min_dist > max_distance ||
inspected_elements >= max_checked_elements)
{ {
break; break;
} }

View File

@ -169,9 +169,12 @@ void ExtractionContainers::PrepareNodes()
external_to_internal_node_id_map.reserve(used_node_id_list.size()); external_to_internal_node_id_map.reserve(used_node_id_list.size());
auto node_iter = all_nodes_list.begin(); auto node_iter = all_nodes_list.begin();
auto ref_iter = used_node_id_list.begin(); auto ref_iter = used_node_id_list.begin();
const auto all_nodes_list_end = all_nodes_list.end();
const auto used_node_id_list_end = used_node_id_list.end();
auto internal_id = 0u; auto internal_id = 0u;
// compute the intersection of nodes that were referenced and nodes we actually have // compute the intersection of nodes that were referenced and nodes we actually have
while (node_iter != all_nodes_list.end() && ref_iter != used_node_id_list.end()) while (node_iter != all_nodes_list_end && ref_iter != used_node_id_list_end)
{ {
if (node_iter->node_id < *ref_iter) if (node_iter->node_id < *ref_iter)
{ {
@ -208,7 +211,11 @@ void ExtractionContainers::PrepareEdges(lua_State *segment_state)
// Traverse list of edges and nodes in parallel and set start coord // Traverse list of edges and nodes in parallel and set start coord
auto node_iterator = all_nodes_list.begin(); auto node_iterator = all_nodes_list.begin();
auto edge_iterator = all_edges_list.begin(); auto edge_iterator = all_edges_list.begin();
while (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end())
const auto all_edges_list_end = all_edges_list.end();
const auto all_nodes_list_end = all_nodes_list.end();
while (edge_iterator != all_edges_list_end && node_iterator != all_nodes_list_end)
{ {
if (edge_iterator->result.source < node_iterator->node_id) if (edge_iterator->result.source < node_iterator->node_id)
{ {
@ -259,7 +266,10 @@ void ExtractionContainers::PrepareEdges(lua_State *segment_state)
TIMER_START(compute_weights); TIMER_START(compute_weights);
node_iterator = all_nodes_list.begin(); node_iterator = all_nodes_list.begin();
edge_iterator = all_edges_list.begin(); edge_iterator = all_edges_list.begin();
while (edge_iterator != all_edges_list.end() && node_iterator != all_nodes_list.end()) const auto all_edges_list_end_ = all_edges_list.end();
const auto all_nodes_list_end_ = all_nodes_list.end();
while (edge_iterator != all_edges_list_end_ && node_iterator != all_nodes_list_end_)
{ {
// skip all invalid edges // skip all invalid edges
if (edge_iterator->result.source == SPECIAL_NODEID) if (edge_iterator->result.source == SPECIAL_NODEID)
@ -475,7 +485,10 @@ void ExtractionContainers::WriteNodes(std::ofstream& file_out_stream) const
// identify all used nodes by a merging step of two sorted lists // identify all used nodes by a merging step of two sorted lists
auto node_iterator = all_nodes_list.begin(); auto node_iterator = all_nodes_list.begin();
auto node_id_iterator = used_node_id_list.begin(); auto node_id_iterator = used_node_id_list.begin();
while (node_id_iterator != used_node_id_list.end() && node_iterator != all_nodes_list.end()) const auto used_node_id_list_end = used_node_id_list.end();
const auto all_nodes_list_end = all_nodes_list.end();
while (node_id_iterator != used_node_id_list_end && node_iterator != all_nodes_list_end)
{ {
if (*node_id_iterator < node_iterator->node_id) if (*node_id_iterator < node_iterator->node_id)
{ {
@ -550,9 +563,11 @@ void ExtractionContainers::PrepareRestrictions()
TIMER_START(fix_restriction_starts); TIMER_START(fix_restriction_starts);
auto restrictions_iterator = restrictions_list.begin(); auto restrictions_iterator = restrictions_list.begin();
auto way_start_and_end_iterator = way_start_end_id_list.cbegin(); auto way_start_and_end_iterator = way_start_end_id_list.cbegin();
const auto restrictions_list_end = restrictions_list.end();
const auto way_start_end_id_list_end = way_start_end_id_list.cend();
while (way_start_and_end_iterator != way_start_end_id_list.cend() && while (way_start_and_end_iterator != way_start_end_id_list_end &&
restrictions_iterator != restrictions_list.end()) restrictions_iterator != restrictions_list_end)
{ {
if (way_start_and_end_iterator->way_id < restrictions_iterator->restriction.from.way) if (way_start_and_end_iterator->way_id < restrictions_iterator->restriction.from.way)
{ {
@ -616,8 +631,11 @@ void ExtractionContainers::PrepareRestrictions()
TIMER_START(fix_restriction_ends); TIMER_START(fix_restriction_ends);
restrictions_iterator = restrictions_list.begin(); restrictions_iterator = restrictions_list.begin();
way_start_and_end_iterator = way_start_end_id_list.cbegin(); way_start_and_end_iterator = way_start_end_id_list.cbegin();
while (way_start_and_end_iterator != way_start_end_id_list.cend() && const auto way_start_end_id_list_end_ = way_start_end_id_list.cend();
restrictions_iterator != restrictions_list.end()) const auto restrictions_list_end_ = restrictions_list.end();
while (way_start_and_end_iterator != way_start_end_id_list_end_ &&
restrictions_iterator != restrictions_list_end_)
{ {
if (way_start_and_end_iterator->way_id < restrictions_iterator->restriction.to.way) if (way_start_and_end_iterator->way_id < restrictions_iterator->restriction.to.way)
{ {

View File

@ -161,7 +161,7 @@ int extractor::run()
{ {
// create a vector of iterators into the buffer // create a vector of iterators into the buffer
std::vector<osmium::memory::Buffer::const_iterator> osm_elements; std::vector<osmium::memory::Buffer::const_iterator> osm_elements;
for (auto iter = std::begin(buffer); iter != std::end(buffer); ++iter) for (auto iter = std::begin(buffer), end = std::end(buffer); iter != end; ++iter)
{ {
osm_elements.push_back(iter); osm_elements.push_back(iter);
} }
@ -180,7 +180,7 @@ int extractor::run()
ExtractionWay result_way; ExtractionWay result_way;
lua_State *local_state = scripting_environment.get_lua_state(); lua_State *local_state = scripting_environment.get_lua_state();
for (auto x = range.begin(); x != range.end(); ++x) for (auto x = range.begin(), end = range.end(); x != end; ++x)
{ {
const auto entity = osm_elements[x]; const auto entity = osm_elements[x];

View File

@ -61,12 +61,11 @@ struct Renderer : mapbox::util::static_visitor<>
void operator()(const Object &object) const void operator()(const Object &object) const
{ {
out << "{"; out << "{";
auto iterator = object.values.begin(); for (auto it = object.values.begin(), end = object.values.end(); it != end;)
while (iterator != object.values.end())
{ {
out << "\"" << (*iterator).first << "\":"; out << "\"" << it->first << "\":";
mapbox::util::apply_visitor(Renderer(out), (*iterator).second); mapbox::util::apply_visitor(Renderer(out), it->second);
if (++iterator != object.values.end()) if (++it != end)
{ {
out << ","; out << ",";
} }
@ -77,12 +76,10 @@ struct Renderer : mapbox::util::static_visitor<>
void operator()(const Array &array) const void operator()(const Array &array) const
{ {
out << "["; out << "[";
std::vector<Value>::const_iterator iterator; for (auto it = array.values.cend(), end = array.values.cend(); it != end;)
iterator = array.values.begin();
while (iterator != array.values.end())
{ {
mapbox::util::apply_visitor(Renderer(out), *iterator); mapbox::util::apply_visitor(Renderer(out), *it);
if (++iterator != array.values.end()) if (++it != end)
{ {
out << ","; out << ",";
} }
@ -121,16 +118,15 @@ struct ArrayRenderer : mapbox::util::static_visitor<>
void operator()(const Object &object) const void operator()(const Object &object) const
{ {
out.push_back('{'); out.push_back('{');
auto iterator = object.values.begin(); for (auto it = object.values.begin(), end = object.values.end(); it != end;)
while (iterator != object.values.end())
{ {
out.push_back('\"'); out.push_back('\"');
out.insert(out.end(), (*iterator).first.begin(), (*iterator).first.end()); out.insert(out.end(), it->first.begin(), it->first.end());
out.push_back('\"'); out.push_back('\"');
out.push_back(':'); out.push_back(':');
mapbox::util::apply_visitor(ArrayRenderer(out), (*iterator).second); mapbox::util::apply_visitor(ArrayRenderer(out), it->second);
if (++iterator != object.values.end()) if (++it != end)
{ {
out.push_back(','); out.push_back(',');
} }
@ -141,12 +137,10 @@ struct ArrayRenderer : mapbox::util::static_visitor<>
void operator()(const Array &array) const void operator()(const Array &array) const
{ {
out.push_back('['); out.push_back('[');
std::vector<Value>::const_iterator iterator; for (auto it = array.values.cbegin(), end = array.values.cend(); it != end;)
iterator = array.values.begin();
while (iterator != array.values.end())
{ {
mapbox::util::apply_visitor(ArrayRenderer(out), *iterator); mapbox::util::apply_visitor(ArrayRenderer(out), *it);
if (++iterator != array.values.end()) if (++it != end)
{ {
out.push_back(','); out.push_back(',');
} }

View File

@ -132,9 +132,10 @@ inline std::string escape_JSON(const std::string &input)
inline std::size_t URIDecode(const std::string &input, std::string &output) inline std::size_t URIDecode(const std::string &input, std::string &output)
{ {
auto src_iter = std::begin(input); auto src_iter = std::begin(input);
const auto src_end = std::end(input);
output.resize(input.size() + 1); output.resize(input.size() + 1);
std::size_t decoded_length = 0; std::size_t decoded_length = 0;
for (decoded_length = 0; src_iter != std::end(input); ++decoded_length) for (decoded_length = 0; src_iter != src_end; ++decoded_length)
{ {
if (src_iter[0] == '%' && src_iter[1] && src_iter[2] && isxdigit(src_iter[1]) && if (src_iter[0] == '%' && src_iter[1] && src_iter[2] && isxdigit(src_iter[1]) &&
isxdigit(src_iter[2])) isxdigit(src_iter[2]))

View File

@ -56,38 +56,33 @@ struct XMLToArrayRenderer : mapbox::util::static_visitor<>
void operator()(const Object &object) const void operator()(const Object &object) const
{ {
auto iterator = object.values.begin(); for (auto &&each : object.values)
while (iterator != object.values.end())
{ {
if (iterator->first.at(0) != '_') if (each.first.at(0) != '_')
{ {
out.push_back('<'); out.push_back('<');
out.insert(out.end(), (*iterator).first.begin(), (*iterator).first.end()); out.insert(out.end(), each.first.begin(), each.first.end());
} }
else else
{ {
out.push_back(' '); out.push_back(' ');
out.insert(out.end(), ++(*iterator).first.begin(), (*iterator).first.end()); out.insert(out.end(), ++(each).first.begin(), each.first.end());
out.push_back('='); out.push_back('=');
} }
mapbox::util::apply_visitor(XMLToArrayRenderer(out), (*iterator).second); mapbox::util::apply_visitor(XMLToArrayRenderer(out), each.second);
if (iterator->first.at(0) != '_') if (each.first.at(0) != '_')
{ {
out.push_back('/'); out.push_back('/');
out.push_back('>'); out.push_back('>');
} }
++iterator;
} }
} }
void operator()(const Array &array) const void operator()(const Array &array) const
{ {
std::vector<Value>::const_iterator iterator; for (auto &&each : array.values)
iterator = array.values.begin();
while (iterator != array.values.end())
{ {
mapbox::util::apply_visitor(XMLToArrayRenderer(out), *iterator); mapbox::util::apply_visitor(XMLToArrayRenderer(out), each);
++iterator;
} }
} }