Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/facett

facett-analys-2026-10-04.md

Analys av Facett

Datum: 2026-10-04
Granskad revision: 33f16430

Bedömning

Facett är tydligt optimerat på renderingssidan, men det finns konkreta förbättringar att göra i datahantering, minnesåtgång och tester. Grunden är bra, men vissa funktioner kan bli långsamma när datamängderna växer.

Det som redan är bra

Projektets befintliga mätningar visar omkring 60 FPS för flera grafvyer med 100 000 noder på angiven hårdvara. Detta är tidigare mätningar, inte nya resultat från denna granskning, och gäller de konfigurationer och arbetslaster som rapporterna anger.

Prioriterade förbättringar

1. Cacha tabellens summeringar

Prioritet: hög. Kodfynd verifierat; tidskostnaden har inte mätts i denna granskning.

När summaraden är påslagen går column_sum() igenom alla rader i den aktuella filtrerade radordningen. draw_total() anropar funktionen vid varje bildruta för respektive visad numerisk kolumn. Det innebär att arbetet växer med antalet filtrerade rader och visade numeriska kolumner, även om själva tabellkroppen bara ritar synliga celler. Stora tabeller förlorar därmed en viktig del av vinsten med virtualiseringen. Förslag: cacha summorna och uppdatera dem när data eller filter ändras. Säkerställ att redigering och inklistring också invaliderar relevanta summor.

Kod:

2. Undvik fullständig omräkning vid varje filterändring

Prioritet: hög. Kodfynd verifierat; faktisk användarlatens behöver mätas.

Msg::SetFilter anropar rebuild_order() synkront. Funktionen bygger först radordningen från sorteringsinställningen över samtliga källrader och filtrerar sedan resultatet. När sortering är aktiv görs alltså sorteringen om även om bara söktexten har ändrats.

Sökningen använder cell_raw(...).to_ascii_lowercase(), vilket skapar strängar och gemenkopior när cellerna undersöks. Filterresultatets radindex kopieras dessutom till filtered samtidigt som order behålls.

Förslag:

Kod:

3. Minska dubbel lagring vid Arrow-import

Prioritet: hög vid stora dataset. Kodfynd verifierat; minnesåtgången har inte profilerats.

Arrow-importen materialiserar kolumnerna till egna Rust-vektorer. Textvärden kopieras till separata strängar. Samtidigt behåller griden originalets RecordBatch genom delade Arrow-buffertar.

Att delningen av originalets buffertar och den typade kolumnkopieringen är zero-copy innebär därför inte att hela importen är zero-copy. De materialiserade kolumnerna tillkommer i minnet.

Förslag: läs direkt från typade Arrow-kolumner där det passar och lagra redigeringar separat. Mät särskilt texttunga tabeller och många kolumner innan representationen ändras.

Kod:

4. Mät kompletta användarinteraktioner

Prioritet: medel. Testlucka verifierad i det granskade prestandatestet.

Gridens prestandatest mäter framför allt beräkningen av vilka rader som är synliga. Det visar att fönsterberäkningen inte växer med hela datasetet, men styrker i sig inte ett generellt påstående om 60 FPS för kompletta bildrutor.

Testfilen kontrollerar också importtid och delning av Arrow-kolumner, men fångar inte exempelvis kostnaden för summering vid varje bildruta eller filterrespons under inmatning.

Förslag: mät hela bildrutor, scrollning och filterrespons med summor, textkolumner och realistiska datamängder. Följ minnesåtgång och långsamma bildrutor, inte enbart genomsnittlig FPS.

Källa:

5. Utvärdera synlighetsfiltrering och detaljnivå i Flow

Prioritet: medel för större grafer. Optimeringsmöjlighet; vinsten är inte uppmätt.

Flow-renderaren skickar samtliga kanter till GPU-renderingen med 96 vertexpositioner per kant varje bildruta. Att geometrin ligger kvar på GPU:n sparar uppladdningar, men eliminerar inte arbetet med att rita den.

Förslag: utvärdera synlighetsfiltrering och detaljnivå efter zoom. Mät vinsten på representativa stora grafer innan implementation väljs.

Källa:

Tre reproducerade korrekthetsproblem

De befintliga testerna i data.rs, sort.rs och arrow.rs kördes tillsammans med tre kompletterande gränsfall direkt mot projektets källfiler, i en separat testharness med befintliga kompilerade beroenden.

Resultat: 15 befintliga tester passerade och de tre kompletterande gränsfallen misslyckades. Detta är en riktad kontroll av tre moduler, inte resultatet för hela projektets testsvit.

Stora UInt64-värden ändras vid import

Arrow-adaptern begränsar UInt64 till i64::MAX. Därmed ändras datavärdet som används för visning och sortering.

Reproducerat exempel:

Indata:          18446744073709551615
Importerad text: 9223372036854775807

Förslag: bevara osignerade heltal i en egen kolumntyp eller annan förlustfri representation.

Källa: Arrow-konvertering, från rad 56.

Minsta i64-värdet får dubbla minustecken

group_int() negerar negativa värden, men absolutbeloppet av i64::MIN kan inte representeras som i64.

Reproducerat i optimerad körning:

Förväntat: -9,223,372,036,854,775,808
Faktiskt:  --9,223,372,036,854,775,808

Förslag: formatera absolutbeloppet som ett osignerat värde och hantera tecknet separat.

Källa: Talformatering, rad 127.

Nullvärden hamnar först vid fallande sortering

Kodens dokumenterade avsikt är att nullvärden alltid ska hamna sist. Den fallande sorteringen reverserar dock även nulljämförelsen.

Reproducerat exempel:

Indata:    [3, null, 1]
Förväntat: [3, 1, null]
Faktiskt:  [null, 3, 1]

Förslag: hantera nullplaceringen separat från riktningen för jämförelsen av vanliga värden.

Källa: Sortering, rad 108.

Rekommenderad arbetsordning

  1. Rätta korrekthetsproblemen och lägg till regressionstester.
  2. Cacha summeringen.
  3. Optimera filtreringen och återanvänd sorteringsresultat.
  4. Mät minnesåtgång, kompletta bildrutor och användarinteraktioner.
  5. Prioritera därefter större ändringar i Arrow-lagring och GPU-rendering utifrån mätresultaten.

Omfattning och begränsningar