increase performance by passing vars instead of a table

This commit is contained in:
Emil Tin 2016-11-11 14:31:14 +01:00 committed by Patrick Niklaus
parent fd95b2da76
commit 184cfab33b
2 changed files with 186 additions and 190 deletions

View File

@ -236,17 +236,17 @@ function node_function (node, result)
end
-- abort early if this way is obviouslt not routable
function handle_initial_check(data)
return TagCache.get(data,'highway') ~= nil or
TagCache.get(data,'route') ~= nil or
TagCache.get(data,'bridge') ~= nil
function handle_initial_check(way,result,cache)
return TagCache.get(way,cache,'highway') ~= nil or
TagCache.get(way,cache,'route') ~= nil or
TagCache.get(way,cache,'bridge') ~= nil
end
-- handle high occupancy vehicle tags
function handle_hov(data)
function handle_hov(way,result,cache)
-- respect user-preference for HOV-only ways
if ignore_hov_ways then
local hov = TagCache.get(data,"hov")
local hov = TagCache.get(way,cache,"hov")
if hov and "designated" == hov then
return false
end
@ -265,9 +265,9 @@ function handle_hov(data)
return all
end
local hov_lanes = TagCache.get(data,"hov:lanes")
local hov_lanes_forward = TagCache.get(data,"hov:lanes:forward")
local hov_lanes_backward = TagCache.get(data,"hov:lanes:backward")
local hov_lanes = TagCache.get(way,cache,"hov:lanes")
local hov_lanes_forward = TagCache.get(way,cache,"hov:lanes:forward")
local hov_lanes_backward = TagCache.get(way,cache,"hov:lanes:backward")
local hov_all_designated = hov_lanes and hov_lanes ~= ""
and has_all_designated_hov_lanes(hov_lanes)
@ -279,22 +279,22 @@ function handle_hov(data)
and has_all_designated_hov_lanes(hov_lanes_backward)
-- forward/backward lane depend on a way's direction
local oneway = TagCache.get(data,"oneway")
local oneway = TagCache.get(way,cache,"oneway")
local reverse = oneway and oneway == "-1"
if hov_all_designated or hov_all_designated_forward then
if reverse then
data.result.backward_mode = mode.inaccessible
result.backward_mode = mode.inaccessible
else
data.result.forward_mode = mode.inaccessible
result.forward_mode = mode.inaccessible
end
end
if hov_all_designated_backward then
if reverse then
data.result.forward_mode = mode.inaccessible
result.forward_mode = mode.inaccessible
else
data.result.backward_mode = mode.inaccessible
result.backward_mode = mode.inaccessible
end
end
@ -302,384 +302,384 @@ function handle_hov(data)
end
-- handle squares and other areas
function handle_area(data)
function handle_area(way,result,cache)
-- we dont route over areas
local area = TagCache.get(data,"area")
local area = TagCache.get(way,cache,"area")
if ignore_areas and area and "yes" == area then
return false
end
end
-- handle toll roads
function handle_toll(data)
function handle_toll(way,result,cache)
-- respect user-preference for toll=yes ways
local toll = TagCache.get(data,"toll")
local toll = TagCache.get(way,cache,"toll")
if ignore_toll_ways and toll and "yes" == toll then
return false
end
end
-- handle various that can block access
function handle_blocking(data)
if handle_area(data) == false then
function handle_blocking(way,result,cache)
if handle_area(way,result,cache) == false then
return false
end
if handle_hov(data) == false then
if handle_hov(way,result,cache) == false then
return false
end
if handle_toll(data) == false then
if handle_toll(way,result,cache) == false then
return false
end
-- Reversible oneways change direction with low frequency (think twice a day):
-- do not route over these at all at the moment because of time dependence.
-- Note: alternating (high frequency) oneways are handled below with penalty.
local oneway = TagCache.get(data,"oneway")
local oneway = TagCache.get(way,cache,"oneway")
if oneway and "reversible" == oneway then
return false
end
local impassable = TagCache.get(data,"impassable")
local impassable = TagCache.get(way,cache,"impassable")
if impassable and "yes" == impassable then
return false
end
local status = TagCache.get(data,"status")
local status = TagCache.get(way,cache,"status")
if status and "impassable" == status then
return false
end
end
-- set default mode
function handle_default_mode(data)
data.result.forward_mode = mode.driving
data.result.backward_mode = mode.driving
function handle_default_mode(way,result,cache)
result.forward_mode = mode.driving
result.backward_mode = mode.driving
end
-- check accessibility by traversing our acces tag hierarchy
function handle_access(data)
data.access = find_access_tag(data.way, access_tags_hierarchy)
if access_tag_blacklist[data.access] then
function handle_access(way,result,cache)
access = find_access_tag(way, access_tags_hierarchy)
if access_tag_blacklist[access] then
return false
end
end
-- handling ferries and piers
function handle_ferries(data)
local route = TagCache.get(data,"route")
function handle_ferries(way,result,cache)
local route = TagCache.get(way,cache,"route")
local route_speed = speed_profile[route]
if (route_speed and route_speed > 0) then
TagCache.set(data,"highway",route)
local duration = TagCache.get(data,"duration")
TagCache.set(cache,"highway",route)
local duration = TagCache.get(way,cache,"duration")
if duration and durationIsValid(duration) then
data.result.duration = max( parseDuration(duration), 1 )
result.duration = max( parseDuration(duration), 1 )
end
data.result.forward_mode = mode.ferry
data.result.backward_mode = mode.ferry
data.result.forward_speed = route_speed
data.result.backward_speed = route_speed
result.forward_mode = mode.ferry
result.backward_mode = mode.ferry
result.forward_speed = route_speed
result.backward_speed = route_speed
end
end
-- handling movable bridges
function handle_movables(data)
local bridge = TagCache.get(data,"bridge")
function handle_movables(way,result,cache)
local bridge = TagCache.get(way,cache,"bridge")
local bridge_speed = speed_profile[bridge]
local capacity_car = TagCache.get(data,"capacity:car")
local capacity_car = TagCache.get(way,cache,"capacity:car")
if (bridge_speed and bridge_speed > 0) and (capacity_car ~= 0) then
TagCache.set(data,"highway",bridge)
local duration = TagCache.get(data,"duration")
TagCache.set(cache,"highway",bridge)
local duration = TagCache.get(way,cache,"duration")
if duration and durationIsValid(duration) then
data.result.duration = max( parseDuration(duration), 1 )
result.duration = max( parseDuration(duration), 1 )
end
data.result.forward_speed = bridge_speed
data.result.backward_speed = bridge_speed
result.forward_speed = bridge_speed
result.backward_speed = bridge_speed
end
end
-- handle speed (excluding maxspeed)
function handle_speed(data)
if data.result.forward_speed == -1 then
local highway_speed = speed_profile[TagCache.get(data,"highway")]
local max_speed = parse_maxspeed( TagCache.get(data,"maxspeed") )
function handle_speed(way,result,cache)
if result.forward_speed == -1 then
local highway_speed = speed_profile[TagCache.get(way,cache,"highway")]
local max_speed = parse_maxspeed( TagCache.get(way,cache,"maxspeed") )
-- Set the avg speed on the way if it is accessible by road class
if highway_speed then
if max_speed and max_speed > highway_speed then
data.result.forward_speed = max_speed
data.result.backward_speed = max_speed
result.forward_speed = max_speed
result.backward_speed = max_speed
-- max_speed = math.huge
else
data.result.forward_speed = highway_speed
data.result.backward_speed = highway_speed
result.forward_speed = highway_speed
result.backward_speed = highway_speed
end
else
-- Set the avg speed on ways that are marked accessible
if access_tag_whitelist[data.access] then
data.result.forward_speed = speed_profile["default"]
data.result.backward_speed = speed_profile["default"]
if access_tag_whitelist[access] then
result.forward_speed = speed_profile["default"]
result.backward_speed = speed_profile["default"]
end
end
if 0 == max_speed then
max_speed = math.huge
end
data.result.forward_speed = min(data.result.forward_speed, max_speed)
data.result.backward_speed = min(data.result.backward_speed, max_speed)
result.forward_speed = min(result.forward_speed, max_speed)
result.backward_speed = min(result.backward_speed, max_speed)
end
if -1 == data.result.forward_speed and -1 == data.result.backward_speed then
if -1 == result.forward_speed and -1 == result.backward_speed then
return false
end
if handle_side_roads(data) == false then return false end
if handle_surface(data) == false then return false end
if handle_maxspeed(data) == false then return false end
if handle_speed_scaling(data) == false then return false end
if handle_alternating_speed(data) == false then return false end
if handle_side_roads(way,result,cache) == false then return false end
if handle_surface(way,result,cache) == false then return false end
if handle_maxspeed(way,result,cache) == false then return false end
if handle_speed_scaling(way,result,cache) == false then return false end
if handle_alternating_speed(way,result,cache) == false then return false end
end
-- reduce speed on special side roads
function handle_side_roads(data)
local sideway = TagCache.get(data,"side_road")
function handle_side_roads(way,result,cache)
local sideway = TagCache.get(way,cache,"side_road")
if "yes" == sideway or
"rotary" == sideway then
data.result.forward_speed = data.result.forward_speed * side_road_speed_multiplier
data.result.backward_speed = data.result.backward_speed * side_road_speed_multiplier
result.forward_speed = result.forward_speed * side_road_speed_multiplier
result.backward_speed = result.backward_speed * side_road_speed_multiplier
end
end
-- reduce speed on bad surfaces
function handle_surface(data)
local surface = TagCache.get(data,"surface")
local tracktype = TagCache.get(data,"tracktype")
local smoothness = TagCache.get(data,"smoothness")
function handle_surface(way,result,cache)
local surface = TagCache.get(way,cache,"surface")
local tracktype = TagCache.get(way,cache,"tracktype")
local smoothness = TagCache.get(way,cache,"smoothness")
if surface and surface_speeds[surface] then
data.result.forward_speed = math.min(surface_speeds[surface], data.result.forward_speed)
data.result.backward_speed = math.min(surface_speeds[surface], data.result.backward_speed)
result.forward_speed = math.min(surface_speeds[surface], result.forward_speed)
result.backward_speed = math.min(surface_speeds[surface], result.backward_speed)
end
if tracktype and tracktype_speeds[tracktype] then
data.result.forward_speed = math.min(tracktype_speeds[tracktype], data.result.forward_speed)
data.result.backward_speed = math.min(tracktype_speeds[tracktype], data.result.backward_speed)
result.forward_speed = math.min(tracktype_speeds[tracktype], result.forward_speed)
result.backward_speed = math.min(tracktype_speeds[tracktype], result.backward_speed)
end
if smoothness and smoothness_speeds[smoothness] then
data.result.forward_speed = math.min(smoothness_speeds[smoothness], data.result.forward_speed)
data.result.backward_speed = math.min(smoothness_speeds[smoothness], data.result.backward_speed)
result.forward_speed = math.min(smoothness_speeds[smoothness], result.forward_speed)
result.backward_speed = math.min(smoothness_speeds[smoothness], result.backward_speed)
end
end
-- handles name, including ref and pronunciation
function handle_names(data)
function handle_names(way,result,cache)
-- parse the remaining tags
local name = TagCache.get(data,"name")
local pronunciation = TagCache.get(data,"name:pronunciation")
local ref = TagCache.get(data,"ref")
local name = TagCache.get(way,cache,"name")
local pronunciation = TagCache.get(way,cache,"name:pronunciation")
local ref = TagCache.get(way,cache,"ref")
-- Set the name that will be used for instructions
if name then
data.result.name = name
result.name = name
end
if ref then
data.result.ref = canonicalizeStringList(ref, ";")
result.ref = canonicalizeStringList(ref, ";")
end
if pronunciation then
data.result.pronunciation = pronunciation
result.pronunciation = pronunciation
end
end
-- handle turn lanes
function handle_turn_lanes(data)
function handle_turn_lanes(way,result,cache)
local turn_lanes = ""
local turn_lanes_forward = ""
local turn_lanes_backward = ""
turn_lanes, turn_lanes_forward, turn_lanes_backward = get_turn_lanes(data.way)
turn_lanes, turn_lanes_forward, turn_lanes_backward = get_turn_lanes(way)
if turn_lanes and turn_lanes ~= "" then
data.result.turn_lanes_forward = turn_lanes;
data.result.turn_lanes_backward = turn_lanes;
result.turn_lanes_forward = turn_lanes;
result.turn_lanes_backward = turn_lanes;
else
if turn_lanes_forward and turn_lanes_forward ~= "" then
data.result.turn_lanes_forward = turn_lanes_forward;
result.turn_lanes_forward = turn_lanes_forward;
end
if turn_lanes_backward and turn_lanes_backward ~= "" then
data.result.turn_lanes_backward = turn_lanes_backward;
result.turn_lanes_backward = turn_lanes_backward;
end
end
end
-- junctions
function handle_junctions(data)
if TagCache.get(data,"junction") == "roundabout" then
data.result.roundabout = true
function handle_junctions(way,result,cache)
if TagCache.get(way,cache,"junction") == "roundabout" then
result.roundabout = true
end
end
-- Set access restriction flag if access is allowed under certain restrictions only
function handle_restricted(data)
if data.access ~= "" and access_tag_restricted[data.access] then
data.result.is_access_restricted = true
function handle_restricted(way,result,cache)
if access ~= "" and access_tag_restricted[access] then
result.is_access_restricted = true
end
end
-- service roads
function handle_service(data)
local service = TagCache.get(data,"service")
function handle_service(way,result,cache)
local service = TagCache.get(way,cache,"service")
if service then
-- Set access restriction flag if service is allowed under certain restrictions only
if service_tag_restricted[service] then
data.result.is_access_restricted = true
result.is_access_restricted = true
end
-- Set don't allow access to certain service roads
if service_tag_forbidden[service] then
data.result.forward_mode = mode.inaccessible
data.result.backward_mode = mode.inaccessible
result.forward_mode = mode.inaccessible
result.backward_mode = mode.inaccessible
return false
end
end
end
-- scale speeds to get better average driving times
function handle_speed_scaling(data)
function handle_speed_scaling(way,result,cache)
local width = math.huge
local lanes = math.huge
if data.result.forward_speed > 0 or data.result.backward_speed > 0 then
local width_string = TagCache.get(data,"width")
if result.forward_speed > 0 or result.backward_speed > 0 then
local width_string = TagCache.get(way,cache,"width")
if width_string and tonumber(width_string:match("%d*")) then
width = tonumber(width_string:match("%d*"))
end
local lanes_string = TagCache.get(data,"lanes")
local lanes_string = TagCache.get(way,cache,"lanes")
if lanes_string and tonumber(lanes_string:match("%d*")) then
lanes = tonumber(lanes_string:match("%d*"))
end
end
local is_bidirectional = data.result.forward_mode ~= mode.inaccessible and
data.result.backward_mode ~= mode.inaccessible
local is_bidirectional = result.forward_mode ~= mode.inaccessible and
result.backward_mode ~= mode.inaccessible
local service = TagCache.get(data,"service")
if data.result.forward_speed > 0 then
local scaled_speed = data.result.forward_speed * speed_reduction
local service = TagCache.get(way,cache,"service")
if result.forward_speed > 0 then
local scaled_speed = result.forward_speed * speed_reduction
local penalized_speed = math.huge
if service and service ~= "" and service_speeds[service] then
penalized_speed = service_speeds[service]
elseif width <= 3 or (lanes <= 1 and is_bidirectional) then
penalized_speed = data.result.forward_speed / 2
penalized_speed = result.forward_speed / 2
end
data.result.forward_speed = math.min(penalized_speed, scaled_speed)
result.forward_speed = math.min(penalized_speed, scaled_speed)
end
if data.result.backward_speed > 0 then
local scaled_speed = data.result.backward_speed * speed_reduction
if result.backward_speed > 0 then
local scaled_speed = result.backward_speed * speed_reduction
local penalized_speed = math.huge
if service and service ~= "" and service_speeds[service]then
penalized_speed = service_speeds[service]
elseif width <= 3 or (lanes <= 1 and is_bidirectional) then
penalized_speed = data.result.backward_speed / 2
penalized_speed = result.backward_speed / 2
end
data.result.backward_speed = math.min(penalized_speed, scaled_speed)
result.backward_speed = math.min(penalized_speed, scaled_speed)
end
end
-- oneways
function handle_oneway(data)
local oneway = TagCache.get(data,"oneway")
function handle_oneway(way,result,cache)
local oneway = TagCache.get(way,cache,"oneway")
if obey_oneway then
if oneway == "-1" then
data.result.forward_mode = mode.inaccessible
result.forward_mode = mode.inaccessible
local is_forward = false
local destination = get_destination(data.way, is_forward)
data.result.destinations = canonicalizeStringList(destination, ",")
local destination = get_destination(way, is_forward)
result.destinations = canonicalizeStringList(destination, ",")
elseif oneway == "yes" or
oneway == "1" or
oneway == "true" or
TagCache.get(data,"junction") == "roundabout" or
(TagCache.get(data,"highway") == "motorway" and oneway ~= "no") then
TagCache.get(way,cache,"junction") == "roundabout" or
(TagCache.get(way,cache,"highway") == "motorway" and oneway ~= "no") then
data.result.backward_mode = mode.inaccessible
result.backward_mode = mode.inaccessible
local is_forward = true
local destination = get_destination(data.way, is_forward)
data.result.destinations = canonicalizeStringList(destination, ",")
local destination = get_destination(way, is_forward)
result.destinations = canonicalizeStringList(destination, ",")
end
end
end
-- maxspeed and advisory maxspeed
function handle_maxspeed(data)
function handle_maxspeed(way,result,cache)
-- Override speed settings if explicit forward/backward maxspeeds are given
local maxspeed_forward = parse_maxspeed(TagCache.get(data,"maxspeed:forward"))
local maxspeed_backward = parse_maxspeed(TagCache.get(data,"maxspeed:backward"))
local maxspeed_forward = parse_maxspeed(TagCache.get(way,cache,"maxspeed:forward"))
local maxspeed_backward = parse_maxspeed(TagCache.get(way,cache,"maxspeed:backward"))
if maxspeed_forward and maxspeed_forward > 0 then
if mode.inaccessible ~= data.result.forward_mode and
mode.inaccessible ~= data.result.backward_mode then
data.result.backward_speed = data.result.forward_speed
if mode.inaccessible ~= result.forward_mode and
mode.inaccessible ~= result.backward_mode then
result.backward_speed = result.forward_speed
end
data.result.forward_speed = maxspeed_forward
result.forward_speed = maxspeed_forward
end
if maxspeed_backward and maxspeed_backward > 0 then
data.result.backward_speed = maxspeed_backward
result.backward_speed = maxspeed_backward
end
-- Override speed settings if advisory forward/backward maxspeeds are given
local advisory_speed = parse_maxspeed(TagCache.get(data,"maxspeed:advisory"))
local advisory_forward = parse_maxspeed(TagCache.get(data,"maxspeed:advisory:forward"))
local advisory_backward = parse_maxspeed(TagCache.get(data,"maxspeed:advisory:backward"))
local advisory_speed = parse_maxspeed(TagCache.get(way,cache,"maxspeed:advisory"))
local advisory_forward = parse_maxspeed(TagCache.get(way,cache,"maxspeed:advisory:forward"))
local advisory_backward = parse_maxspeed(TagCache.get(way,cache,"maxspeed:advisory:backward"))
-- apply bi-directional advisory speed first
if advisory_speed and advisory_speed > 0 then
if mode.inaccessible ~= data.result.forward_mode then
data.result.forward_speed = advisory_speed
if mode.inaccessible ~= result.forward_mode then
result.forward_speed = advisory_speed
end
if mode.inaccessible ~= data.result.backward_mode then
data.result.backward_speed = advisory_speed
if mode.inaccessible ~= result.backward_mode then
result.backward_speed = advisory_speed
end
end
if advisory_forward and advisory_forward > 0 then
if mode.inaccessible ~= data.result.forward_mode and mode.inaccessible ~= data.result.backward_mode then
data.result.backward_speed = data.result.forward_speed
if mode.inaccessible ~= result.forward_mode and mode.inaccessible ~= result.backward_mode then
result.backward_speed = result.forward_speed
end
data.result.forward_speed = advisory_forward
result.forward_speed = advisory_forward
end
if advisory_backward and advisory_backward > 0 then
data.result.backward_speed = advisory_backward
result.backward_speed = advisory_backward
end
end
-- Handle high frequency reversible oneways (think traffic signal controlled, changing direction every 15 minutes).
-- Scaling speed to take average waiting time into account plus some more for start / stop.
function handle_alternating_speed(data)
if "alternating" == TagCache.get(data,'oneway') then
function handle_alternating_speed(way,result,cache)
if "alternating" == TagCache.get(way,cache,'oneway') then
local scaling_factor = 0.4
if data.result.forward_speed ~= math.huge then
data.result.forward_speed = data.result.forward_speed * scaling_factor
if result.forward_speed ~= math.huge then
result.forward_speed = result.forward_speed * scaling_factor
end
if data.result.backward_speed ~= math.huge then
data.result.backward_speed = data.result.backward_speed * scaling_factor
if result.backward_speed ~= math.huge then
result.backward_speed = result.backward_speed * scaling_factor
end
end
end
-- determine if this way can be used as a start/end point for routing
function handle_startpoint(data)
function handle_startpoint(way,result,cache)
-- only allow this road as start point if it not a ferry
data.result.is_startpoint = data.result.forward_mode == mode.driving or
data.result.backward_mode == mode.driving
result.is_startpoint = result.forward_mode == mode.driving or
result.backward_mode == mode.driving
end
-- leave early if this way is not accessible
function handle_way_type(data)
if "" == TagCache.get(data,"highway") then return false end
function handle_way_type(way,result,cache)
if "" == TagCache.get(way,cache,"highway") then return false end
end
-- set the road classification based on guidance globals configuration
function handle_classification(data)
set_classification(TagCache.get(data,"highway"),data.result,data.way)
function handle_classification(way,result,cache)
set_classification(TagCache.get(way,cache,"highway"),result,way)
end
-- main entry point for processsing a way
@ -692,31 +692,27 @@ function way_function(way, result)
-- into C++ more than once for each tag, without having to
-- pass lists of already fetches tags around.
local data = {
way = way,
result = result,
cache = {},
}
cache = {}
-- perform each procesing step sequentially.
-- most steps can abort processing, meaning the way
-- is not routable
if handle_initial_check(data) == false then return end
if handle_default_mode(data) == false then return end--
if handle_blocking(data) == false then return end
if handle_access(data) == false then return end
if handle_ferries(data) == false then return end--
if handle_movables(data) == false then return end--
if handle_service(data) == false then return end
if handle_oneway(data) == false then return end--
if handle_speed(data) == false then return end
if handle_turn_lanes(data) == false then return end--
if handle_junctions(data) == false then return end--
if handle_startpoint(data) == false then return end--
if handle_restricted(data) == false then return end--
if handle_classification(data) == false then return end--
if handle_names(data) == false then return end--
if handle_initial_check(way,result,cache) == false then return end
if handle_default_mode(way,result,cache) == false then return end--
if handle_blocking(way,result,cache) == false then return end
if handle_access(way,result,cache) == false then return end
if handle_ferries(way,result,cache) == false then return end--
if handle_movables(way,result,cache) == false then return end--
if handle_service(way,result,cache) == false then return end
if handle_oneway(way,result,cache) == false then return end--
if handle_speed(way,result,cache) == false then return end
if handle_turn_lanes(way,result,cache) == false then return end--
if handle_junctions(way,result,cache) == false then return end--
if handle_startpoint(way,result,cache) == false then return end--
if handle_restricted(way,result,cache) == false then return end--
if handle_classification(way,result,cache) == false then return end--
if handle_names(way,result,cache) == false then return end--
end
function turn_function (angle)

View File

@ -1,7 +1,7 @@
TagCache = {}
function TagCache.get(data, key)
local v = data.cache[key]
function TagCache.get(way,cache,key)
local v = cache[key]
if v then
if v == '' then
return nil
@ -9,12 +9,12 @@ function TagCache.get(data, key)
return v
end
else
v = data.way:get_value_by_key(key)
v = way:get_value_by_key(key)
if v == nil then
data.cache[key] = ''
cache[key] = ''
return nil
else
data.cache[key] = v
cache[key] = v
if v == '' then
return nil
else
@ -24,11 +24,11 @@ function TagCache.get(data, key)
end
end
function TagCache.set(data,key,value)
function TagCache.set(cache,key,value)
if value then
data.cache[key] = value
cache[key] = value
else
data.cache[key] = ''
cache[key] = ''
end
end