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),
[&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;
}
@ -324,7 +324,7 @@ class Contractor
const tbb::blocked_range<int> &range)
{
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] =
this->EvaluateNodePriority(data, &node_data[x], x);
@ -430,7 +430,7 @@ class Contractor
{
ContractorThreadData *data = thread_data_list.getThreadData();
// 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;
remaining_nodes[i].is_independent =
@ -451,7 +451,7 @@ class Contractor
[this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int> &range)
{
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;
this->ContractNode<false>(data, x);
@ -470,7 +470,7 @@ class Contractor
[this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int> &range)
{
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;
this->DeleteIncomingEdges(data, x);
@ -508,7 +508,7 @@ class Contractor
const tbb::blocked_range<int> &range)
{
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;
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](
const tbb::blocked_range<uint64_t> &range)
{
for (uint64_t element_counter = range.begin(); element_counter != range.end();
++element_counter)
for (uint64_t element_counter = range.begin(), end = range.end();
element_counter != end; ++element_counter)
{
WrappedInputElement &current_wrapper = input_wrapper_vector[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),
[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];
for (uint32_t j = 0; j < current_tree_node.child_count; ++j)
@ -664,7 +664,8 @@ class StaticRTree
while (!traversal_queue.empty())
{
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;
}
@ -760,7 +761,7 @@ class StaticRTree
// stop the search by flushing the queue
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>{};
}
@ -804,7 +805,8 @@ class StaticRTree
const IncrementalQueryCandidate current_query_node = traversal_queue.top();
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;
}

View File

@ -169,9 +169,12 @@ void ExtractionContainers::PrepareNodes()
external_to_internal_node_id_map.reserve(used_node_id_list.size());
auto node_iter = all_nodes_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;
// 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)
{
@ -208,7 +211,11 @@ void ExtractionContainers::PrepareEdges(lua_State *segment_state)
// Traverse list of edges and nodes in parallel and set start coord
auto node_iterator = all_nodes_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)
{
@ -259,7 +266,10 @@ void ExtractionContainers::PrepareEdges(lua_State *segment_state)
TIMER_START(compute_weights);
node_iterator = all_nodes_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
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
auto node_iterator = all_nodes_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)
{
@ -550,9 +563,11 @@ void ExtractionContainers::PrepareRestrictions()
TIMER_START(fix_restriction_starts);
auto restrictions_iterator = restrictions_list.begin();
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() &&
restrictions_iterator != 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.from.way)
{
@ -616,8 +631,11 @@ void ExtractionContainers::PrepareRestrictions()
TIMER_START(fix_restriction_ends);
restrictions_iterator = restrictions_list.begin();
way_start_and_end_iterator = way_start_end_id_list.cbegin();
while (way_start_and_end_iterator != way_start_end_id_list.cend() &&
restrictions_iterator != restrictions_list.end())
const auto way_start_end_id_list_end_ = way_start_end_id_list.cend();
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)
{

View File

@ -161,7 +161,7 @@ int extractor::run()
{
// create a vector of iterators into the buffer
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);
}
@ -180,7 +180,7 @@ int extractor::run()
ExtractionWay result_way;
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];

View File

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

View File

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