reduce size of InternalExtractorEdge by using single-precision values

This commit is contained in:
Michael Krasnyk 2017-02-02 17:05:08 +01:00 committed by Patrick Niklaus
parent 5f1c7efd41
commit c48fc58eb2
4 changed files with 41 additions and 27 deletions

View File

@ -20,23 +20,37 @@ namespace extractor
namespace detail namespace detail
{ {
// these are used for duration based mode of transportations like ferries // Use a single float to pack two positive values:
OSRM_STRONG_TYPEDEF(double, ValueByEdge) // * by_edge: + sign, value >= 0, value used as the edge weight
OSRM_STRONG_TYPEDEF(double, ValueByMeter) // * by_meter: - sign, value > 0, value used as a denominator in distance / value
using ByEdgeOrByMeterValue = mapbox::util::variant<detail::ValueByEdge, detail::ValueByMeter>; struct ByEdgeOrByMeterValue
struct ToValueByEdge
{ {
ToValueByEdge(double distance_) : distance(distance_) {} struct ValueByEdge
ValueByEdge operator()(const ValueByMeter by_meter) const
{ {
return ValueByEdge{distance / static_cast<double>(by_meter)}; } static const by_edge;
struct ValueByMeter
{
} static const by_meter;
ByEdgeOrByMeterValue() : value(0.f) {}
ByEdgeOrByMeterValue(ValueByEdge, double input)
{
BOOST_ASSERT(input >= 0.f);
value = static_cast<value_type>(input);
} }
ValueByEdge operator()(const ValueByEdge by_edge) const { return by_edge; } ByEdgeOrByMeterValue(ValueByMeter, double input)
{
BOOST_ASSERT(input > 0.f);
value = -static_cast<value_type>(input);
}
double distance; double operator()(double distance) { return value >= 0 ? value : -distance / value; }
private:
using value_type = float;
value_type value;
}; };
} }
@ -60,7 +74,7 @@ struct InternalExtractorEdge
false, false,
guidance::TurnLaneType::empty, guidance::TurnLaneType::empty,
guidance::RoadClassification()), guidance::RoadClassification()),
weight_data(detail::ValueByMeter{0.0}), duration_data(detail::ValueByMeter{0.0}) weight_data(), duration_data()
{ {
} }
@ -113,8 +127,8 @@ struct InternalExtractorEdge
return InternalExtractorEdge(MIN_OSM_NODEID, return InternalExtractorEdge(MIN_OSM_NODEID,
MIN_OSM_NODEID, MIN_OSM_NODEID,
SPECIAL_NODEID, SPECIAL_NODEID,
detail::ValueByMeter{0.0}, WeightData(),
detail::ValueByMeter{0.0}, DurationData(),
false, // forward false, // forward
false, // backward false, // backward
false, // roundabout false, // roundabout
@ -131,8 +145,8 @@ struct InternalExtractorEdge
return InternalExtractorEdge(MAX_OSM_NODEID, return InternalExtractorEdge(MAX_OSM_NODEID,
MAX_OSM_NODEID, MAX_OSM_NODEID,
SPECIAL_NODEID, SPECIAL_NODEID,
detail::ValueByMeter{0.0}, WeightData(),
detail::ValueByMeter{0.0}, DurationData(),
false, // forward false, // forward
false, // backward false, // backward
false, // roundabout false, // roundabout

View File

@ -48,6 +48,7 @@ struct NodeBasedEdge
guidance::RoadClassification road_classification; guidance::RoadClassification road_classification;
}; };
#pragma pack(push, 4)
struct NodeBasedEdgeWithOSM : NodeBasedEdge struct NodeBasedEdgeWithOSM : NodeBasedEdge
{ {
NodeBasedEdgeWithOSM(OSMNodeID source, NodeBasedEdgeWithOSM(OSMNodeID source,
@ -68,6 +69,7 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
OSMNodeID osm_source_id; OSMNodeID osm_source_id;
OSMNodeID osm_target_id; OSMNodeID osm_target_id;
}; };
#pragma pack(pop)
// Impl. // Impl.

View File

@ -427,10 +427,8 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm
const double distance = util::coordinate_calculation::greatCircleDistance( const double distance = util::coordinate_calculation::greatCircleDistance(
edge_iterator->source_coordinate, target_coord); edge_iterator->source_coordinate, target_coord);
double weight = static_cast<double>(mapbox::util::apply_visitor( auto weight = edge_iterator->weight_data(distance);
detail::ToValueByEdge(distance), edge_iterator->weight_data)); auto duration = edge_iterator->duration_data(distance);
double duration = static_cast<double>(mapbox::util::apply_visitor(
detail::ToValueByEdge(distance), edge_iterator->duration_data));
ExtractionSegment extracted_segment( ExtractionSegment extracted_segment(
edge_iterator->source_coordinate, target_coord, distance, weight, duration); edge_iterator->source_coordinate, target_coord, distance, weight, duration);

View File

@ -119,20 +119,20 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
InternalExtractorEdge::WeightData forward_weight_data; InternalExtractorEdge::WeightData forward_weight_data;
InternalExtractorEdge::WeightData backward_weight_data; InternalExtractorEdge::WeightData backward_weight_data;
const auto toValueByEdgeOrByMeter = const auto toValueByEdgeOrByMeter = [&nodes](const double by_way, const double by_meter) {
[&nodes](const double by_way, const double by_meter) -> detail::ByEdgeOrByMeterValue { using Value = detail::ByEdgeOrByMeterValue;
if (by_way > 0) if (by_way >= 0)
{ {
// FIXME We divide by the number of edges here, but should rather consider // FIXME We divide by the number of edges here, but should rather consider
// the length of each segment. We would either have to compute the length // the length of each segment. We would either have to compute the length
// of the whole way here (we can't: no node coordinates) or push that back // of the whole way here (we can't: no node coordinates) or push that back
// to the container and keep a reference to the way. // to the container and keep a reference to the way.
const unsigned num_edges = (nodes.size() - 1); const std::size_t num_edges = (nodes.size() - 1);
return detail::ValueByEdge{by_way / num_edges}; return Value(Value::by_edge, by_way / num_edges);
} }
else else
{ {
return detail::ValueByMeter{by_meter}; return Value(Value::by_meter, by_meter);
} }
}; };