Berkeley DB med Perl: json_encode / json_decode vs att dela upp platt men stor grafstrukturer till ett index för varje båge

2015-10-07

Jag representerar typiskt data jag lägger i BDB (flera BDB-inlägg hittas i taggen) som JSON därför att det nästan alltid är en graf-liknande struktur som slås upp från en nyckel av flera koncept. Grafer är mycket funktionellt att koda till JSON för att få som sträng i platt BDB (det BDB alternativ vettigt använda och tror jag normalt snabbare än att göra det via XML med stöd nere i BDB-stödjande bibliotek). Det JSON stöd jag använder (mycket kompetent bibliotek som klarar av all JSON som jag minns det oavsett vad jag skapat eller från nätet) finns diskuterat sist


Det håller tycker jag god prestanda för kodning båda riktningarna även för lite komplexa grafer föga platta.


Emellertid oavsett en helt plattstruktur märkte jag en fantastiskt svag prestation när antalet noder direkt under ett första lager börjar växa lite. Någonstans ovanför 7000 - 12000 märks det lätt medan när vi passerat en bit till att det ska behöva ha många sekunder på sig för att gå upp till på min dator flera månader när vi är på flera hundra tusen (de värsta exemplen var föga förvånande location och person: Av de jag lade märke till men de hör helt säkert till de tio största och kan troligt vara också de två största).


I kontrast som jag läste det här för mina databaser med similarity värden mellan en uppslagsnoden och ett antal för-beräknade värden för samtliga nycklar genom att lagra varje förberäknad relation med index-nyckel enligt:


concept_similarity_beräknas_från_som_utgångspunkt_perspektiv concept_similarity_beräknas_till alg_configuration_rörande_vikter_för_uttryck_likhet_och_skillnad prioritet_likhet_eller_olikhet_eller_samlat_standardmått

Istället för att som innan slöa ner en algoritm för att beräkna något annat som gick igenom samtliga relationer similarity fanns beräknat för via flera förfrågningar per relation med någon sekund emellan verkar nu anropen över åtminstone flera hundra tusen upp till kanske 1 miljon (innan jag gick till internet-datorn eftersom ännu inga fel hade rapporterats på de ny-byggda BDB när test-koden jämför slumpmässiga värden från text-filer med själva datat använt) inte mer än kanske 10 - 20 s (vi kan tänka oss en extra 30 s så jag är trygg i att jag inte bedömde det fel eftersom det var en sådan kontrast: Men jag tror nog 10 - 20 s är vad jag hade det i):


  • Intern hårddisk.
  • Kopierade till den med en stor mängd fritt utrymme nyligen formaterad men ej kopierade i sekventiell ordning under min direkta kontroll utan katalogen med BDB-filerna via Nautilus. Samt därefter enstaka kompletterande en del saknat första QA-kontrollen upptäckte (koncept i perspektiv börjande på ex. "a" och ett blanksteg eller annan bokstav innan: En liten miss för att minna om att man bäst testar databaser man bygger upp).
  • En databas minst för resp. bokstav och ibland fler. Jag har förr alltid gjort så därför att det tog så lång tid annars att bygga dem. Men läser man instruktioner, manualer m.m. noggrant tänker jag eller som jag surfade runt på frågor och svar runt det kan man lära som jag senare kom att göra att om man ställer in parametriseringen rätt så slipper man att BDB-stödet sitter och expanderar ut filen på slöaste tänkbara sätt för nära nog varje nytt koncept när man är över en viss storlek (en storlek man ställer in när den ska göra sådant och ex. kan dra upp till att täcka några tio tals miljoner nycklar eller vad man har minne och egen förändrad Linux till att orka med).
  • Föregående har jag fått för mig när man bygger en stor fil ej ger någon förlust i prestanda. Emellertid eftersom jag nu i versionen innan hade just en stor fil valde jag att istället göra tvärtom.
  • Filsystem XFS.
  • Linux ändrat - resp. en del små-saker runt i XFS-lagret - till att ej försöka göra något smart i hur skrivningar hanteras.
  • Viss uppföljning och skattning av vad jag tror / fått för mig är hårddisk-nära komprimering av något slag (förr användes run-length-kodning vilket jag kan tänka mig att det är nu också men har ej försökt bedöma det: Endast beräknat entropin över det) för att se att det konvergerar i rätt riktning när en del annat material kopierats in.
  • Sortering där det är prestanda-gynnsamt rörande nycklar i access såväl självklart när databaserna byggs.
  • Självklart ingenting på hårddisken som Linux resp. Perl-biblioteken har att göra med.

Men kanske kan man få god prestanda också med SQL, XML eller något sådant? Dock betvivlar jag på en dator med min hårdvara varande en fyra år nu.


Hade prestandan varit kvar som innan vilket jag tror är inte mycket bättre än vad en typisk SQL-databas eller NOSQL lösning (NOSQL rörande påkostade lösningar med allt färdigt i logik snarare än man som jag gör med BDB - argumenterat också en NOSQL givetvis - behöver göra det själv: Ej för många andra tillämpningar en rättvis jämförelse) av dom vanligaste ger hade det jag gjorde med dom när problemet uppträdde aldrig under min livstid blivit klart. Nu är det när testningen är klar inte vad som kommer ta mer än maximalt en timme.


Tiny och JSON

Json-stöd jag använder:



JSON-stödet antar jag har någon form av teoretiskt och i kanske i kod-mängd elegant liten rekursiv eller non-state-medveten algoritm för att vandra i graf-minnesstrukturerna (hasch-tabellerna som ju går att göra som godtyckliga träd i Perl) görande det väldigt svårt att hantera defekter i strukturen eller själva logiken där med annat än exceptions (utan en massa extra kod görande kod-elegansen "gömd"). Annars föredrar jag ju själv viss medvetenhet i logiken därför att jag för att klara prestanda regelmässigt undviker allt konceptuellt ens i närheten av rekursion eller tillståndslösa "algoritmer konvergernade lösning via enkla principer" som därför också får värdet av mycket exakt information om var felet uppstår i strukturerna (görande det möjligt som typiskt för fel JSON om det skulle inträffa motsvarande vad jag kan få i stora grafstrukturer: Genom att en liten defekt i en liten subgraf kan skäras bort utan just någon förlust alls). Men i JSON-kodningen är det verkligen inte på den exaktheten information ges. Det är fel och koden klagar via exceptions och jag kan inte föreställa mig att något där som man inte bör ha märkt redan innan kontrollerande parametrarna föregripande anrop går att få ut om vad som egentligen är fel.


En del exceptions (flera) tycks när jag läser dokumentationen vara vad som "hjälper" folk att missbruka Perls notation och flexibilitet till att skriva ganska sunkig kod med en massa sammanblandningar av "pekare", "implicita typ-konverteringar" m.m. Jag skriver Perl så att man kan konvertera det nära nog 1 till 1 till C och om jag någonsin behövt skriva Bless någon gång eller låtit kod göra det implicit kommer jag ej ihåg det. Många andra har en annan förväntan av vilka värden de vill få ut av Perl och gillar detta. Jag använder Perl mer därför att det har en svårslagen mängd färdigt stöd som samlats genom alla år fritt tillgängligt inte minst inom text mining, natural language processing, statistik m.m.


"If $enable is true (or missing), then the encode method will not barf when it encounters a blessed reference. Instead, the value of the convert_blessed option will decide whether null (convert_blessed disabled or no TO_JSON method found) or a representation of the object (convert_blessed enabled and TO_JSON method found) is being encoded. Has no effect on decode.

If $enable is false (the default), then encode will throw an exception when it encounters a blessed object."

JSON stödet kan jag inte minnas att jag någonsin haft problem att få att koda mina grafer som hasch-tabeller eller att den haft problem att göra grafer av JSON jag tagit ner från databaser eller webb-servrar på internet. När de är korrekta (och en hel del strukturer egentligen inkorrekta vet jag att den klarar av att koda som vettigt förväntat). Tämligen stabil med andra ord. "Perl-anpassad-Perl-kod" kan vi kanske kalla det med den positiva bieffekten att sunking JSON-strukturer på internet med alla möjliga underligheter också blir vettiga :-)


Vilket stöd exceptions jag använder minns jag ej namnet på (jag tror det ligger i Tiny) och hittade ingenting självklart direkt på CPAN. Jag hanterar inte själv fel med exceptions så jag är föga engagerad annat än för att fånga dem bäddande in en del externa moduler av och till.