perf(rover): tighten Overpass timeout and log per-step compute timing
Calculate occasionally hung in production for ~30s. Adds per-phase timing logs to Compute.run so the slow step is visible in pod logs, and trims the Overpass road-proximity request to a 10s server-side timeout / 12s receive timeout (no Req retries) so a slow road API fails soft to no road penalty instead of stalling Calculate.
This commit is contained in:
parent
10cbd8dd48
commit
4bfcff4e32
2 changed files with 25 additions and 9 deletions
|
|
@ -17,6 +17,8 @@ defmodule Microwaveprop.Rover.Compute do
|
||||||
alias Microwaveprop.Rover.Prominence
|
alias Microwaveprop.Rover.Prominence
|
||||||
alias Microwaveprop.Rover.RoadProximity
|
alias Microwaveprop.Rover.RoadProximity
|
||||||
|
|
||||||
|
require Logger
|
||||||
|
|
||||||
@avg_speed_kmh 65.0
|
@avg_speed_kmh 65.0
|
||||||
@drive_penalty_db_per_hour 2.0
|
@drive_penalty_db_per_hour 2.0
|
||||||
@top_n 5
|
@top_n 5
|
||||||
|
|
@ -86,23 +88,25 @@ defmodule Microwaveprop.Rover.Compute do
|
||||||
radius_km = max_distance_km * 1.0
|
radius_km = max_distance_km * 1.0
|
||||||
bbox = bbox_around(home, radius_km)
|
bbox = bbox_around(home, radius_km)
|
||||||
|
|
||||||
raw_cells = scores_at.(band_mhz, valid_time, bbox)
|
raw_cells = time_step("scores_at", fn -> scores_at.(band_mhz, valid_time, bbox) end)
|
||||||
|
|
||||||
# First filter: drive radius
|
|
||||||
in_radius =
|
in_radius =
|
||||||
Enum.filter(raw_cells, fn cell ->
|
Enum.filter(raw_cells, fn cell ->
|
||||||
DriveTime.haversine_km({home.lat, home.lon}, {cell.lat, cell.lon}) <= radius_km
|
DriveTime.haversine_km({home.lat, home.lon}, {cell.lat, cell.lon}) <= radius_km
|
||||||
end)
|
end)
|
||||||
|
|
||||||
# Bulk SRTM lookup for cell centers, then per-link path-terrain clearance.
|
Logger.info(
|
||||||
|
"rover compute: radius=#{radius_km}km cells=#{length(raw_cells)} in_radius=#{length(in_radius)} stations=#{length(selected_stations)}"
|
||||||
|
)
|
||||||
|
|
||||||
points = Enum.map(in_radius, &{&1.lat, &1.lon})
|
points = Enum.map(in_radius, &{&1.lat, &1.lon})
|
||||||
elev_map = elev_lookup.(points)
|
elev_map = time_step("elev_lookup", fn -> elev_lookup.(points) end)
|
||||||
clearance_map = clearance_lookup.(in_radius, selected_stations)
|
clearance_map = time_step("clearance", fn -> clearance_lookup.(in_radius, selected_stations) end)
|
||||||
prominence_map = prominence_lookup.(in_radius)
|
prominence_map = time_step("prominence", fn -> prominence_lookup.(in_radius) end)
|
||||||
|
|
||||||
road_map =
|
road_map =
|
||||||
if Application.get_env(:microwaveprop, :rover_road_proximity_enabled, true),
|
if Application.get_env(:microwaveprop, :rover_road_proximity_enabled, true),
|
||||||
do: fetch_road_map(road_lookup, in_radius, bbox),
|
do: time_step("road_proximity", fn -> fetch_road_map(road_lookup, in_radius, bbox) end),
|
||||||
else: %{}
|
else: %{}
|
||||||
|
|
||||||
home_elev = home.elev_m || 0
|
home_elev = home.elev_m || 0
|
||||||
|
|
@ -203,6 +207,12 @@ defmodule Microwaveprop.Rover.Compute do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp time_step(label, fun) do
|
||||||
|
{us, result} = :timer.tc(fun)
|
||||||
|
Logger.info("rover compute: #{label} took #{div(us, 1000)} ms")
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
defp fetch_road_map(road_lookup, cells, bbox) do
|
defp fetch_road_map(road_lookup, cells, bbox) do
|
||||||
case road_lookup.(cells, bbox) do
|
case road_lookup.(cells, bbox) do
|
||||||
{:ok, map} -> map
|
{:ok, map} -> map
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ defmodule Microwaveprop.Rover.RoadProximity do
|
||||||
|
|
||||||
@overpass_url "https://overpass-api.de/api/interpreter"
|
@overpass_url "https://overpass-api.de/api/interpreter"
|
||||||
@road_types ~w(motorway trunk primary secondary tertiary unclassified residential)
|
@road_types ~w(motorway trunk primary secondary tertiary unclassified residential)
|
||||||
|
@overpass_query_timeout_s 10
|
||||||
|
@overpass_receive_timeout_ms 12_000
|
||||||
|
|
||||||
@type latlon :: {float(), float()}
|
@type latlon :: {float(), float()}
|
||||||
@type segment :: {latlon(), latlon()}
|
@type segment :: {latlon(), latlon()}
|
||||||
|
|
@ -44,12 +46,16 @@ defmodule Microwaveprop.Rover.RoadProximity do
|
||||||
types = Enum.join(@road_types, "|")
|
types = Enum.join(@road_types, "|")
|
||||||
|
|
||||||
query = """
|
query = """
|
||||||
[out:json][timeout:25];
|
[out:json][timeout:#{@overpass_query_timeout_s}];
|
||||||
way["highway"~"^(#{types})$"](#{s},#{w},#{n},#{e});
|
way["highway"~"^(#{types})$"](#{s},#{w},#{n},#{e});
|
||||||
out geom;
|
out geom;
|
||||||
"""
|
"""
|
||||||
|
|
||||||
case Req.post(@overpass_url, form: [data: query], receive_timeout: 30_000) do
|
case Req.post(@overpass_url,
|
||||||
|
form: [data: query],
|
||||||
|
receive_timeout: @overpass_receive_timeout_ms,
|
||||||
|
retry: false
|
||||||
|
) do
|
||||||
{:ok, %{status: 200, body: %{"elements" => elements}}} ->
|
{:ok, %{status: 200, body: %{"elements" => elements}}} ->
|
||||||
{:ok, segments_from_elements(elements)}
|
{:ok, segments_from_elements(elements)}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue