Modernit C2-kojetaulut eivät enää renderöi satoja ratoja. Ne renderöivät kymmeniä tuhansia. Ilmakuvat federoiduista tutkaverkoista, AIS-merisyötteet, droonikehätelemetria, maajoukkoyksikköjen GPS-pingit ja fuusoidut monianturiradot saapuvat kaikki samalle operaattorinäytölle. Toimiva yhteinen operatiivinen kuva vuonna 2026 ylittää rutiininomaisesti 100 000 samanaikaista rataa. Visualisointikerros joko pitää 60fps-nopeuden tällä kuormituksella tai operaattori menettää luottamuksensa järjestelmään.
Tämä artikkeli on tekninen läpikäynti siitä, miten kehysbudjetit pidetään kurissa tässä mittakaavassa. Käymme läpi WebGL-instanssoinnin, Cesium-primitiivien eräajon, deck.gl-kerroskoostumuksen, LOD-strategian, GPU-muistibudjetit, kehystahtilaskennan ja testiympäristön, jota tarvitaan regressioiden havaitsemiseen ennen kuin operaattori kohtaa ne.
100 000 radan todellisuus
Vanha nyrkkisääntГ¶ — "taktisen nГ¤ytГ¶n tГ¤ytyy kГ¤sitellГ¤ muutama tuhat rataa" — oli oikea vuonna 2010 ja vaarallisen väärГ¤ vuonna 2026. NATO:n monianturifuusiasyГ¶tteet, matalakorkeusВtutkaverkot ja kaupalliset ADS-B/AIS-koostajat tuottavat rutiininomaisesti kuusinumeroisia ratamääriГ¤ harjoitusten ja aktiivisten operaatioiden aikana. DroonikehГ¤oppi yksinään voi sijoittaa 200–500 omaa lГ¤hetintГ¤ 50 km:n alueelle.
Suorituskykyero on merkittävä, koska operaattorin luottamus romahtaa alle 30fps:ssä. Kun panorointi pätkii tai symbologia viivästyy pohjana olevasta radan päivityksestä, operaattori epäilee kaikkea muuta näytöllä — ja alkaa ristiintarkistaa kuvaa paperikarttaa tai toissijaista näyttöä vasten. Tämä ristiintarkistusaika on juuri se operatiivinen viive, jonka C2-järjestelmä rakennettiin poistamaan. C2-kojetaulu, joka tippuu alle 60fps:n realistisella kuormituksella, ei ole hidas C2-kojetaulu. Se on rikki.
Tavoite on kiinteГ¤: 60fps jatkuvasti, 100 000+ radalla, tyypillisellГ¤ keskitasoisella operaatiotyГ¶asemalla (8-ytiminen CPU, keskitason erillinen GPU, 1440p). TГ¤hГ¤n tavoitteeseen pääseminen edellyttää, ettГ¤ jokainen pinon kerros — geometria, piirtokutsut, GPU-muisti, verkon nielu, tilantilaВmuutokset — kunnioittaa 16,67ms:n kehysbudjettia.
WebGL-instanssointi
Ensimmäinen vipuvarsi on piirtokutsu. 100 000 yksittäisen piirron antaminen kehystä kohti on mahdotonta 60fps:llä millään nykyisellä GPU:lla; CPU-puolen ajurin yleisrasite yksinään kuluttaa koko budjetin. Instanssoitu renderöinti romahduttaa tuhannet symbolit yhdeksi piirtokutsuksi. Yksi geometria (symboliverkko), yksi varjostin ja instanssikohtainen attribuuttipuskuri, joka kuljettaa sijainnin, suunnan, yhteenliittymän ja symbolin tunnuksen.
Vakiokuvio käyttää ANGLE_instanced_arrays-laajennusta WebGL 1:ssä tai natiivia drawArraysInstanced-funktiota WebGL 2:ssa. Instanssikohtaiset attribuutit virtaavat tiiviisti pakatusta puskurista: tyypillisesti 32 tavua rataa kohti (vec3-sijainti, vec2-nopeus, uint32-pakatut liput). 100k radalla se on 3,2 MB vertex-attribuuttidataa — riittävän pieni ladataan uudelleen joka kehys tarvittaessa, vaikka osittaiset päivitykset bufferSubData-kutsulla ovatkin halvempia.
Three.js paljastaa instanssoinnin InstancedMesh-luokan kautta; deck.gl käsittelee sen natiivisti lähes jokaiselle kerrokselle; Cesiumin Primitive-API tukee sitä GeometryInstance-taulukoiden kautta. Kolme kehystä asettuvat samalle spektrille — Three.js antaa eniten vapautta ja vähiten valmista geospatiaalista matematiikkaa, deck.gl on nopein reitti toimivaan korkeatiheyksiseen kerrokseen, Cesium tarjoaa 3D-maapallo-semantiikan ja maaston peittämisen, joita muilla kahdella ei ole.
Cesium-primitiivien eräajo
Cesiumin Entity-API on väärä työkalu yli 5 000 radalle. Entiteetit varaavat ratakohtaisia JavaScript-objekteja, suorittavat CPU-puolen päivityssilmukan ja rakentavat geometrian uudelleen ominaisuusmuutosten yhteydessä. Kustannus on kohtuullinen pienillä määrillä ja katastrofaalinen suurilla.
100k-mittakaavan renderöinnissä siirrytään Primitive-APIin. PointPrimitiveCollection renderöi jopa noin 1M pistettä yhdellä piirtokutsulla. BillboardCollection käsittelee kymmeniä tuhansia ikon-teksturoituja sprite-kuvia jaetun tekstuuriatlaksen avulla. GeometryInstance-kuvio ryhmittelee tuhansia staattisia geometrioita (esim. kantamarengot, geoaidat) yhdeksi erätoimitetuksi primitiiviksi luomishetkellä.
Nimiketunnisteiden renderöinti on epäsymmetrinen. 100k PointPrimitiveCollection renderöityy vaivattomasti; 100k nimiketunnisteen lisääminen päälle rikkoo kehysbudjetin välittömästi. Nimiketunnisteet kulkevat Cesiumin SDF-tekstitien kautta, mikä maksaa sekä glyfi-atlasmuistin että erillisen eräpiirron. Ratkaisu on LOD-ohjattu nimiketunnisteiden näkyvyys: renderöi nimiketunnisteet vain kursoria lähimmälle zoomitasosta riippuvalle näyttötila-säteelle tai fuusiomoottorin "kiinnostava"-merkinnän saaneille radoille. Tyypillinen operaattorinäyttö tarvitsee enintään 50–200 näkyvää nimiketunnistetta kerrallaan.
deck.gl-kerrokset puolustukseen
deck.gl istuu MapboxGL- tai MapLibre-pohjakartan päällä ja tarjoaa koostettavan kerrosstackin, joka on suunniteltu juuri tähän ongelmaan. Relevantit kerrokset C2-näytölle:
ScatterplotLayer. Työhevonen raakoja ratasijainneja varten. Renderöi miljoonia pisteitä 60fps:llä, koska jokainen attribuutti (sijainti, väri, säde) on GPU-sidottu. Käytä symboloimattomille ratapisteille, anturin kattavuusrenkaista ja korkeatiheyksisille tasaisille kerroksille.
IconLayer. Renderöi MIL-STD-2525-symboleja tekstuuriatlaksesta. Suorituskyky skaalautuu atlaksen koon mukaan; pakkaa 2525-symbologia yhdeksi 4096×4096-atlakseksi, jossa kaikki yhteenliittymä-/osastotason variantit on esirasteröity. 100k ikonilla yhdellä jaetulla atlaksella IconLayer pitää 60fps:n mukavasti keskitasoisella laitteistolla.
PathLayer. Ratahistorioille ja projisoiduille kursseille. Kustannus skaalautuu kärkipistemäärän, ei polkumäärän mukaan — suosi pitkien historioiden harventamista (Douglas-Peucker, epsilon sidottuna zoomitasoon) mieluummin kuin polkujen pudottamista.
GPU-aggregointikerrokset. ScreenGridLayer, HexagonLayer ja HeatmapLayer kokoavat miljoonia pisteitä bin-summattuihin visualisointeihin GPU:lla. Hyödyllisiä zoomauskattavuuden tiheyspeitteenä — matalalla zoomilla et halua nähdä 100k symbolia, vaan uhkatiheyden gradientin.
Yksityiskohtasuuden taso (LOD) -strategia
Tehokkain suorituskykyoptimointi on olla renderöimättä sitä, mitä operaattori ei voi merkityksellisesti nähdä. 2 000 km levyisellä zoomitasolla 100k-radan näyttö ei pysty erottamaan yksittäisiä symboleita — jokainen näyttöpiksel kattaa useita ratoja. Täyden MIL-STD-2525-symbologian renderöinti tällä zoomilla on hukkaan heitettyä GPU-aikaa ja tuottaa lukukelvottoman kuvan.
LOD-portaikko: kaukaisella zoomilla renderöi koostettu tiheys (GPU-binattu lämpökartta tai heksagonaalinen kerros); keskizoomilla renderöi symboloimattomat pisteet väritettynä yhteenliittymän mukaan; lähizoomilla renderöi täysi 2525-symbologia nimiketunnisteilla merkityille radoille; maksimizoomilla renderöi täysi symbologia nimiketunnisteilla, historiapolkuineen ja projisoituine kursseineen jokaiselle näkyvälle radalle.
Näyttötila-klusterointi on täydentävä tekijä. Jopa lähizoomilla tiheät klusterit (autojen pysäköintialue, satama täynnä laivoja) tuottavat päällekkäisiä symboleita, jotka peittävät toisensa. k-d-puu- tai ruudukkobin-klusterointiläpikäynti (ajetaan työläissäikeessä, ei pääsäikeessä) romahduttaa päällekkäiset symbolit yhdeksi "N rataa tässä" -merkkipaikaksi, kunnes operaattori zoomaa sisään.
Käyttöprofiili oikeuttaa aggressiivisen LOD:n: operaattori zoomaa sisään kerran 30–60 sekunnissa ja viettää suurimman osan ajastaan skannaten laajaa kuvaa. Laajan kuvan kehysbudjetin optimointi maksaa jatkuvasti; lähizoomibudjetin optimointi maksaa vain aktiivisen kiinnostuksen hetkillä.
GPU-muistibudjetit
Muistipaine on korkeatiheyksisten näyttöjen hiljainen tappaja. Näkyvä ratamäärä on vain osa budjetista. Tekstuuriatlakset (symbolilehti, maastolaatat, pohjakartan rasterilaattat), verteksipuskurit (instanssikohtaiset attribuutit, historiapolut), yhtenäiset puskurit, kehyspuskuriliitteet ja selaimen oma koostin ammentavat kaikki samasta poolista.
Todellisuuden budjetit, joihin suunnittelemme: 4 GB integroitu GPU (Intel Iris Xe, AMD Radeon 780M) käyttöön sijoitetussa kannettavassa on noin 2–2,5 GB käytettävissä WebGL-kontekstille sen jälkeen, kun käyttöjärjestelmä, selain ja muut välilehdet ottavat osuutensa. 16 GB erillisellä GPU:lla (RTX 4070/5070-luokka) on 12+ GB käytettävissä. Monet konservatiiviset sijoitukset — operaatiokeskukset vuosia sitten hankituilla kovennetuilla työasemilla — toimivat edelleen iGPU-luokan laitteistolla. Suunnittelu iGPU-kirjekuoreen on turvallisempi oletusarvo.
Käytännön luvut 100k-radan C2-kojetaululle: instanssikohtaiset attribuuttipuskurit ~5–10 MB; symboli-atlas ~64 MB (4096² RGBA); pohjakartan rasterivälimuisti ~200–400 MB; maastolaatoitusvälimuisti ~300–600 MB; historiapolkugeometria ~20–50 MB säilytyksestä riippuen. Yhteensä ~600 MB–1,2 GB. Tämä mahtuu iGPU-kirjekuoreen marginaalilla, mutta vain jos jokainen kerros on kurinalainen tekstuurikokojen ja puskurikasvun suhteen.
Viive ja kehystahti
16,67ms:n kehysbudjetti jakautuu suunnilleen: 2–3ms syötteen käsittelyyn ja tilamuutoksiin, 4–6ms kerrosten päivitykseen (CPU-puoli, pääasiassa attribuuttipuskurien uudelleenlaskenta ja poistaminen), 6–8ms GPU-renderöintiin, 1–2ms koostimen yleisrasitteeseen. Mikä tahansa, joka kuluttaa enemmän kuin oman osansa, varastaa seuraavasta osasta ja tuottaa pudotetun kehyksen.
Pahimmat piikit piilevät paikoissa, jotka on helppo jättää huomiotta. Ratakorrelointiyhteenliittymät pääsäikeessä — fuusiomoottorin korrelaatioläpikäynnin ajaminen renderöinnin yhteydessä — tuottavat 50–200ms:n pysähdyksiä aina kun uusi anturierä saapuu. Ratkaisu on ajaa korrelaatio työläissäikeessä ja postata muuttumattomat ratamuutokset pääsäikeeseen. Palvelimen työntämät päivityspurskeet (websocket, joka dumpaa 5 000 radan päivitykset yhdessä tikissä) kyllästävät JS-tapahtumasilmukan; nopeusrajoita ja erää deltat yhteen puskuroituun päivitykseen kehystä kohti.
Roskienkeruu on kolmas piikkien lähde. Uusien objektien allokointi rataa kohti kehystä kohti tuottaa sahanteräisiä GC-taukoja muutaman sekunnin välein. Käytä tyypitettyjen taulukoiden pooleja ja käytä puskureita uudelleen; vältä kehyskohtaista objektiliteraalin luomista kuumissa poluissa. 60fps-tai-rikki-odotus on todellinen, ja yksittäinen 100ms:n GC-tauko 10 sekunnin välein on juuri sellainen nykiminen, joka tuhoaa operaattorin luottamuksen.
Testaus mittakaavassa
Et voi toimittaa 100k-radan näyttöä ilman testiympäristöä, joka tuottaa ja toistaa kuormitukset tässä mittakaavassa. Kolme komponenttia: synteettinen radan generaattori, automatisoitu FPS-regressiopaketti ja tallennettu toisto-totuuslähde.
Synteettinen generaattori tuottaa deterministisiä 100k-radan skenaarioita — satunnaisjakaumat, tiheät klusterit, droonikehämuodostelmat, massiiviset ryöstöilmahyökkäysskenaariot — kukin siemennetty niin, että CI-ajo toistaa saman kohtauksen joka kerta. Jokainen skenaario ajaa pääteettömän selaimen skriptatun kamerapolun läpi (panoroi, zoomaa sisään, zoomaa ulos, selkeytä, suodata) samalla kun ympäristö ottaa näytteitä performance.now()-delta-histogrammeista ja raportoi p50/p95/p99 kehysajat.
FPS-regressiopaketti ajetaan jokaisella PR:llä. Kynnykset ovat eksplisiittisiä: p95-kehysaika alle 18ms, p99 alle 25ms, ei 50ms:tä ylittäviä pudotettuja kehyksiä 60 sekunnin skriptatun ajon aikana. Mikä tahansa muutos, joka vie luvut kynnyksen ohi, estää yhdistämisen. Tämä on ainoa tapa havaita tuhannen leikkauksen kuolemaan johtavat regressiot, joissa jokainen yksittäinen muutos maksaa 0,2ms.
Todellinen tallennettu anturitoisto on totuuslähde. Synteettiset kuormitukset havaitsevat suorituskykyjyrkänteet, mutta jättävät huomaamatta todellisen datan epäsymmetriset jakaumat — klusterit, aukot, purskekuviot. Reaaliaikaisesta harjoitussyötteestä pcap-tyylillä otettu tallennus, toistettu seinäkellonopeudella kojetaulua vasten, on lähinnä mitä pääset operatiiviseen kuormitukseen ilman operaattoria tuolissa. Parista synteettistä ympäristöä kahdella tai kolmella vahvistusharjoituksista tallennetulla kohtauksella ja sinulla on regressioverkko, joka pitää.