Remove all delays from historical packet loading for maximum speed
Server-side optimizations: - Remove all Process.send_after delays - use immediate send() - High zoom (10+): Load everything in single batch (up to 500 packets) - Low zoom: Load all batches immediately without delays - Remove debug logging for performance Client-side optimizations: - Remove chunking delays and requestAnimationFrame - Process all packets immediately without setTimeout - Remove 10-packet chunk limit - process everything at once Result: Historical packets now load as fast as possible without artificial delays or chunking bottlenecks. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
a9414823f1
commit
57fe2b0182
2 changed files with 61 additions and 94 deletions
|
|
@ -685,64 +685,42 @@ let MapAPRSMap = {
|
|||
// Handle progressive loading of historical packets (batch processing)
|
||||
self.handleEvent("add_historical_packets_batch", (data: { packets: MarkerData[], batch: number, is_final: boolean }) => {
|
||||
if (data.packets && Array.isArray(data.packets)) {
|
||||
// Use requestAnimationFrame to ensure smooth rendering
|
||||
requestAnimationFrame(() => {
|
||||
// Process packets in smaller chunks to prevent UI blocking
|
||||
const chunkSize = 10;
|
||||
let currentIndex = 0;
|
||||
|
||||
const processChunk = () => {
|
||||
const chunk = data.packets.slice(currentIndex, currentIndex + chunkSize);
|
||||
|
||||
// Group packets by callsign to process them in chronological order for proper trail drawing
|
||||
const packetsByCallsign = new Map<string, MarkerData[]>();
|
||||
// Process all packets immediately for maximum speed
|
||||
const packetsByCallsign = new Map<string, MarkerData[]>();
|
||||
|
||||
chunk.forEach((packet) => {
|
||||
const callsign = packet.callsign_group || packet.callsign || packet.id;
|
||||
if (!packetsByCallsign.has(callsign)) {
|
||||
packetsByCallsign.set(callsign, []);
|
||||
}
|
||||
packetsByCallsign.get(callsign)!.push(packet);
|
||||
data.packets.forEach((packet) => {
|
||||
const callsign = packet.callsign_group || packet.callsign || packet.id;
|
||||
if (!packetsByCallsign.has(callsign)) {
|
||||
packetsByCallsign.set(callsign, []);
|
||||
}
|
||||
packetsByCallsign.get(callsign)!.push(packet);
|
||||
});
|
||||
|
||||
// Process each callsign group in chronological order (oldest first)
|
||||
packetsByCallsign.forEach((packets, callsign) => {
|
||||
// Sort by timestamp (oldest first) to ensure proper trail line drawing
|
||||
const sortedPackets = packets.sort((a, b) => {
|
||||
const timeA = a.timestamp
|
||||
? typeof a.timestamp === "number"
|
||||
? a.timestamp
|
||||
: new Date(a.timestamp).getTime()
|
||||
: 0;
|
||||
const timeB = b.timestamp
|
||||
? typeof b.timestamp === "number"
|
||||
? b.timestamp
|
||||
: new Date(b.timestamp).getTime()
|
||||
: 0;
|
||||
return timeA - timeB;
|
||||
});
|
||||
|
||||
// Add markers in chronological order
|
||||
sortedPackets.forEach((packet) => {
|
||||
self.addMarker({
|
||||
...packet,
|
||||
historical: true,
|
||||
popup: packet.popup || self.buildPopupContent(packet),
|
||||
});
|
||||
|
||||
// Process each callsign group in chronological order (oldest first)
|
||||
packetsByCallsign.forEach((packets, callsign) => {
|
||||
// Sort by timestamp (oldest first) to ensure proper trail line drawing
|
||||
const sortedPackets = packets.sort((a, b) => {
|
||||
const timeA = a.timestamp
|
||||
? typeof a.timestamp === "number"
|
||||
? a.timestamp
|
||||
: new Date(a.timestamp).getTime()
|
||||
: 0;
|
||||
const timeB = b.timestamp
|
||||
? typeof b.timestamp === "number"
|
||||
? b.timestamp
|
||||
: new Date(b.timestamp).getTime()
|
||||
: 0;
|
||||
return timeA - timeB;
|
||||
});
|
||||
|
||||
// Add markers in chronological order
|
||||
sortedPackets.forEach((packet) => {
|
||||
self.addMarker({
|
||||
...packet,
|
||||
historical: true,
|
||||
popup: packet.popup || self.buildPopupContent(packet),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
currentIndex += chunkSize;
|
||||
|
||||
// Continue processing if there are more packets
|
||||
if (currentIndex < data.packets.length) {
|
||||
// Use setTimeout to yield control and prevent blocking
|
||||
setTimeout(processChunk, 0);
|
||||
}
|
||||
};
|
||||
|
||||
// Start processing
|
||||
processChunk();
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1321,52 +1321,44 @@ defmodule AprsmeWeb.MapLive.Index do
|
|||
# Progressive loading functions using LiveView's efficient update mechanisms
|
||||
@spec start_progressive_historical_loading(Socket.t()) :: Socket.t()
|
||||
defp start_progressive_historical_loading(socket) do
|
||||
# Calculate optimal batch count based on zoom level
|
||||
# For high zoom levels, load everything in one batch for maximum speed
|
||||
zoom = socket.assigns.map_zoom || 5
|
||||
total_batches = calculate_batch_count_for_zoom(zoom)
|
||||
|
||||
# Start with a small batch for immediate visual feedback
|
||||
socket =
|
||||
|
||||
if zoom >= 10 do
|
||||
# High zoom - load everything at once for maximum speed
|
||||
socket
|
||||
|> assign(loading_batch: 0, total_batches: total_batches)
|
||||
|> assign(loading_batch: 0, total_batches: 1)
|
||||
|> load_historical_batch(0)
|
||||
else
|
||||
# Low zoom - use progressive loading to prevent overwhelming
|
||||
total_batches = calculate_batch_count_for_zoom(zoom)
|
||||
|
||||
# Start with first batch
|
||||
socket =
|
||||
socket
|
||||
|> assign(loading_batch: 0, total_batches: total_batches)
|
||||
|> load_historical_batch(0)
|
||||
|
||||
# Schedule next batches using LiveView's async processing
|
||||
# Use much shorter delays for higher zoom levels (fewer batches)
|
||||
base_delay =
|
||||
cond do
|
||||
# Very zoomed in - almost instant
|
||||
zoom >= 15 -> 10
|
||||
# Moderately zoomed in
|
||||
zoom >= 12 -> 20
|
||||
# Medium zoom
|
||||
zoom >= 8 -> 35
|
||||
# Zoomed out
|
||||
true -> 50
|
||||
end
|
||||
# Load all remaining batches immediately - no delays
|
||||
Enum.each(1..(total_batches - 1), fn batch_index ->
|
||||
send(self(), {:load_historical_batch, batch_index})
|
||||
end)
|
||||
|
||||
Enum.each(1..(total_batches - 1), fn batch_index ->
|
||||
# Linear delays instead of exponential
|
||||
delay = base_delay * batch_index
|
||||
Process.send_after(self(), {:load_historical_batch, batch_index}, delay)
|
||||
end)
|
||||
|
||||
socket
|
||||
socket
|
||||
end
|
||||
end
|
||||
|
||||
# Calculate optimal batch size based on zoom level
|
||||
# Higher zoom = smaller viewport = fewer packets needed = smaller batches for faster response
|
||||
# Higher zoom = smaller viewport = load everything at once for speed
|
||||
@spec calculate_batch_size_for_zoom(integer()) :: integer()
|
||||
# Very zoomed in - tiny batches for instant response
|
||||
defp calculate_batch_size_for_zoom(zoom) when zoom >= 15, do: 10
|
||||
# Moderately zoomed in - small batches
|
||||
defp calculate_batch_size_for_zoom(zoom) when zoom >= 12, do: 20
|
||||
# High zoom - load everything at once (up to 500 packets)
|
||||
defp calculate_batch_size_for_zoom(zoom) when zoom >= 10, do: 500
|
||||
# Medium zoom
|
||||
defp calculate_batch_size_for_zoom(zoom) when zoom >= 8, do: 35
|
||||
defp calculate_batch_size_for_zoom(zoom) when zoom >= 8, do: 100
|
||||
# Zoomed out
|
||||
defp calculate_batch_size_for_zoom(zoom) when zoom >= 5, do: 50
|
||||
defp calculate_batch_size_for_zoom(zoom) when zoom >= 5, do: 75
|
||||
# Very zoomed out
|
||||
defp calculate_batch_size_for_zoom(_), do: 75
|
||||
defp calculate_batch_size_for_zoom(_), do: 50
|
||||
|
||||
# Calculate optimal number of batches based on zoom level
|
||||
# Higher zoom = fewer batches needed since viewport is smaller
|
||||
|
|
@ -1397,10 +1389,7 @@ defmodule AprsmeWeb.MapLive.Index do
|
|||
batch_size = calculate_batch_size_for_zoom(zoom)
|
||||
offset = batch_offset * batch_size
|
||||
|
||||
# Debug logging to see what bounds we're using
|
||||
Logger.debug(
|
||||
"Loading historical batch #{batch_offset} with zoom #{zoom}, batch_size #{batch_size}, bounds: #{inspect(bounds)}"
|
||||
)
|
||||
# Debug logging removed for performance
|
||||
|
||||
packets_module = Application.get_env(:aprsme, :packets_module, Aprsme.Packets)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue