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
- Tabellerna virtualiserar rader och kolumner: bara den synliga delen ritas.
- Flera grafvyer behåller geometrin på GPU:n och uppdaterar främst kameran under interaktion.
- Det finns gemensamma komponentkontrakt, separat tillståndshantering och omfattande testinfrastruktur.
- Tunga komponenter som dokument-, video- och 3D-modellvisning är valbara beroenden.
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:
- Grid:
column_sum(), rad 703; summaradens rendering, rad 1166;draw_total(), rad 1551.
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:
- Behåll sorteringsresultatet mellan filterändringar.
- Minska strängallokeringarna i sökningen.
- Kör stora sökningar i bakgrunden med avbrytning eller generationskontroll så att inaktuella resultat inte ersätter nyare resultat.
- Undvik dubbla indexvektorer om samma information kan representeras enklare.
Kod:
- Grid:
rebuild_order(), rad 655;Msg::SetFilter, rad 772. - Datamodell:
cell_raw(), rad 235. - Sortering:
sorted_order(), rad 99.
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:
- Grid-konstruktorer:
from_record_batch()ochfrom_record_batch_arc(), från rad 397. - Arrow-adapter:
grid_data_from_batch()ochcolumn_from_array().
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:
- Gridens prestandatest, särskilt
building_the_window_is_o_visible_not_o_total(), rad 39.
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:
- Flow-renderaren, ritkommandon från rad 280.
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
- Rätta korrekthetsproblemen och lägg till regressionstester.
- Cacha summeringen.
- Optimera filtreringen och återanvänd sorteringsresultat.
- Mät minnesåtgång, kompletta bildrutor och användarinteraktioner.
- Prioritera därefter större ändringar i Arrow-lagring och GPU-rendering utifrån mätresultaten.
Omfattning och begränsningar
- Inga projektfiler ändrades under analysen.
- Full testsvit och nya GPU-mätningar ingick inte.
- Kodfynd om onödigt arbete är verifierade, men deras faktiska tids- och minneskostnad behöver mätas.
- De citerade FPS-resultaten är projektets tidigare dokumenterade mätningar för specifika konfigurationer.