From 1dde56705ab87dc50a4dcaed179126897da513a0 Mon Sep 17 00:00:00 2001 From: mytec Date: Sun, 1 Feb 2026 14:26:17 +0200 Subject: [PATCH] @mytec: before 3.0 REFACTOR --- RFCP-Phase-2.5.1-Performance-AppClose.md | 577 ++++++++++++++++++ backend/app/services/coverage_service.py | 28 +- backend/app/services/dominant_path_service.py | 211 ++++++- backend/app/services/geometry_vectorized.py | 309 ++++++++++ desktop/main.js | 140 +++-- files.zip | Bin 0 -> 161446 bytes installer/coverage-result-detailed.json | 1 - installer/coverage-result-fast.json | 1 - installer/coverage-result-standard.json | 1 - installer/monitor-realtime.bat | 49 ++ installer/rfcp-debug-enhanced.bat | 93 +++ installer/test-coverage-monitor.bat | 282 +++++++++ installer/test-detailed-quick.bat | 128 ++++ 13 files changed, 1759 insertions(+), 61 deletions(-) create mode 100644 RFCP-Phase-2.5.1-Performance-AppClose.md create mode 100644 backend/app/services/geometry_vectorized.py create mode 100644 files.zip delete mode 100644 installer/coverage-result-detailed.json delete mode 100644 installer/coverage-result-fast.json delete mode 100644 installer/coverage-result-standard.json create mode 100644 installer/monitor-realtime.bat create mode 100644 installer/rfcp-debug-enhanced.bat create mode 100644 installer/test-coverage-monitor.bat create mode 100644 installer/test-detailed-quick.bat diff --git a/RFCP-Phase-2.5.1-Performance-AppClose.md b/RFCP-Phase-2.5.1-Performance-AppClose.md new file mode 100644 index 0000000..1c9ddac --- /dev/null +++ b/RFCP-Phase-2.5.1-Performance-AppClose.md @@ -0,0 +1,577 @@ +# RFCP Phase 2.5.1: Performance Tuning + App Close Fix + +**Date:** February 1, 2025 +**Type:** Performance + Bug Fix +**Priority:** HIGH +**Depends on:** Phase 2.5.0 + +--- + +## 🎯 Summary + +Phase 2.5.0 vectorization ΠΏΡ€Π°Ρ†ΡŽΡ”, Π°Π»Π΅ bottleneck залишився: +- `line_intersects_polygons_batch()` ΠΌΠ°Ρ” Π²Π½ΡƒΡ‚Ρ€Ρ–ΡˆΠ½Ρ–ΠΉ loop ΠΏΠΎ polygons +- 351-458 walls ΠΏΠ΅Ρ€Π΅Π²Ρ–Ρ€ΡΡŽΡ‚ΡŒΡΡ для ΠΊΠΎΠΆΠ½ΠΎΡ— Ρ‚ΠΎΡ‡ΠΊΠΈ +- Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚: 329ms/point (ΠΌΠ°ΠΉΠΆΠ΅ Π±Π΅Π· Π·ΠΌΡ–Π½) + +Π’Π°ΠΊΠΎΠΆ: App close Π”ΠžΠ‘Π† Π½Π΅ ΠΏΡ€Π°Ρ†ΡŽΡ” β€” хрСстик Π½Π΅ Π·Π°ΠΊΡ€ΠΈΠ²Π°Ρ” backend. + +--- + +## πŸ“Š Current Performance Analysis + +``` +[DOMINANT_PATH_VEC] Point #1: buildings=50, walls=351 +[DOMINANT_PATH_VEC] Point #2: buildings=50, walls=439 +[DOMINANT_PATH_VEC] Point #3: buildings=50, walls=458 + +Result: 329ms/point β€” NOT improved! +``` + +**Root cause:** LOS check loop inside vectorized function: +```python +# geometry_vectorized.py line ~85 +for i, length in enumerate(polygon_lengths): # ← THIS LOOP + # Check each polygon... +``` + +--- + +## πŸ”§ Fix 2.5.1a: Limit Walls for Reflection Check + +**File:** `backend/app/services/geometry_vectorized.py` + +**In `find_best_reflection_path_vectorized()`:** + +```python +def find_best_reflection_path_vectorized( + tx: np.ndarray, + rx: np.ndarray, + building_walls_start: np.ndarray, + building_walls_end: np.ndarray, + wall_to_building: np.ndarray, + obstacle_polygons_x: np.ndarray, + obstacle_polygons_y: np.ndarray, + obstacle_lengths: np.ndarray, + max_candidates: int = 50, + max_walls: int = 100, # ← ADD THIS + max_los_checks: int = 10 # ← ADD THIS +) -> Tuple[Optional[np.ndarray], float, float]: + """ + Find best single-reflection path using vectorized operations. + + OPTIMIZATION: Limit walls and LOS checks for speed. + - max_walls: Only consider closest N walls for reflection + - max_los_checks: Only verify LOS for top N shortest paths + """ + num_walls = len(building_walls_start) + + if num_walls == 0: + return None, np.inf, 0.0 + + # === OPTIMIZATION 1: Limit walls by distance to path midpoint === + if num_walls > max_walls: + # Calculate midpoint of TX-RX path + midpoint = (tx + rx) / 2 + + # Calculate wall midpoints + wall_midpoints = (building_walls_start + building_walls_end) / 2 + + # Distance from each wall to path midpoint + wall_distances = np.linalg.norm(wall_midpoints - midpoint, axis=1) + + # Take closest walls + closest_indices = np.argpartition(wall_distances, max_walls)[:max_walls] + + building_walls_start = building_walls_start[closest_indices] + building_walls_end = building_walls_end[closest_indices] + wall_to_building = wall_to_building[closest_indices] + + # Log reduction (first 3 points only) + # print(f"[WALLS] Reduced {num_walls} β†’ {max_walls} walls") + + # Step 1: Calculate all reflection points at once + refl_points, valid = calculate_reflection_points_batch( + tx, rx, building_walls_start, building_walls_end + ) + + if not np.any(valid): + return None, np.inf, 0.0 + + # Step 2: Calculate path lengths for valid reflections + valid_indices = np.where(valid)[0] + valid_refl = refl_points[valid] + + tx_to_refl = np.linalg.norm(valid_refl - tx, axis=1) + refl_to_rx = np.linalg.norm(rx - valid_refl, axis=1) + path_lengths = tx_to_refl + refl_to_rx + + # === OPTIMIZATION 2: Sort by path length, check LOS only for top N === + # Sort indices by path length (shortest first) + sorted_order = np.argsort(path_lengths) + + # Limit to max_los_checks + check_count = min(len(sorted_order), max_los_checks) + + # Step 3: Check LOS only for top candidates + best_idx = -1 + best_length = np.inf + + for i in range(check_count): + idx = sorted_order[i] + refl_pt = valid_refl[idx] + length = path_lengths[idx] + + # Skip if already longer than best found + if length >= best_length: + continue + + # Check TX β†’ reflection LOS + intersects1, _ = line_intersects_polygons_batch( + tx, refl_pt, obstacle_polygons_x, obstacle_polygons_y, obstacle_lengths + ) + + if np.any(intersects1): + continue + + # Check reflection β†’ RX LOS + intersects2, _ = line_intersects_polygons_batch( + refl_pt, rx, obstacle_polygons_x, obstacle_polygons_y, obstacle_lengths + ) + + if np.any(intersects2): + continue + + # Valid path found! + best_idx = idx + best_length = length + break # ← EARLY EXIT: First valid shortest path is best + + if best_idx < 0: + return None, np.inf, 0.0 + + best_point = valid_refl[best_idx] + + # Reflection loss calculation + direct_dist = np.linalg.norm(rx - tx) + path_ratio = best_length / max(direct_dist, 1.0) + reflection_loss = 3.0 + 7.0 * min(1.0, (path_ratio - 1.0) * 2) + + return best_point, best_length, reflection_loss +``` + +**Key optimizations:** +1. **max_walls=100**: Only consider 100 closest walls (was 351-458) +2. **max_los_checks=10**: Only verify LOS for 10 shortest paths (was 50) +3. **Early exit**: Stop when first valid path found (sorted by length) + +**Expected speedup:** 5-10x for reflection calculation + +--- + +## πŸ”§ Fix 2.5.1b: Simplify LOS Check for Obstacles + +**File:** `backend/app/services/geometry_vectorized.py` + +**Optimize `line_intersects_polygons_batch()` β€” limit polygons:** + +```python +def line_intersects_polygons_batch( + p1: np.ndarray, p2: np.ndarray, + polygons_x: np.ndarray, polygons_y: np.ndarray, + polygon_lengths: np.ndarray, + max_polygons: int = 30 # ← ADD LIMIT +) -> Tuple[np.ndarray, np.ndarray]: + """ + Check if line p1β†’p2 intersects multiple polygons. + + OPTIMIZATION: Only check nearest polygons to the line. + """ + num_polygons = len(polygon_lengths) + + if num_polygons == 0: + return np.array([], dtype=bool), np.array([]) + + # === OPTIMIZATION: Filter to nearby polygons first === + if num_polygons > max_polygons: + # Quick filter: bounding box check + line_min_x = min(p1[0], p2[0]) - 50 # 50m buffer + line_max_x = max(p1[0], p2[0]) + 50 + line_min_y = min(p1[1], p2[1]) - 50 + line_max_y = max(p1[1], p2[1]) + 50 + + # Calculate polygon centroids quickly + # This is approximate but fast + idx = 0 + nearby_mask = np.zeros(num_polygons, dtype=bool) + + for i, length in enumerate(polygon_lengths): + if length < 3: + idx += length + continue + + # Polygon centroid (approximate: first vertex) + px = polygons_x[idx] + py = polygons_y[idx] + + # Check if centroid is near the line bounding box + if (line_min_x <= px <= line_max_x and + line_min_y <= py <= line_max_y): + nearby_mask[i] = True + + idx += length + + # If still too many, take first max_polygons that are nearby + nearby_indices = np.where(nearby_mask)[0] + if len(nearby_indices) > max_polygons: + nearby_indices = nearby_indices[:max_polygons] + nearby_mask = np.zeros(num_polygons, dtype=bool) + nearby_mask[nearby_indices] = True + else: + nearby_mask = np.ones(num_polygons, dtype=bool) + + # Now check only nearby polygons + intersects = np.zeros(num_polygons, dtype=bool) + min_t = np.ones(num_polygons) * np.inf + + idx = 0 + for i, length in enumerate(polygon_lengths): + if length < 3 or not nearby_mask[i]: + idx += length + continue + + # Get polygon vertices + px = polygons_x[idx:idx + length] + py = polygons_y[idx:idx + length] + + # Create edge segments + starts = np.stack([px, py], axis=1) + ends = np.stack([np.roll(px, -1), np.roll(py, -1)], axis=1) + + # Check intersections + edge_intersects, t_vals = line_segments_intersect_batch(p1, p2, starts, ends) + + if np.any(edge_intersects): + intersects[i] = True + min_t[i] = np.min(t_vals[edge_intersects]) + + idx += length + + line_length = np.linalg.norm(p2 - p1) + min_distances = min_t * line_length + + return intersects, min_distances +``` + +--- + +## πŸ”§ Fix 2.5.1c: Update Constants in dominant_path_service.py + +**File:** `backend/app/services/dominant_path_service.py` + +```python +# At top of file, update constants: +MAX_BUILDINGS_FOR_LINE = 30 # was 50 +MAX_BUILDINGS_FOR_REFLECTION = 20 # was 30 +MAX_DISTANCE_FROM_PATH = 200 # was 300m + +# In find_dominant_paths_vectorized(), add parameters: +result = find_best_reflection_path_vectorized( + tx_local, rx_local, + walls_start, walls_end, wall_to_bldg, + poly_x, poly_y, poly_lengths, + max_candidates=30, # was 50 + max_walls=100, # NEW: limit walls + max_los_checks=10 # NEW: limit LOS checks +) +``` + +--- + +## πŸ”΄ Fix 2.5.1d: App Close β€” AGGRESSIVE FIX + +**The X button STILL doesn't close the app!** + +**File:** `desktop/main.js` + +**Problem analysis:** +- `killBackend()` is called but processes survive +- `killAllBackendProcesses()` uses `execSync` but maybe fails silently +- Electron might quit before kill completes + +**AGGRESSIVE FIX β€” Multiple kill strategies:** + +```javascript +const { execSync, spawn } = require('child_process'); +const path = require('path'); + +let backendProcess = null; +let isQuitting = false; + +// Track all spawned PIDs +let knownPids = new Set(); + +function killAllRfcpProcesses() { + console.log('[KILL] === Starting aggressive kill ==='); + + if (process.platform === 'win32') { + // Strategy 1: Kill by image name (most reliable) + try { + console.log('[KILL] Strategy 1: taskkill /F /IM'); + execSync('taskkill /F /IM rfcp-server.exe', { + stdio: 'pipe', + timeout: 5000, + windowsHide: true + }); + console.log('[KILL] Strategy 1: SUCCESS'); + } catch (e) { + console.log('[KILL] Strategy 1: No processes or already killed'); + } + + // Strategy 2: Kill by tree if we have PID + if (backendProcess && backendProcess.pid) { + try { + console.log(`[KILL] Strategy 2: taskkill /F /T /PID ${backendProcess.pid}`); + execSync(`taskkill /F /T /PID ${backendProcess.pid}`, { + stdio: 'pipe', + timeout: 5000, + windowsHide: true + }); + console.log('[KILL] Strategy 2: SUCCESS'); + } catch (e) { + console.log('[KILL] Strategy 2: PID not found'); + } + } + + // Strategy 3: PowerShell kill (backup) + try { + console.log('[KILL] Strategy 3: PowerShell Stop-Process'); + execSync('powershell -Command "Get-Process rfcp-server -ErrorAction SilentlyContinue | Stop-Process -Force"', { + stdio: 'pipe', + timeout: 5000, + windowsHide: true + }); + console.log('[KILL] Strategy 3: SUCCESS'); + } catch (e) { + console.log('[KILL] Strategy 3: PowerShell failed or no processes'); + } + + // Strategy 4: WMIC kill (legacy but works) + try { + console.log('[KILL] Strategy 4: WMIC process delete'); + execSync('wmic process where "name=\'rfcp-server.exe\'" delete', { + stdio: 'pipe', + timeout: 5000, + windowsHide: true + }); + console.log('[KILL] Strategy 4: SUCCESS'); + } catch (e) { + console.log('[KILL] Strategy 4: WMIC failed'); + } + + } else { + // Unix + try { + execSync('pkill -9 -f rfcp-server', { stdio: 'pipe', timeout: 5000 }); + } catch (e) { + // Ignore + } + } + + console.log('[KILL] === Kill sequence complete ==='); +} + +// Call backend shutdown endpoint before killing +async function gracefulShutdown() { + console.log('[SHUTDOWN] Starting graceful shutdown...'); + + // Step 1: Try graceful API shutdown + try { + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), 2000); + + await fetch('http://127.0.0.1:8888/api/system/shutdown', { + method: 'POST', + signal: controller.signal + }); + + clearTimeout(timeout); + console.log('[SHUTDOWN] Backend acknowledged shutdown'); + + // Wait for backend to cleanup + await new Promise(r => setTimeout(r, 1000)); + + } catch (e) { + console.log('[SHUTDOWN] Backend did not respond:', e.message); + } + + // Step 2: Force kill everything + killAllRfcpProcesses(); + + // Step 3: Wait and verify + await new Promise(r => setTimeout(r, 500)); + + console.log('[SHUTDOWN] Shutdown complete'); +} + +// === EVENT HANDLERS === + +// When window X is clicked +mainWindow.on('close', async (event) => { + console.log('[EVENT] Window close clicked'); + + if (!isQuitting) { + event.preventDefault(); // Prevent immediate close + isQuitting = true; + + await gracefulShutdown(); + + // Now actually quit + app.quit(); + } +}); + +// When all windows closed +app.on('window-all-closed', () => { + console.log('[EVENT] All windows closed'); + killAllRfcpProcesses(); // Extra safety + + if (process.platform !== 'darwin') { + app.quit(); + } +}); + +// Before quit +app.on('before-quit', async (event) => { + console.log('[EVENT] Before quit'); + + if (!isQuitting) { + event.preventDefault(); + isQuitting = true; + await gracefulShutdown(); + app.quit(); + } +}); + +// Will quit (sync only!) +app.on('will-quit', () => { + console.log('[EVENT] Will quit - final sync kill'); + killAllRfcpProcesses(); +}); + +// Process exit +process.on('exit', () => { + console.log('[EVENT] Process exit'); + killAllRfcpProcesses(); +}); + +// Handle Ctrl+C in dev mode +process.on('SIGINT', () => { + console.log('[SIGNAL] SIGINT'); + killAllRfcpProcesses(); + process.exit(0); +}); + +process.on('SIGTERM', () => { + console.log('[SIGNAL] SIGTERM'); + killAllRfcpProcesses(); + process.exit(0); +}); +``` + +**Key changes:** +1. **4 kill strategies** on Windows (taskkill, PID tree, PowerShell, WMIC) +2. **`isQuitting` flag** prevents multiple shutdown attempts +3. **`event.preventDefault()`** on close to allow async shutdown +4. **Graceful shutdown first** via API, then force kill +5. **Every event handler** calls killAllRfcpProcesses() + +--- + +## πŸ”§ Fix 2.5.1e: Update Test Scripts for Win11 + +**File:** All .bat scripts + +**Replace `wmic` with PowerShell (wmic deprecated in Win11):** + +```batch +:: OLD (wmic - deprecated): +for /f "tokens=2 delims==" %%a in ('wmic OS get FreePhysicalMemory /value') do ... + +:: NEW (PowerShell): +for /f %%a in ('powershell -Command "(Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory"') do set /a FREE_RAM=%%a/1024 + +:: OLD (CPU): +for /f "tokens=2 delims==" %%a in ('wmic cpu get LoadPercentage /value') do ... + +:: NEW (PowerShell): +for /f %%a in ('powershell -Command "(Get-CimInstance Win32_Processor).LoadPercentage"') do set CPU=%%a +``` + +--- + +## πŸ“ Files to Modify + +| File | Changes | +|------|---------| +| `backend/app/services/geometry_vectorized.py` | Add max_walls, max_los_checks limits; optimize LOS check | +| `backend/app/services/dominant_path_service.py` | Update constants, pass new parameters | +| `desktop/main.js` | Aggressive multi-strategy kill; async shutdown with prevention | +| `installer/*.bat` | Replace wmic with PowerShell commands | + +--- + +## πŸ§ͺ Testing + +### Test 1: Performance +```bash +# Run Detailed preset +# Expected: < 90 seconds (was 292s) +# Expected: < 100ms/point (was 329ms) +``` + +### Test 2: App Close +```bash +# Start RFCP.exe +# Click X +# Check Task Manager β€” should be 0 rfcp-server.exe +# Check console for [KILL] logs showing all strategies +``` + +### Test 3: Accuracy Spot Check +```bash +# Run Standard preset, note coverage shape +# Run Detailed preset, compare coverage shape +# Should be similar (within visual inspection) +``` + +--- + +## βœ… Success Criteria + +- [ ] Detailed preset completes in < 90 seconds +- [ ] ms/point < 100ms (was 329ms) +- [ ] App close works on first X click +- [ ] No rfcp-server.exe in Task Manager after close +- [ ] Test scripts work on Windows 11 (no wmic errors) + +--- + +## πŸ“ˆ Expected Performance + +| Metric | Before 2.5.1 | After 2.5.1 | +|--------|--------------|-------------| +| Walls checked | 351-458 | 100 max | +| LOS checks | 50 | 10 max | +| ms/point | 329ms | ~50-80ms | +| Detailed time | 292s | ~60-90s | +| App close | ❌ broken | βœ… works | + +--- + +## πŸ”œ After 2.5.1 + +If performance is acceptable: +- Phase 2.6: Fun facts loading screen +- Phase 2.6: Export to GeoJSON/KML +- Phase 2.7: Multi-site interference visualization diff --git a/backend/app/services/coverage_service.py b/backend/app/services/coverage_service.py index d7d6ac3..753bfe3 100644 --- a/backend/app/services/coverage_service.py +++ b/backend/app/services/coverage_service.py @@ -44,7 +44,7 @@ from app.services.terrain_service import terrain_service, TerrainService from app.services.los_service import los_service from app.services.buildings_service import buildings_service, Building from app.services.materials_service import materials_service -from app.services.dominant_path_service import dominant_path_service +from app.services.dominant_path_service import dominant_path_service, find_dominant_paths_vectorized from app.services.street_canyon_service import street_canyon_service, Street from app.services.reflection_service import reflection_service from app.services.spatial_index import get_spatial_index, SpatialIndex @@ -648,22 +648,28 @@ class CoverageService: break timing["buildings"] += time.time() - t0 - # Dominant path (sync) β€” uses spatial index for O(1) building lookups + # Dominant path (vectorized NumPy) β€” replaces loop-based sync version if settings.use_dominant_path and (spatial_idx or nearby_buildings): t0 = time.time() - paths = dominant_path_service.find_dominant_paths_sync( + dominant = find_dominant_paths_vectorized( site.lat, site.lon, site.height, lat, lon, 1.5, site.frequency, nearby_buildings, - spatial_idx=spatial_idx + spatial_idx=spatial_idx, ) - if paths: - best_path = paths[0] - if best_path.is_valid and best_path.path_loss < (path_loss + terrain_loss + building_loss): - path_loss = best_path.path_loss - terrain_loss = 0 - building_loss = 0 - has_los = best_path.path_type == "direct" and not best_path.materials_crossed + if dominant['path_type'] == 'direct': + # Direct LOS confirmed by vectorized check + has_los = True + building_loss = 0.0 + elif dominant['path_type'] == 'reflection': + # Reflection path bypasses buildings β€” reduce building loss + building_loss = max(0.0, building_loss - (10.0 - dominant['total_loss'])) + has_los = False + elif dominant['path_type'] == 'diffraction': + # Diffraction: use estimated loss if worse than current + if dominant['total_loss'] > building_loss: + building_loss = dominant['total_loss'] + has_los = False timing["dominant_path"] += time.time() - t0 # Street canyon (sync) diff --git a/backend/app/services/dominant_path_service.py b/backend/app/services/dominant_path_service.py index 8915545..98e1cf0 100644 --- a/backend/app/services/dominant_path_service.py +++ b/backend/app/services/dominant_path_service.py @@ -1,10 +1,15 @@ import time import numpy as np -from typing import List, Tuple, Optional, TYPE_CHECKING +from typing import List, Tuple, Optional, Dict, Any, TYPE_CHECKING from dataclasses import dataclass from app.services.terrain_service import terrain_service from app.services.buildings_service import buildings_service, Building from app.services.materials_service import materials_service, BuildingMaterial +from app.services.geometry_vectorized import ( + points_to_local_coords, + line_intersects_polygons_batch, + find_best_reflection_path_vectorized, +) if TYPE_CHECKING: from app.services.spatial_index import SpatialIndex @@ -21,9 +26,9 @@ class RayPath: is_valid: bool # Does this path exist? -MAX_BUILDINGS_FOR_LINE = 50 -MAX_BUILDINGS_FOR_REFLECTION = 30 -MAX_DISTANCE_FROM_PATH = 300 # meters +MAX_BUILDINGS_FOR_LINE = 30 +MAX_BUILDINGS_FOR_REFLECTION = 20 +MAX_DISTANCE_FROM_PATH = 200 # meters def _filter_buildings_by_distance(buildings, tx_point, rx_point, max_count=100, max_distance=500): @@ -60,6 +65,204 @@ def _filter_buildings_by_distance(buildings, tx_point, rx_point, max_count=100, return filtered[:max_count] +# ── Vectorized dominant path (NumPy) ── + +_vec_log_count = 0 + + +def _buildings_to_arrays(buildings: List[Building], ref_lat: float, ref_lon: float): + """Convert Building objects to numpy arrays for vectorized geometry. + + Returns: + walls_start: (W, 2) wall start points in local XY meters + walls_end: (W, 2) wall end points in local XY meters + wall_to_building: (W,) mapping wall index -> building index + poly_x: flattened polygon X coords + poly_y: flattened polygon Y coords + poly_lengths: (num_polygons,) vertices per polygon + """ + all_walls_start = [] + all_walls_end = [] + wall_to_building = [] + + all_poly_x = [] + all_poly_y = [] + poly_lengths = [] + + for i, b in enumerate(buildings): + geom = b.geometry # [[lon, lat], ...] + if not geom or len(geom) < 3: + poly_lengths.append(0) + continue + + poly_lats = np.array([p[1] for p in geom]) + poly_lons = np.array([p[0] for p in geom]) + px, py = points_to_local_coords(ref_lat, ref_lon, poly_lats, poly_lons) + + all_poly_x.extend(px) + all_poly_y.extend(py) + poly_lengths.append(len(geom)) + + # Extract wall segments + for j in range(len(geom) - 1): + all_walls_start.append([px[j], py[j]]) + all_walls_end.append([px[j + 1], py[j + 1]]) + wall_to_building.append(i) + + return ( + np.array(all_walls_start) if all_walls_start else np.zeros((0, 2)), + np.array(all_walls_end) if all_walls_end else np.zeros((0, 2)), + np.array(wall_to_building, dtype=int) if wall_to_building else np.zeros(0, dtype=int), + np.array(all_poly_x) if all_poly_x else np.zeros(0), + np.array(all_poly_y) if all_poly_y else np.zeros(0), + np.array(poly_lengths, dtype=int), + ) + + +def find_dominant_paths_vectorized( + tx_lat: float, tx_lon: float, tx_height: float, + rx_lat: float, rx_lon: float, rx_height: float, + frequency_mhz: float, + buildings: List[Building], + spatial_idx: 'Optional[SpatialIndex]' = None, +) -> Dict[str, Any]: + """Vectorized dominant path finding using NumPy batch operations. + + Replaces the loop-based find_dominant_paths_sync() with: + 1. Batch building-to-array conversion + 2. Vectorized LOS polygon intersection check + 3. Vectorized reflection point calculation + 4. Simplified diffraction estimate + + Returns dict with: + has_los, path_type, total_loss, path_length, reflection_point + """ + global _vec_log_count + + # Get nearby buildings via spatial index (same filtering as sync version) + if spatial_idx: + line_buildings = spatial_idx.query_line(tx_lat, tx_lon, rx_lat, rx_lon) + else: + line_buildings = buildings + + line_buildings = _filter_buildings_by_distance( + line_buildings, + (tx_lat, tx_lon), (rx_lat, rx_lon), + max_count=MAX_BUILDINGS_FOR_LINE, + max_distance=MAX_DISTANCE_FROM_PATH, + ) + + # Reference point for local coordinate system + ref_lat = (tx_lat + rx_lat) / 2 + ref_lon = (tx_lon + rx_lon) / 2 + + # Convert TX/RX to local meters + tx_xy = points_to_local_coords(ref_lat, ref_lon, np.array([tx_lat]), np.array([tx_lon])) + rx_xy = points_to_local_coords(ref_lat, ref_lon, np.array([rx_lat]), np.array([rx_lon])) + tx = np.array([tx_xy[0][0], tx_xy[1][0]]) + rx = np.array([rx_xy[0][0], rx_xy[1][0]]) + + direct_dist = np.linalg.norm(rx - tx) + + # Convert buildings to arrays + walls_start, walls_end, wall_to_bldg, poly_x, poly_y, poly_lengths = ( + _buildings_to_arrays(line_buildings, ref_lat, ref_lon) + ) + + # Diagnostic log for first few points + _vec_log_count += 1 + if _vec_log_count <= 3: + print( + f"[DOMINANT_PATH_VEC] Point #{_vec_log_count}: " + f"buildings={len(line_buildings)}, walls={len(walls_start)}, " + f"dist={direct_dist:.0f}m", + flush=True, + ) + + # No buildings β†’ direct LOS + if len(poly_lengths) == 0 or np.all(poly_lengths < 3): + return { + 'has_los': True, + 'path_type': 'direct', + 'total_loss': 0.0, + 'path_length': direct_dist, + 'reflection_point': None, + } + + # Step 1: Vectorized direct LOS check + intersects, _ = line_intersects_polygons_batch(tx, rx, poly_x, poly_y, poly_lengths) + + if not np.any(intersects): + return { + 'has_los': True, + 'path_type': 'direct', + 'total_loss': 0.0, + 'path_length': direct_dist, + 'reflection_point': None, + } + + # Step 2: Vectorized reflection path finding + # Use all line buildings for reflection walls + if spatial_idx: + mid_lat = (tx_lat + rx_lat) / 2 + mid_lon = (tx_lon + rx_lon) / 2 + refl_buildings = spatial_idx.query_point(mid_lat, mid_lon, buffer_cells=3) + refl_buildings = _filter_buildings_by_distance( + refl_buildings, + (tx_lat, tx_lon), (rx_lat, rx_lon), + max_count=MAX_BUILDINGS_FOR_REFLECTION, + max_distance=MAX_DISTANCE_FROM_PATH, + ) + # Merge line + reflection buildings (deduplicate by id) + seen_ids = {b.id for b in line_buildings} + merged = list(line_buildings) + for b in refl_buildings: + if b.id not in seen_ids: + merged.append(b) + seen_ids.add(b.id) + r_walls_start, r_walls_end, r_wall_to_bldg, r_poly_x, r_poly_y, r_poly_lengths = ( + _buildings_to_arrays(merged, ref_lat, ref_lon) + ) + else: + r_walls_start, r_walls_end, r_wall_to_bldg = walls_start, walls_end, wall_to_bldg + r_poly_x, r_poly_y, r_poly_lengths = poly_x, poly_y, poly_lengths + + refl_point, refl_length, refl_loss = find_best_reflection_path_vectorized( + tx, rx, + r_walls_start, r_walls_end, r_wall_to_bldg, + r_poly_x, r_poly_y, r_poly_lengths, + max_candidates=30, + max_walls=100, + max_los_checks=10, + ) + + if refl_point is not None: + # Convert reflection point back to lat/lon + cos_lat = np.cos(np.radians(ref_lat)) + refl_lat = ref_lat + refl_point[1] / 110540.0 + refl_lon = ref_lon + refl_point[0] / (111320.0 * cos_lat) + + return { + 'has_los': False, + 'path_type': 'reflection', + 'total_loss': refl_loss, + 'path_length': refl_length, + 'reflection_point': (refl_lat, refl_lon), + } + + # Step 3: Diffraction fallback + num_blocking = int(np.sum(intersects)) + diffraction_loss = 10.0 + 5.0 * min(num_blocking, 5) + + return { + 'has_los': False, + 'path_type': 'diffraction', + 'total_loss': diffraction_loss, + 'path_length': direct_dist, + 'reflection_point': None, + } + + class DominantPathService: """ Find dominant propagation paths (2-3 strongest) diff --git a/backend/app/services/geometry_vectorized.py b/backend/app/services/geometry_vectorized.py new file mode 100644 index 0000000..b6676c0 --- /dev/null +++ b/backend/app/services/geometry_vectorized.py @@ -0,0 +1,309 @@ +""" +Vectorized geometry operations using NumPy. + +All functions operate on arrays, not single values. +Provides 10-50x speedup over Python loops for batch geometry checks. +""" + +import numpy as np +from typing import Tuple, Optional + +EARTH_RADIUS = 6371000 # meters + + +def haversine_batch( + lat1: float, lon1: float, + lats2: np.ndarray, lons2: np.ndarray, +) -> np.ndarray: + """Distance from one point to many points (meters).""" + lat1_rad = np.radians(lat1) + lon1_rad = np.radians(lon1) + lats2_rad = np.radians(lats2) + lons2_rad = np.radians(lons2) + + dlat = lats2_rad - lat1_rad + dlon = lons2_rad - lon1_rad + + a = np.sin(dlat / 2) ** 2 + np.cos(lat1_rad) * np.cos(lats2_rad) * np.sin(dlon / 2) ** 2 + c = 2 * np.arcsin(np.sqrt(a)) + + return EARTH_RADIUS * c + + +def points_to_local_coords( + ref_lat: float, ref_lon: float, + lats: np.ndarray, lons: np.ndarray, +) -> Tuple[np.ndarray, np.ndarray]: + """Convert lat/lon to local X/Y meters (equirectangular projection).""" + cos_lat = np.cos(np.radians(ref_lat)) + x = (lons - ref_lon) * 111320.0 * cos_lat + y = (lats - ref_lat) * 110540.0 + return x, y + + +def line_segments_intersect_batch( + p1: np.ndarray, p2: np.ndarray, + segments_start: np.ndarray, segments_end: np.ndarray, +) -> Tuple[np.ndarray, np.ndarray]: + """Check if line p1->p2 intersects with N segments. + + Args: + p1, p2: shape (2,) + segments_start, segments_end: shape (N, 2) + + Returns: + intersects: bool array (N,) + t_values: parameter along p1->p2 (N,) + """ + d = p2 - p1 + seg_d = segments_end - segments_start + + cross = d[0] * seg_d[:, 1] - d[1] * seg_d[:, 0] + + parallel_mask = np.abs(cross) < 1e-10 + cross_safe = np.where(parallel_mask, 1.0, cross) + + dp = p1 - segments_start + + t = (dp[:, 0] * seg_d[:, 1] - dp[:, 1] * seg_d[:, 0]) / cross_safe + u = (dp[:, 0] * d[1] - dp[:, 1] * d[0]) / cross_safe + + intersects = ~parallel_mask & (t >= 0) & (t <= 1) & (u >= 0) & (u <= 1) + + return intersects, t + + +def line_intersects_polygons_batch( + p1: np.ndarray, p2: np.ndarray, + polygons_x: np.ndarray, polygons_y: np.ndarray, + polygon_lengths: np.ndarray, + max_polygons: int = 30, +) -> Tuple[np.ndarray, np.ndarray]: + """Check if line p1->p2 intersects multiple polygons. + + Args: + p1, p2: shape (2,) + polygons_x, polygons_y: flattened vertex arrays + polygon_lengths: vertices per polygon (num_polygons,) + max_polygons: only check nearest N polygons (bbox pre-filter) + + Returns: + intersects: bool (num_polygons,) + min_distances: distance to first hit (num_polygons,) + """ + num_polygons = len(polygon_lengths) + + if num_polygons == 0: + return np.array([], dtype=bool), np.array([]) + + intersects = np.zeros(num_polygons, dtype=bool) + min_t = np.full(num_polygons, np.inf) + + # Pre-filter: only check polygons whose first vertex is near the line bbox + if num_polygons > max_polygons: + buf = 50.0 # 50m buffer + line_min_x = min(p1[0], p2[0]) - buf + line_max_x = max(p1[0], p2[0]) + buf + line_min_y = min(p1[1], p2[1]) - buf + line_max_y = max(p1[1], p2[1]) + buf + + nearby_mask = np.zeros(num_polygons, dtype=bool) + vi = 0 + for i, length in enumerate(polygon_lengths): + if length >= 3: + cx = polygons_x[vi] + cy = polygons_y[vi] + if line_min_x <= cx <= line_max_x and line_min_y <= cy <= line_max_y: + nearby_mask[i] = True + vi += length + + # Cap at max_polygons + nearby_indices = np.where(nearby_mask)[0] + if len(nearby_indices) > max_polygons: + nearby_mask = np.zeros(num_polygons, dtype=bool) + nearby_mask[nearby_indices[:max_polygons]] = True + else: + nearby_mask = np.ones(num_polygons, dtype=bool) + + idx = 0 + for i, length in enumerate(polygon_lengths): + if length < 3 or not nearby_mask[i]: + idx += length + continue + + px = polygons_x[idx:idx + length] + py = polygons_y[idx:idx + length] + + starts = np.stack([px, py], axis=1) + ends = np.stack([np.roll(px, -1), np.roll(py, -1)], axis=1) + + edge_intersects, t_vals = line_segments_intersect_batch(p1, p2, starts, ends) + + if np.any(edge_intersects): + intersects[i] = True + min_t[i] = np.min(t_vals[edge_intersects]) + + idx += length + + line_length = np.linalg.norm(p2 - p1) + min_distances = min_t * line_length + + return intersects, min_distances + + +def calculate_reflection_points_batch( + tx: np.ndarray, rx: np.ndarray, + wall_starts: np.ndarray, wall_ends: np.ndarray, +) -> Tuple[np.ndarray, np.ndarray]: + """Calculate reflection points on N walls via mirror-image method. + + Args: + tx, rx: shape (2,) + wall_starts, wall_ends: shape (N, 2) + + Returns: + reflection_points: (N, 2) + valid: bool (N,) + """ + wall_vec = wall_ends - wall_starts + wall_length = np.linalg.norm(wall_vec, axis=1, keepdims=True) + wall_unit = wall_vec / np.maximum(wall_length, 1e-10) + + normals = np.stack([-wall_unit[:, 1], wall_unit[:, 0]], axis=1) + + tx_to_wall = tx - wall_starts + tx_dist_to_wall = np.sum(tx_to_wall * normals, axis=1, keepdims=True) + tx_mirror = tx - 2 * tx_dist_to_wall * normals + + rx_to_mirror = tx_mirror - rx + + cross_denom = (rx_to_mirror[:, 0] * wall_vec[:, 1] - + rx_to_mirror[:, 1] * wall_vec[:, 0]) + + valid_denom = np.abs(cross_denom) > 1e-10 + cross_denom_safe = np.where(valid_denom, cross_denom, 1.0) + + rx_to_start = wall_starts - rx + t = (rx_to_start[:, 0] * rx_to_mirror[:, 1] - + rx_to_start[:, 1] * rx_to_mirror[:, 0]) / cross_denom_safe + + reflection_points = wall_starts + t[:, np.newaxis] * wall_vec + + valid = valid_denom & (t >= 0) & (t <= 1) & (tx_dist_to_wall[:, 0] > 0) + + return reflection_points, valid + + +def find_best_reflection_path_vectorized( + tx: np.ndarray, rx: np.ndarray, + building_walls_start: np.ndarray, + building_walls_end: np.ndarray, + wall_to_building: np.ndarray, + obstacle_polygons_x: np.ndarray, + obstacle_polygons_y: np.ndarray, + obstacle_lengths: np.ndarray, + max_candidates: int = 50, + max_walls: int = 100, + max_los_checks: int = 10, +) -> Tuple[Optional[np.ndarray], float, float]: + """Find best single-reflection path using vectorized ops. + + Args: + max_walls: Only consider closest N walls for reflection candidates. + max_los_checks: Only verify LOS for top N shortest reflection paths. + + Returns: + best_reflection_point: (2,) or None + best_path_length: meters + best_reflection_loss: dB + """ + num_walls = len(building_walls_start) + if num_walls == 0: + return None, np.inf, 0.0 + + # Limit walls by distance to path midpoint + if num_walls > max_walls: + midpoint = (tx + rx) / 2 + wall_midpoints = (building_walls_start + building_walls_end) / 2 + wall_distances = np.linalg.norm(wall_midpoints - midpoint, axis=1) + closest = np.argpartition(wall_distances, max_walls)[:max_walls] + building_walls_start = building_walls_start[closest] + building_walls_end = building_walls_end[closest] + wall_to_building = wall_to_building[closest] + + refl_points, valid = calculate_reflection_points_batch( + tx, rx, building_walls_start, building_walls_end, + ) + + if not np.any(valid): + return None, np.inf, 0.0 + + valid_indices = np.where(valid)[0] + valid_refl = refl_points[valid] + + tx_to_refl = np.linalg.norm(valid_refl - tx, axis=1) + refl_to_rx = np.linalg.norm(rx - valid_refl, axis=1) + path_lengths = tx_to_refl + refl_to_rx + + # Direct distance filter: skip if reflection path > 2x direct + direct_dist = np.linalg.norm(rx - tx) + within_range = path_lengths <= direct_dist * 2.0 + if not np.any(within_range): + return None, np.inf, 0.0 + + valid_indices = valid_indices[within_range] + valid_refl = valid_refl[within_range] + path_lengths = path_lengths[within_range] + + # Keep top candidates by shortest path + if len(valid_indices) > max_candidates: + top_idx = np.argpartition(path_lengths, max_candidates)[:max_candidates] + valid_indices = valid_indices[top_idx] + valid_refl = valid_refl[top_idx] + path_lengths = path_lengths[top_idx] + + # Sort by path length for early exit + sort_order = np.argsort(path_lengths) + valid_refl = valid_refl[sort_order] + path_lengths = path_lengths[sort_order] + + # Check LOS only for top N shortest candidates + check_count = min(len(valid_refl), max_los_checks) + best_idx = -1 + best_length = np.inf + + for i in range(check_count): + length = path_lengths[i] + if length >= best_length: + continue + + refl_pt = valid_refl[i] + + # TX -> reflection LOS + intersects1, _ = line_intersects_polygons_batch( + tx, refl_pt, obstacle_polygons_x, obstacle_polygons_y, obstacle_lengths, + ) + if np.any(intersects1): + continue + + # Reflection -> RX LOS + intersects2, _ = line_intersects_polygons_batch( + refl_pt, rx, obstacle_polygons_x, obstacle_polygons_y, obstacle_lengths, + ) + if np.any(intersects2): + continue + + best_idx = i + best_length = length + break # sorted by length, first valid is best + + if best_idx < 0: + return None, np.inf, 0.0 + + best_point = valid_refl[best_idx] + + # Reflection loss: 3-10 dB depending on path ratio + path_ratio = best_length / max(direct_dist, 1.0) + reflection_loss = 3.0 + 7.0 * min(1.0, (path_ratio - 1.0) * 2) + + return best_point, best_length, reflection_loss diff --git a/desktop/main.js b/desktop/main.js index 068c3e8..cd47c2a 100644 --- a/desktop/main.js +++ b/desktop/main.js @@ -269,17 +269,23 @@ function createMainWindow() { }); // Save window state on close and trigger shutdown - mainWindow.on('close', () => { + mainWindow.on('close', (event) => { log('[CLOSE] Window close event fired, isQuitting=' + isQuitting); try { const bounds = mainWindow.getBounds(); store.set('windowState', bounds); } catch (_e) {} - isQuitting = true; - // Graceful shutdown is async but we also do sync kill as safety net - gracefulShutdown().catch(() => {}); - killBackend(); - killAllBackendProcesses(); + + if (!isQuitting) { + event.preventDefault(); + isQuitting = true; + gracefulShutdown().then(() => { + app.quit(); + }).catch(() => { + killAllRfcpProcesses(); + app.quit(); + }); + } }); // Load frontend @@ -364,41 +370,86 @@ function killBackend() { } /** - * Nuclear option: kill ALL rfcp-server processes by name. - * This catches orphaned workers that PID-based kill misses. + * Aggressive kill: multiple strategies to ensure ALL rfcp-server processes die. + * Uses 4 strategies on Windows for maximum reliability. */ -function killAllBackendProcesses() { - log('[KILL] killAllBackendProcesses() β€” killing by process name...'); +function killAllRfcpProcesses() { + log('[KILL] === Starting aggressive kill ==='); if (process.platform === 'win32') { + // Strategy 1: Kill by image name (most reliable) try { - execSync('taskkill /F /IM rfcp-server.exe /T', { - stdio: 'ignore', - timeout: 5000 + log('[KILL] Strategy 1: taskkill /F /IM'); + execSync('taskkill /F /IM rfcp-server.exe', { + stdio: 'pipe', + timeout: 5000, + windowsHide: true }); - log('[KILL] taskkill /IM rfcp-server.exe completed'); + log('[KILL] Strategy 1: SUCCESS'); } catch (_e) { - // Error means no processes found β€” OK - log('[KILL] No rfcp-server.exe processes found (or already killed)'); + log('[KILL] Strategy 1: No processes or already killed'); + } + + // Strategy 2: Kill by PID tree if we have PID + if (backendPid) { + try { + log(`[KILL] Strategy 2: taskkill /F /T /PID ${backendPid}`); + execSync(`taskkill /F /T /PID ${backendPid}`, { + stdio: 'pipe', + timeout: 5000, + windowsHide: true + }); + log('[KILL] Strategy 2: SUCCESS'); + } catch (_e) { + log('[KILL] Strategy 2: PID not found'); + } + } + + // Strategy 3: PowerShell kill (backup) + try { + log('[KILL] Strategy 3: PowerShell Stop-Process'); + execSync('powershell -Command "Get-Process rfcp-server -ErrorAction SilentlyContinue | Stop-Process -Force"', { + stdio: 'pipe', + timeout: 5000, + windowsHide: true + }); + log('[KILL] Strategy 3: SUCCESS'); + } catch (_e) { + log('[KILL] Strategy 3: PowerShell failed or no processes'); + } + + // Strategy 4: PowerShell CimInstance terminate (modern replacement for wmic) + try { + log('[KILL] Strategy 4: PowerShell CimInstance Terminate'); + execSync('powershell -NoProfile -Command "Get-CimInstance Win32_Process -Filter \\"name=\'rfcp-server.exe\'\\" | Invoke-CimMethod -MethodName Terminate"', { + stdio: 'pipe', + timeout: 5000, + windowsHide: true + }); + log('[KILL] Strategy 4: SUCCESS'); + } catch (_e) { + log('[KILL] Strategy 4: No processes or failed'); } } else { + // Unix: pkill try { - execSync('pkill -9 -f rfcp-server', { - stdio: 'ignore', - timeout: 5000 - }); + execSync('pkill -9 -f rfcp-server', { stdio: 'pipe', timeout: 5000 }); log('[KILL] pkill rfcp-server completed'); } catch (_e) { log('[KILL] No rfcp-server processes found'); } } + + backendPid = null; + backendProcess = null; + log('[KILL] === Kill sequence complete ==='); } /** - * Graceful shutdown: ask backend to clean up, then force kill everything. + * Graceful shutdown: API call first, then multi-strategy force kill. */ async function gracefulShutdown() { - log('[SHUTDOWN] Requesting graceful shutdown...'); + log('[SHUTDOWN] Starting graceful shutdown...'); // Step 1: Ask backend to clean up workers and exit try { @@ -410,18 +461,18 @@ async function gracefulShutdown() { }); clearTimeout(timeout); log('[SHUTDOWN] Backend acknowledged shutdown'); + // Wait for backend to cleanup + await new Promise(r => setTimeout(r, 1000)); } catch (_e) { log('[SHUTDOWN] Backend did not respond β€” force killing'); } - // Step 2: Wait briefly for graceful exit + // Step 2: Force kill everything + killAllRfcpProcesses(); + + // Step 3: Wait and verify await new Promise(r => setTimeout(r, 500)); - - // Step 3: PID-based kill (catches the main process) - killBackend(); - - // Step 4: Name-based kill (catches orphaned workers) - killAllBackendProcesses(); + log('[SHUTDOWN] Shutdown complete'); } // ── App lifecycle ────────────────────────────────────────────────── @@ -456,8 +507,7 @@ app.whenReady().then(async () => { app.on('window-all-closed', () => { log('[CLOSE] window-all-closed fired'); isQuitting = true; - killBackend(); - killAllBackendProcesses(); + killAllRfcpProcesses(); if (process.platform !== 'darwin') { app.quit(); @@ -470,17 +520,23 @@ app.on('activate', () => { } }); -app.on('before-quit', () => { - log('[CLOSE] before-quit fired'); - isQuitting = true; - killBackend(); - killAllBackendProcesses(); +app.on('before-quit', (event) => { + log('[CLOSE] before-quit fired, isQuitting=' + isQuitting); + if (!isQuitting) { + event.preventDefault(); + isQuitting = true; + gracefulShutdown().then(() => { + app.quit(); + }).catch(() => { + killAllRfcpProcesses(); + app.quit(); + }); + } }); app.on('will-quit', () => { log('[CLOSE] will-quit fired'); - killBackend(); - killAllBackendProcesses(); + killAllRfcpProcesses(); if (backendLogStream) { try { backendLogStream.end(); } catch (_e) {} @@ -508,21 +564,19 @@ process.on('exit', () => { } // Name-based kill β€” catches orphaned workers - killAllBackendProcesses(); + killAllRfcpProcesses(); }); // Handle SIGINT/SIGTERM (Ctrl+C, system shutdown) process.on('SIGINT', () => { try { log('[SIGNAL] SIGINT received'); } catch (_e) {} - killBackend(); - killAllBackendProcesses(); + killAllRfcpProcesses(); process.exit(0); }); process.on('SIGTERM', () => { try { log('[SIGNAL] SIGTERM received'); } catch (_e) {} - killBackend(); - killAllBackendProcesses(); + killAllRfcpProcesses(); process.exit(0); }); diff --git a/files.zip b/files.zip new file mode 100644 index 0000000000000000000000000000000000000000..145fb86a904d9b7524984a241150086d30c54b20 GIT binary patch literal 161446 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%0AYP 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') do ( + set /a PROC_COUNT+=1 + set MEM_STR=%%m + set MEM_STR=!MEM_STR:,=! + set MEM_STR=!MEM_STR: =! + if "!MEM_STR!" NEQ "" ( + set /a TOTAL_MEM+=!MEM_STR! 2>nul + ) +) +set /a TOTAL_MEM_MB=TOTAL_MEM/1024 2>nul + +:: Get free RAM (PowerShell β€” wmic deprecated in Win11) +for /f %%a in ('powershell -NoProfile -Command "(Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory" 2^>nul') do ( + set /a FREE_RAM=%%a/1024 2>nul +) + +:: Get CPU load (PowerShell β€” wmic deprecated in Win11) +for /f %%a in ('powershell -NoProfile -Command "(Get-CimInstance Win32_Processor).LoadPercentage" 2^>nul') do ( + set CPU=%%a +) + +:: Display +echo %T% %CPU%%% %TOTAL_MEM_MB% %PROC_COUNT% %FREE_RAM% + +:: Wait 2 seconds +timeout /t 2 /nobreak >nul + +goto loop diff --git a/installer/rfcp-debug-enhanced.bat b/installer/rfcp-debug-enhanced.bat new file mode 100644 index 0000000..8fb8281 --- /dev/null +++ b/installer/rfcp-debug-enhanced.bat @@ -0,0 +1,93 @@ +@echo off +title RFCP Debug Launcher + Monitor +setlocal EnableDelayedExpansion + +echo ============================================ +echo RFCP Debug Launcher + Monitor +echo ============================================ +echo. + +:: Kill any running instance +echo [1/3] Cleaning up existing processes... +taskkill /F /IM rfcp-server.exe 2>nul +if %ERRORLEVEL% EQU 0 ( + echo Killed existing rfcp-server.exe + timeout /t 2 /nobreak >nul +) else ( + echo No existing process found +) +echo. + +:: Environment setup +set PYTHONUNBUFFERED=1 +set RFCP_DEBUG=1 +set RFCP_HOST=127.0.0.1 +set RFCP_PORT=8888 + +echo [2/3] Environment: +echo PYTHONUNBUFFERED=%PYTHONUNBUFFERED% +echo RFCP_DEBUG=%RFCP_DEBUG% +echo RFCP_HOST=%RFCP_HOST% +echo RFCP_PORT=%RFCP_PORT% +echo. + +:: Find executable +if exist "%~dp0dist\rfcp-server.exe" ( + set EXE_PATH=%~dp0dist\rfcp-server.exe + set WORK_DIR=%~dp0dist +) else if exist "%~dp0rfcp-server.exe" ( + set EXE_PATH=%~dp0rfcp-server.exe + set WORK_DIR=%~dp0 +) else ( + echo [ERROR] rfcp-server.exe not found! + pause + exit /b 1 +) + +echo [3/3] Starting server... +echo Executable: %EXE_PATH% +echo Working dir: %WORK_DIR% +echo. + +:: Create log directory +set LOG_DIR=%WORK_DIR%\logs +if not exist "%LOG_DIR%" mkdir "%LOG_DIR%" + +:: Log file with timestamp +set TIMESTAMP=%date:~-4%%date:~3,2%%date:~0,2%-%time:~0,2%%time:~3,2%%time:~6,2% +set TIMESTAMP=%TIMESTAMP: =0% +set LOG_FILE=%LOG_DIR%\server-%TIMESTAMP%.log + +echo Log file: %LOG_FILE% +echo. +echo ============================================ +echo SERVER OUTPUT (also saved to log) +echo ============================================ +echo. + +cd /d "%WORK_DIR%" + +:: Run server and tee to log file +:: Note: PowerShell tee for dual output +powershell -Command "& '%EXE_PATH%' 2>&1 | Tee-Object -FilePath '%LOG_FILE%'" + +echo. +echo ============================================ +echo Server stopped +echo Log saved to: %LOG_FILE% +echo ============================================ + +:: Post-mortem check +echo. +echo [POST-MORTEM] Checking for orphan processes... +for /f %%a in ('tasklist /FI "IMAGENAME eq rfcp-server.exe" 2^>nul ^| find /c "rfcp-server"') do ( + if %%a GTR 0 ( + echo WARNING: %%a rfcp-server process(es) still running! + echo Run: taskkill /F /IM rfcp-server.exe + ) else ( + echo All processes cleaned up properly. + ) +) + +echo. +pause diff --git a/installer/test-coverage-monitor.bat b/installer/test-coverage-monitor.bat new file mode 100644 index 0000000..cf03018 --- /dev/null +++ b/installer/test-coverage-monitor.bat @@ -0,0 +1,282 @@ +@echo off +title RFCP Coverage API Test + Resource Monitor +setlocal EnableDelayedExpansion + +echo ============================================ +echo RFCP Coverage API Test + Resource Monitor +echo ============================================ +echo. + +set API=http://127.0.0.1:8888 +set RESULTS_DIR=%~dp0test-results +set TIMESTAMP=%date:~-4%%date:~3,2%%date:~0,2%-%time:~0,2%%time:~3,2% +set TIMESTAMP=%TIMESTAMP: =0% + +:: Create results directory +if not exist "%RESULTS_DIR%" mkdir "%RESULTS_DIR%" + +:: Log file for this run +set LOG_FILE=%RESULTS_DIR%\test-run-%TIMESTAMP%.log + +echo Test started: %date% %time% > "%LOG_FILE%" +echo. >> "%LOG_FILE%" + +:: =========================================== +:: SYSTEM INFO +:: =========================================== +echo [SYSTEM] Collecting system info... +echo. >> "%LOG_FILE%" +echo === SYSTEM INFO === >> "%LOG_FILE%" + +:: CPU info (PowerShell β€” wmic deprecated in Win11) +for /f "delims=" %%a in ('powershell -NoProfile -Command "(Get-CimInstance Win32_Processor).Name"') do ( + echo CPU: %%a >> "%LOG_FILE%" + echo CPU: %%a +) + +:: RAM info (PowerShell) +for /f %%a in ('powershell -NoProfile -Command "(Get-CimInstance Win32_OperatingSystem).TotalVisibleMemorySize"') do ( + set /a RAM_GB=%%a/1024/1024 + echo RAM: !RAM_GB! GB >> "%LOG_FILE%" + echo RAM: !RAM_GB! GB +) + +:: GPU info (PowerShell) +echo GPU: >> "%LOG_FILE%" +for /f "delims=" %%a in ('powershell -NoProfile -Command "(Get-CimInstance Win32_VideoController).Name"') do ( + echo %%a >> "%LOG_FILE%" + echo %%a +) + +echo. >> "%LOG_FILE%" +echo. + +:: =========================================== +:: PRE-TEST BASELINE +:: =========================================== +echo [BASELINE] Capturing baseline resource usage... + +:: Get baseline memory +for /f %%a in ('powershell -NoProfile -Command "(Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory"') do ( + set /a BASELINE_FREE_MB=%%a/1024 +) +echo Free RAM before: %BASELINE_FREE_MB% MB +echo Baseline free RAM: %BASELINE_FREE_MB% MB >> "%LOG_FILE%" + +:: Count rfcp processes +set RFCP_COUNT=0 +for /f %%a in ('tasklist /FI "IMAGENAME eq rfcp-server.exe" 2^>nul ^| find /c "rfcp-server"') do set RFCP_COUNT=%%a +echo RFCP processes: %RFCP_COUNT% +echo Baseline RFCP processes: %RFCP_COUNT% >> "%LOG_FILE%" +echo. >> "%LOG_FILE%" + +:: =========================================== +:: TEST 1: Health check +:: =========================================== +echo. +echo [TEST 1] Health check... +echo === TEST 1: Health Check === >> "%LOG_FILE%" + +curl -s -o nul -w "HTTP %%{http_code}\n" %API%/api/health +curl -s -w "HTTP %%{http_code}" %API%/api/health >> "%LOG_FILE%" +echo. >> "%LOG_FILE%" + +:: =========================================== +:: TEST 2: System info +:: =========================================== +echo. +echo [TEST 2] Backend system info: +echo === TEST 2: Backend System Info === >> "%LOG_FILE%" + +curl -s %API%/api/system/info +curl -s %API%/api/system/info >> "%LOG_FILE%" +echo. +echo. >> "%LOG_FILE%" + +:: =========================================== +:: TEST 3: Fast preset +:: =========================================== +echo. +echo [TEST 3] Coverage - Fast preset (2km, 500m res) +echo Expected: ^< 1 second +echo === TEST 3: Fast Preset === >> "%LOG_FILE%" + +:: Capture start memory +for /f %%a in ('powershell -NoProfile -Command "(Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory"') do set /a START_FREE=%%a/1024 + +set START_TIME=%time% +curl -s -w "\nTime: %%{time_total}s | HTTP: %%{http_code}" ^ + -X POST %API%/api/coverage/calculate ^ + -H "Content-Type: application/json" ^ + -d "{\"sites\": [{\"lat\": 50.45, \"lon\": 30.52, \"height\": 30, \"power\": 43, \"gain\": 15, \"frequency\": 1800}], \"settings\": {\"radius\": 2000, \"resolution\": 500, \"preset\": \"fast\"}}" ^ + -o "%RESULTS_DIR%\coverage-fast.json" + +set END_TIME=%time% + +:: Capture end memory +for /f %%a in ('powershell -NoProfile -Command "(Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory"') do set /a END_FREE=%%a/1024 +set /a MEM_USED=START_FREE-END_FREE + +echo. +echo Memory delta: %MEM_USED% MB +echo Time: %START_TIME% - %END_TIME% >> "%LOG_FILE%" +echo Memory delta: %MEM_USED% MB >> "%LOG_FILE%" +echo. >> "%LOG_FILE%" + +:: =========================================== +:: TEST 4: Standard preset +:: =========================================== +echo. +echo [TEST 4] Coverage - Standard preset (5km, 300m res) +echo Expected: 30-45 seconds +echo === TEST 4: Standard Preset === >> "%LOG_FILE%" + +:: Monitor resources during test +echo Starting resource monitor... +start /b cmd /c "for /l %%i in (1,1,120) do (for /f %%a in ('powershell -NoProfile -Command "(Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory" 2^>nul') do echo [%%i] Free: %%a KB >> "%RESULTS_DIR%\monitor-standard.log") & timeout /t 1 /nobreak >nul 2>&1" + +for /f %%a in ('powershell -NoProfile -Command "(Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory"') do set /a START_FREE=%%a/1024 + +curl -s -w "\nTime: %%{time_total}s | HTTP: %%{http_code}" ^ + -X POST %API%/api/coverage/calculate ^ + -H "Content-Type: application/json" ^ + -d "{\"sites\": [{\"lat\": 50.45, \"lon\": 30.52, \"height\": 30, \"power\": 43, \"gain\": 15, \"frequency\": 1800}], \"settings\": {\"radius\": 5000, \"resolution\": 300, \"preset\": \"standard\"}}" ^ + -o "%RESULTS_DIR%\coverage-standard.json" + +for /f %%a in ('powershell -NoProfile -Command "(Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory"') do set /a END_FREE=%%a/1024 +set /a MEM_USED=START_FREE-END_FREE +set /a PEAK_FROM_BASELINE=BASELINE_FREE_MB-END_FREE + +echo. +echo Memory delta: %MEM_USED% MB (peak from baseline: %PEAK_FROM_BASELINE% MB) +echo Memory delta: %MEM_USED% MB >> "%LOG_FILE%" + +:: Count RFCP processes +for /f %%a in ('tasklist /FI "IMAGENAME eq rfcp-server.exe" 2^>nul ^| find /c "rfcp-server"') do set RFCP_COUNT=%%a +echo RFCP processes: %RFCP_COUNT% +echo RFCP processes: %RFCP_COUNT% >> "%LOG_FILE%" +echo. >> "%LOG_FILE%" + +:: =========================================== +:: TEST 5: Detailed preset (the big one!) +:: =========================================== +echo. +echo [TEST 5] Coverage - Detailed preset (5km, 300m res) +echo Expected: ^< 90 seconds (was 300s timeout) +echo THIS IS THE VECTORIZATION TEST! +echo === TEST 5: Detailed Preset (VECTORIZATION TEST) === >> "%LOG_FILE%" + +:: Start intensive resource monitor +echo Starting intensive resource monitor (every 2s)... +start /b cmd /c "for /l %%i in (1,1,180) do (for /f %%a in ('powershell -NoProfile -Command "(Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory" 2^>nul') do echo [%%i] Free: %%a KB >> "%RESULTS_DIR%\monitor-detailed.log") & timeout /t 2 /nobreak >nul 2>&1" + +:: CPU monitor (approximate via tasklist) +start /b cmd /c "for /l %%i in (1,1,180) do (for /f "skip=2 tokens=5" %%c in ('tasklist /FI "IMAGENAME eq rfcp-server.exe" /FO LIST 2^>nul ^| findstr "Mem"') do echo [%%i] RFCP Mem: %%c >> "%RESULTS_DIR%\monitor-rfcp.log") & timeout /t 2 /nobreak >nul 2>&1" + +for /f %%a in ('powershell -NoProfile -Command "(Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory"') do set /a START_FREE=%%a/1024 + +set START_DETAIL=%time% +echo Start time: %START_DETAIL% + +curl -s -w "\nTime: %%{time_total}s | HTTP: %%{http_code}" ^ + -X POST %API%/api/coverage/calculate ^ + -H "Content-Type: application/json" ^ + -d "{\"sites\": [{\"lat\": 50.45, \"lon\": 30.52, \"height\": 30, \"power\": 43, \"gain\": 15, \"frequency\": 1800}], \"settings\": {\"radius\": 5000, \"resolution\": 300, \"preset\": \"detailed\"}}" ^ + -o "%RESULTS_DIR%\coverage-detailed.json" ^ + 2>&1 + +set END_DETAIL=%time% +echo End time: %END_DETAIL% + +for /f %%a in ('powershell -NoProfile -Command "(Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory"') do set /a END_FREE=%%a/1024 +set /a MEM_USED=START_FREE-END_FREE +set /a PEAK_FROM_BASELINE=BASELINE_FREE_MB-END_FREE + +echo. +echo Memory delta: %MEM_USED% MB (peak from baseline: %PEAK_FROM_BASELINE% MB) +echo Start: %START_DETAIL% >> "%LOG_FILE%" +echo End: %END_DETAIL% >> "%LOG_FILE%" +echo Memory delta: %MEM_USED% MB >> "%LOG_FILE%" + +:: Check result +if exist "%RESULTS_DIR%\coverage-detailed.json" ( + findstr /C:"timeout" "%RESULTS_DIR%\coverage-detailed.json" >nul 2>&1 + if !ERRORLEVEL! EQU 0 ( + echo RESULT: TIMEOUT - Vectorization didn't help enough + echo RESULT: TIMEOUT >> "%LOG_FILE%" + ) else ( + findstr /C:"points" "%RESULTS_DIR%\coverage-detailed.json" >nul 2>&1 + if !ERRORLEVEL! EQU 0 ( + echo RESULT: SUCCESS - Calculation completed! + echo RESULT: SUCCESS >> "%LOG_FILE%" + + :: Extract point count + for /f "tokens=2 delims=:" %%a in ('findstr /C:"count" "%RESULTS_DIR%\coverage-detailed.json"') do ( + echo Points calculated: %%a + echo Points: %%a >> "%LOG_FILE%" + ) + ) else ( + echo RESULT: ERROR - Check JSON file + echo RESULT: ERROR >> "%LOG_FILE%" + ) + ) +) + +:: =========================================== +:: POST-TEST CLEANUP CHECK +:: =========================================== +echo. +echo [CLEANUP] Checking post-test state... +echo === POST-TEST CLEANUP === >> "%LOG_FILE%" + +timeout /t 3 /nobreak >nul + +:: Count RFCP processes +for /f %%a in ('tasklist /FI "IMAGENAME eq rfcp-server.exe" 2^>nul ^| find /c "rfcp-server"') do set RFCP_COUNT=%%a +echo RFCP processes after test: %RFCP_COUNT% +echo RFCP processes after: %RFCP_COUNT% >> "%LOG_FILE%" + +:: Memory recovery +for /f %%a in ('powershell -NoProfile -Command "(Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory"') do set /a FINAL_FREE=%%a/1024 +set /a MEM_NOT_FREED=BASELINE_FREE_MB-FINAL_FREE + +echo Free RAM now: %FINAL_FREE% MB (baseline was: %BASELINE_FREE_MB% MB) +echo Memory not freed: %MEM_NOT_FREED% MB +echo Final free RAM: %FINAL_FREE% MB >> "%LOG_FILE%" +echo Memory not freed: %MEM_NOT_FREED% MB >> "%LOG_FILE%" + +if %MEM_NOT_FREED% GTR 500 ( + echo WARNING: Possible memory leak - %MEM_NOT_FREED% MB not freed! + echo WARNING: Memory leak detected >> "%LOG_FILE%" +) + +if %RFCP_COUNT% GTR 1 ( + echo WARNING: Multiple RFCP processes still running! + echo WARNING: Multiple processes >> "%LOG_FILE%" +) + +:: =========================================== +:: SUMMARY +:: =========================================== +echo. +echo ============================================ +echo TEST SUMMARY +echo ============================================ +echo. +echo Results saved to: %RESULTS_DIR% +echo Log file: %LOG_FILE% +echo. +echo Files created: +echo - coverage-fast.json +echo - coverage-standard.json +echo - coverage-detailed.json +echo - monitor-standard.log (memory during standard) +echo - monitor-detailed.log (memory during detailed) +echo - monitor-rfcp.log (rfcp process memory) +echo. + +echo === SUMMARY === >> "%LOG_FILE%" +echo Test completed: %date% %time% >> "%LOG_FILE%" + +echo ============================================ +pause diff --git a/installer/test-detailed-quick.bat b/installer/test-detailed-quick.bat new file mode 100644 index 0000000..9a6b976 --- /dev/null +++ b/installer/test-detailed-quick.bat @@ -0,0 +1,128 @@ +@echo off +title RFCP - Detailed Preset Quick Test +setlocal EnableDelayedExpansion + +echo ============================================ +echo RFCP - Detailed Preset Quick Test +echo ============================================ +echo. +echo This tests ONLY the Detailed preset to check +echo if NumPy vectorization is working. +echo. +echo Expected: ^< 90 seconds (was 300s timeout) +echo ============================================ +echo. + +set API=http://127.0.0.1:8888 + +:: Check if server is running +echo [1/4] Checking server... +curl -s -o nul -w "HTTP %%{http_code}" %API%/api/health >nul 2>&1 +if %ERRORLEVEL% NEQ 0 ( + echo ERROR: Server not responding! Start rfcp-debug.bat first. + pause + exit /b 1 +) +echo Server OK +echo. + +:: Get baseline +echo [2/4] Capturing baseline... +for /f %%a in ('powershell -NoProfile -Command "(Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory"') do set /a BASE_FREE=%%a/1024 +for /f %%a in ('tasklist /FI "IMAGENAME eq rfcp-server.exe" 2^>nul ^| find /c "rfcp-server"') do set BASE_PROCS=%%a +echo Free RAM: %BASE_FREE% MB +echo RFCP procs: %BASE_PROCS% +echo. + +:: Run test +echo [3/4] Running Detailed preset (5km, 300m)... +echo Start: %time% +echo. + +curl -s -w "\n HTTP: %%{http_code}\n Time: %%{time_total} seconds\n" ^ + -X POST %API%/api/coverage/calculate ^ + -H "Content-Type: application/json" ^ + -d "{\"sites\": [{\"lat\": 50.45, \"lon\": 30.52, \"height\": 30, \"power\": 43, \"gain\": 15, \"frequency\": 1800}], \"settings\": {\"radius\": 5000, \"resolution\": 300, \"preset\": \"detailed\"}}" ^ + -o detailed-result.json + +echo. +echo End: %time% +echo. + +:: Check result +echo [4/4] Analyzing result... + +:: Check for timeout +findstr /C:"timeout" detailed-result.json >nul 2>&1 +if %ERRORLEVEL% EQU 0 ( + echo. + echo ============================================ + echo RESULT: TIMEOUT + echo Vectorization needs more optimization. + echo ============================================ + echo. + type detailed-result.json + goto :cleanup +) + +:: Check for success (has "points") +findstr /C:"\"points\"" detailed-result.json >nul 2>&1 +if %ERRORLEVEL% EQU 0 ( + echo. + echo ============================================ + echo RESULT: SUCCESS! + echo Detailed preset completed without timeout! + echo ============================================ + echo. + + :: Extract stats + echo Extracting stats from result... + + :: Count points (rough) + for /f "tokens=2 delims=:," %%a in ('findstr /C:"\"count\"" detailed-result.json') do ( + echo Points calculated: %%a + ) + + :: Get computation time + for /f "tokens=2 delims=:," %%a in ('findstr /C:"\"computation_time\"" detailed-result.json') do ( + echo Computation time: %%a seconds + ) + + goto :cleanup +) + +:: Unknown result +echo. +echo RESULT: UNKNOWN +echo Check detailed-result.json manually +type detailed-result.json + +:cleanup +echo. +echo ============================================ +echo POST-TEST CLEANUP CHECK +echo ============================================ + +timeout /t 3 /nobreak >nul + +for /f %%a in ('powershell -NoProfile -Command "(Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory"') do set /a END_FREE=%%a/1024 +for /f %%a in ('tasklist /FI "IMAGENAME eq rfcp-server.exe" 2^>nul ^| find /c "rfcp-server"') do set END_PROCS=%%a + +set /a MEM_DIFF=BASE_FREE-END_FREE + +echo Free RAM: %END_FREE% MB (was %BASE_FREE% MB, diff: %MEM_DIFF% MB) +echo RFCP procs: %END_PROCS% (was %BASE_PROCS%) + +if %MEM_DIFF% GTR 500 ( + echo. + echo WARNING: Memory not fully released! +) + +if %END_PROCS% GTR %BASE_PROCS% ( + echo. + echo WARNING: Extra RFCP processes still running! +) + +echo. +echo ============================================ +pause