Tablourile de bord C2 moderne nu mai randează câteva sute de piste. Ele randează zeci de mii. Imagini aeriene din rețele radar federate, fluxuri maritime AIS, telemetrie de roiuri de drone, pinguri GPS ale unităților terestre și piste multi-senzor fuzionate ajung toate pe același ecran al operatorului. O imagine operațională comună funcțională în 2026 depășește în mod curent 100.000 de piste simultane. Stratul de vizualizare fie menține 60fps sub această sarcină, fie operatorul își pierde încrederea în sistem.
Acest articol este un ghid tehnic despre cum să mențineți bugetele de cadre corecte la această scară. Acoperim instanțierea WebGL, procesarea în lot a primitivelor Cesium, compoziția straturilor deck.gl, strategia LOD, bugetele de memorie GPU, aritmetica de sincronizare a cadrelor și harness-ul de testare necesar pentru a prinde regresiile înainte de operator.
Realitatea cu 100.000 de Piste
Regula veche — „un ecran tactic trebuie să gestioneze câteva mii de piste" — era corectă în 2010 și periculos de greșită în 2026. Fluxurile de fuziune multi-senzor NATO, rețelele radar la altitudine joasă și agregatorii comerciali ADS-B/AIS produc în mod curent sute de mii de piste în timpul exercițiilor și operațiunilor active. Doctrina de roiuri de drone singură poate plasa 200–500 de emițători prietenoși într-o zonă de 50 km.
Decalajul de performanță contează deoarece încrederea operatorului se prăbușește sub 30fps. Odată ce panoramarea bâlbâie sau simbolurile rămân în urmă față de actualizarea pistei, operatorul nu mai are încredere în nimic altceva de pe ecran — și începe să verifice încrucișat imaginea față de o hartă pe hârtie sau un ecran secundar. Acel timp de verificare încrucișată este exact latența operațională pe care sistemul C2 a fost construit să o elimine. Un tablou de bord C2 care scade sub 60fps sub sarcina realistă nu este un tablou de bord C2 lent. Este unul defect.
Ținta este fixă: 60fps susținut, cu 100.000+ piste, pe o stație de lucru tipică de nivel mediu (CPU cu 8 nuclee, dGPU de nivel mediu, 1440p). Atingerea acelei ținte necesită ca fiecare strat al stivei — geometrie, apeluri de desenare, memorie GPU, ingestia rețelei, mutarea stării — să respecte bugetul de cadre de 16,67ms.
Instanțierea WebGL
Prima pârghie este apelul de desenare. Emiterea a 100.000 de desene individuale pe cadru este imposibilă la 60fps pe orice GPU actual; overhead-ul driverului de pe partea CPU singur consumă întregul buget. Randarea instanțiată comprimă mii de simboluri într-un singur apel de desenare. O geometrie (mesh-ul simbolului), un shader și un buffer de atribute per-instanță care transportă poziția, direcția, apartenența și ID-ul simbolului.
Modelul standard folosește ANGLE_instanced_arrays în WebGL 1 sau drawArraysInstanced nativ în WebGL 2. Atributele per-instanță sunt transmise dintr-un buffer compact: de obicei 32 de octeți per pistă (vec3 poziție, vec2 viteză, uint32 flaguri compactate). La 100k piste, acesta reprezintă 3,2 MB de date de atribut vertex — suficient de mic pentru a re-încărca în fiecare cadru dacă este necesar, deși actualizările parțiale prin bufferSubData sunt mai ieftine.
Three.js expune instanțierea prin InstancedMesh; deck.gl o gestionează nativ pentru aproape fiecare strat; API-ul Primitive al Cesium o suportă prin tablouri GeometryInstance. Cele trei framework-uri se încadrează pe același spectru — Three.js oferă cea mai mare libertate și cea mai mică matematică geospațială inclusă, deck.gl este calea cea mai rapidă spre un strat de înaltă densitate funcțional, Cesium oferă semantici de glob 3D și ocluzie de teren pe care celelalte două nu le au.
Procesarea în Lot a Primitivelor Cesium
API-ul Entity al Cesium este instrumentul greșit pentru mai mult de 5.000 de piste. Entitățile alocă obiecte JavaScript per-pistă, rulează o buclă de actualizare pe partea CPU și reconstruiesc geometria la modificările proprietăților. Costul este amortizat bine la număr mic și catastrofal la număr mare.
Pentru randarea la scară de 100k, coborâți la API-ul Primitive. O PointPrimitiveCollection randează până la ~1M de puncte într-un singur apel de desenare. O BillboardCollection gestionează zeci de mii de sprite-uri cu textură de pictogramă cu un atlas de textură partajat. Modelul GeometryInstance grupează mii de geometrii statice (ex. inele de rază, geolocalizări) într-o singură primitivă procesată în lot la momentul creării.
Randarea etichetelor este asimetrică. O PointPrimitiveCollection de 100k randează fără efort; adăugarea a 100k etichete deasupra strică bugetul de cadre instantaneu. Etichetele trec prin calea de text SDF a Cesium, care costă atât memorie pentru atlasul de glife, cât și un desen separat procesat în lot. Soluția este vizibilitatea etichetelor condusă de LOD: randați etichete doar pentru pistele în raza spațiului de ecran dependent de zoom față de cursor sau pentru pistele marcate „de interes" de motorul de fuziune. Un ecran tipic de operator nu necesită mai mult de 50–200 de etichete vizibile simultan.
Straturile deck.gl pentru Apărare
deck.gl se află deasupra unei hărți de bază MapboxGL sau MapLibre și vă oferă o stivă de straturi compozabile concepute exact pentru această problemă. Straturile relevante pentru un ecran C2:
ScatterplotLayer. Calul de bătaie pentru pozițiile brute ale pistelor. Randează milioane de puncte la 60fps deoarece fiecare atribut (poziție, culoare, rază) este legat de GPU. Folosiți-l pentru punctele de pistă nesimbolizate, inelele de acoperire a senzorilor și straturile plate de înaltă densitate.
IconLayer. Randează simboluri MIL-STD-2525 dintr-un atlas de textură. Performanța scalează cu dimensiunea atlasului; împachetați simbolurile 2525 într-un singur atlas de 4096×4096 cu toate variantele de apartenența/eșalon pre-rasterizate. La 100k pictograme cu un singur atlas partajat, IconLayer menține 60fps confortabil pe hardware de nivel mediu.
PathLayer. Pentru istoricele pistelor și cursurile proiectate. Costul scalează cu numărul de vârfuri, nu cu numărul de căi — preferați decimarea istoricelor lungi (Douglas-Peucker, cu epsilon legat de nivelul de zoom) față de eliminarea căilor.
Straturi de agregare GPU. ScreenGridLayer, HexagonLayer și HeatmapLayer agregă milioane de puncte în vizualizări sumate pe bin-uri pe GPU. Utile ca suprapuneri de densitate la zoom îndepărtat — la zoom redus nu doriți să vedeți 100k simboluri, ci gradientul densității amenințărilor.
Strategia de Nivel-de-Detaliu (LOD)
Cea mai eficientă optimizare de performanță este să nu randezi ceea ce operatorul nu poate vedea în mod semnificativ. La un nivel de zoom de 2000 km lățime, un ecran cu 100k piste nu poate rezolva simboluri individuale — fiecare pixel al ecranului acoperă mai multe piste. Randarea simbologiei MIL-STD-2525 complete la acel zoom este timp GPU irosit și produce o imagine necitibilă.
Scara LOD: la zoom îndepărtat, randați densitatea agregată (heatmap sau strat hex pe GPU); la zoom mediu, randați puncte nesimbolizate colorate după apartenența; la zoom apropiat, randați simboluri 2525 complete cu etichete pentru pistele marcate; la zoom maxim, randați simboluri complete cu etichete, traiectorii istorice și cursuri proiectate pentru fiecare pistă vizibilă.
Gruparea în spațiul ecranului este complementul. Chiar și la zoom apropiat, grupurile dense (o parcare de vehicule, un port plin de nave) produc simboluri suprapuse care se ascund unele pe altele. O trecere de grupare k-d tree sau grid-bin (rulată pe firul worker, nu pe firul principal) comprimă simbolurile suprapuse într-un singur insigna „N piste aici" până când operatorul mărește.
Profilul de utilizare justifică LOD agresiv: un operator mărește o dată la 30–60 de secunde și petrece cea mai mare parte a timpului scanând imaginea largă. Optimizarea bugetului de cadre al imaginii largi se plătește continuu; optimizarea bugetului de cadre la zoom apropiat se plătește doar în momentele de interes activ.
Bugete de Memorie GPU
Presiunea memoriei este ucigașul tăcut al ecranelor de înaltă densitate. Numărul de piste vizibile este doar o parte din buget. Atlasele de textură (foaia de simboluri, dalele de teren, dalele raster de hartă de bază), bufferele de vârfuri (atribute per-instanță, căi istorice), bufferele uniforme, atașamentele framebuffer și compozitorul propriu al browserului trag cu toții din același pool.
Bugetele din lumea reală cu care planificăm: un GPU integrat de 4 GB (Intel Iris Xe, AMD Radeon 780M) pe un laptop implementat are aproximativ 2–2,5 GB utilizabili pentru contextul WebGL după ce OS-ul, browserul și alte file își iau cota. Un GPU discret de 16 GB (clasa RTX 4070/5070) are 12+ GB utilizabili. Multe implementări conservative headless — centre de operațiuni cu stații de lucru întărite achiziționate cu ani în urmă — rulează în continuare hardware de clasă iGPU. Proiectarea pentru anvelopa iGPU este implicit-ul mai sigur.
Cifre practice pentru un tablou de bord C2 cu 100k piste: buffere de atribute per-instanță ~5–10 MB; atlas simboluri ~64 MB (4096² RGBA); cache raster hartă de bază ~200–400 MB; cache dale teren ~300–600 MB; geometrie cale istorică ~20–50 MB în funcție de retenție. Total ~600 MB–1,2 GB. Aceasta se încadrează în anvelopa iGPU cu marjă, dar numai dacă fiecare strat este disciplinat cu privire la dimensiunile texturii și creșterea bufferului.
Latența și Sincronizarea Cadrelor
Bugetul de cadre de 16,67ms se împarte aproximativ astfel: 2–3ms pentru gestionarea intrărilor și mutarea stării, 4–6ms pentru actualizarea stratului (pe partea CPU, în principal recomputarea bufferului de atribute și eliminarea), 6–8ms pentru randarea GPU, 1–2ms pentru overhead-ul compositor. Orice lucru care consumă mai mult decât porția sa fură din porția următoare și produce un cadru eliminat.
Cele mai grave spike-uri se ascund în locuri ușor de trecut cu vederea. Îmbinările de corelație a pistelor pe firul principal — rularea pasului de corelație al motorului de fuziune în linie cu randarea — produc blocări de 50–200ms de fiecare dată când sosește un nou lot de senzori. Soluția este să rulați corelația pe un fir worker și să postați delta-urile imuabile ale pistelor pe firul principal. Rafale de actualizări trimise de server (un websocket care descarcă 5.000 de actualizări de piste într-un singur tic) saturează bucla de evenimente JS; limitați rata și procesați delta-urile în lot la câte o actualizare tamponată pe cadru.
Colectarea de gunoi este a treia sursă de spike-uri. Alocarea de obiecte noi per pistă per cadru produce pauze GC în formă de ferăstrău la câteva secunde. Folosiți pool-uri de tablouri tipizate și reutilizați bufferele; evitați crearea de literale de obiecte per-cadru în căile fierbinți. Așteptarea 60fps-sau-nimic este reală, și o singură pauză GC de 100ms la fiecare 10 secunde este exact tipul de intermitență care distruge încrederea operatorului.
Testarea la Scară
Nu puteți livra un ecran cu 100k piste fără un harness de testare care generează și redă sarcini la acea scară. Trei componente: un generator sintetic de piste, o suită automatizată de regresie FPS și o sursă de adevăr prin redare înregistrată.
Generatorul sintetic produce scenarii deterministe cu 100k piste — distribuții aleatoare, grupuri dense, formațiuni de roiuri de drone, scenarii de raid în masă — fiecare semat astfel încât o rulare CI reproduce același scenariu de fiecare dată. Fiecare scenariu conduce un browser headless printr-o cale de cameră scriptată (panoramare, mărire, micșorare, eliminare aglomerație, filtrare) în timp ce harness-ul eșantionează histograme delta performance.now() și raportează timpii de cadru p50/p95/p99.
Suita de regresie FPS rulează la fiecare PR. Pragurile sunt explicite: timp de cadru p95 sub 18ms, p99 sub 25ms, niciun cadru eliminat care depășește 50ms pe o rulare scriptată de 60 de secunde. Orice commit care împinge numerele peste prag blochează fuziunea. Aceasta este singura modalitate de a prinde regresiile de tipul moarte prin o mie de tăieturi, unde fiecare schimbare individuală costă 0,2ms.
Redarea înregistrată de senzori din lumea reală este sursa de adevăr. Sarcinile sintetice prind clifele de performanță, dar ratează distribuțiile asimetrice ale datelor reale — grupurile, golurile, modelele de rafale. O înregistrare de tip pcap a unui flux de exercițiu live, redată la viteza ceasului de perete față de tabloul de bord, este cel mai aproape de sarcina operațională fără un operator pe scaun. Combinați harness-ul sintetic cu două sau trei scene înregistrate din exercițiile de verificare și aveți o rețea de regresie care rezistă.