Alcinoe je open-source knižnica komponentov pre Delphi a C++Builder, ktorú na GitHub-e udržiava Zeus64. Pokrýva oblasti, ktoré VCL a FireMonkey RTL nechávajú na tretie strany: GPU-akcelerovaný video prehrávač, WebRTC wrapper, natívne editačné prvky pre iOS a Android, dvojrežimový JSON/BSON parser, MongoDB klient s poolingom pripojení, ImageMagick wrapper a kolekciu ovládacích prvkov FireMonkey, ktoré úplne obchádzajú štandardný vykresľovací reťazec. Knižnica si vybudovala reputáciu na verziách Rio (10.3.3) a Sydney (10.4.2) a odvtedy sleduje každé vydanie Embarcadero. V čase písania tohto článku je plne kompatibilná s Delphi 11.1 Alexandria a Delphi Athens 12.3.
Začlenenie Alcinoe do projektu
Inštalácia sa delí na základe jednej otázky: potrebujete podporu v čase návrhu (design-time) pre vizuálne komponenty Alcinoe? Ak nie, úplne vynechajte súbor BPL. Pridajte {alcinoe_rootdir}\source do vyhľadávacej cesty knižníc projektu a máte hotovo. Každý nevizuálny komponent, vrátane parserov, databázových klientov a reťazcových utilít, sa skompiluje zo zdroja bez nutnosti registrácie.
Keď podporu v čase návrhu potrebujete, postup je o niečo dlhší. V Delphi IDE otvorte Component > Install Packages, vyhľadajte súbor BPL zodpovedajúci vašej verzii (napríklad {alcinoe_rootdir}\lib\bpl\alcinoe\Win32\alexandria\Alcinoe_alexandria.bpl), nainštalujte ho a následne stále pridajte {alcinoe_rootdir}\source do vyhľadávacej cesty. BPL registruje komponenty; zdrojový adresár je to, čo kompilátor najde pri kompilácii vášho projektu.
Alcinoe dodáva voliteľné opravy (patche) pre zdrojové kódy Embarcadero RTL. Ak ich chcete použiť, prejdite do {alcinoe_rootdir}\embarcadero\, vyberte podadresár pre vašu verziu a spustite update.bat. Skript očakáva GIT v premennej PATH a predpokladá predvolené umiestnenie inštalácie Embarcadero. Stiahne pôvodný zdroj RTL a aplikuje záplaty. Po dokončení pridajte tento opravený zdrojový adresár do vyhľadávacej cesty vášho projektu, aby ho kompilátor uprednostnil pred kópiou iba na čítanie v inštalačnom strome Embarcadero. Nič z toho nie je potrebné pre začiatok; záleží na tom len vtedy, ak narazíte na chyby, ktoré tieto opravy riešia.
Android a proxy pre D8 desugaring
Niekoľko komponentov Alcinoe (WebRTC, video postavené na ExoPlayeri) závisí od knižníc Java, ktoré používajú funkcie jazyka Java 8. Toolchain pre Android dodávaný so staršími verziami Delphi používa na konverziu DEX súbor dx.bat, ktorý nedokáže spracovať tieto bajtkódy na úrovniach API nižších ako 26. Riešením je desugaring, ktorý D8 rieši automaticky, ak sa volá priamo. Alcinoe poskytuje proxy skript na {alcinoe_rootdir}\tools\D8Proxy\dx.bat, ktorý presmerováva volania zo zostavovacieho systému Delphi do D8, vďaka čomu je desugaring transparentný. Nahraďte pôvodný dx.bat vo vašom adresári build-tools v Android SDK (zvyčajne C:\SDKs\android\build-tools\30.0.3\) týmto proxy. Spoločnosť Embarcadero sledovala tento problém pod označením RSP-24155; neskoršie verzie nástrojov SDK ho vyriešili priamo, preto skontrolujte, či váš aktuálny toolchain tento workaround stále potrebuje.
Problém s vykresľovaním vo FireMonkey a odpoveď Alcinoe
Predvolený vykresľovací cyklus FireMonkey sa stáva úzkym hrdlom v používateľských rozhraniach s intenzívnym rolovaním. Prekreslenie jediného prvku TRectangle so zaoblenými rohmi môže trvať približne 3 ms, pretože štandardná implementácia prepočítava cestu pri každom snímku. Pri 20 viditeľných takýchto ovládacích prvkoch to predstavuje 60 ms na jeden priechod snímky, čo obmedzuje efektívnu snímkovú frekvenciu hlboko pod prah plynulého rolovania.
Alcinoe to rieši pomocou GPU-residentného vyrovnávacieho zásobníka (buffer) pre každý ovládací prvok. Prvé vykreslenie vykreslí prvok do TTexture uloženej v pamäti GPU. Následné prekreslenia prenášajú (blitujú) túto textúru namiesto opätovného spúšťania algoritmu vykresľovania. Nameraný výsledok pri rovnakom zaoblenom obdĺžniku klesol z približne 3 ms na zhruba 0.1 ms. Okrem bufferingu Alcinoe nahrádza kreslenie ciest v OpenGL pre základné tvary natívnymi vykresľovacími API pre Android a iOS, čím obchádza kompromis medzi kvalitou a výkonom spojený s Form.Quality. Príslušné ovládacie prvky sú TALRectangle, TALCircle, a sada vylepšených kontajnerov rozloženia vrátane ScrollBox a TabControl.
TALJsonDocument: DOM a SAX v jednom type
TALJsonDocument je parser JSON a BSON od Alcinoe. Podporuje dva režimy prechodu. Režim DOM vytvára strom objektov v pamäti, čo umožňuje náhodný prístup k ľubovoľnému uzlu za cenu spotreby pamäte úmernej veľkosti dokumentu. Režim SAX spúšťa udalosti, keď parser číta každý token, bez ukladania stromu, čo je správna voľba, ak potrebujete filtrovať veľký dokument a uchovať len niekoľko hodnôt. Parsery DOM v Delphi (DBXJSON, SuperObject a ďalšie) sú pre rovnaký obsah zvyčajne trikrát až päťkrát pomalšie ako prístup SAX, pretože každá alokácia uzla prináša réžiu spojenú s vytváraním objektov navyše k samotnej analýze.
Tento typ sleduje rovnaký vzor navigácie v uzloch ako TALXMLDocument. Minimálne čítanie DOM vyzerá takto:
MyJsonDoc.LoadFromJSON(AJsonStr, False {dom mode});
MyJsonDoc.ParseOptions := [poAllowComments];
// read scalar values
ShowMessage(MyJsonDoc.ChildNodes[‘name’].ChildNodes[‘first’].Text);
ShowMessage(IntToStr(MyJsonDoc.ChildNodes[‘_id’].Int32));
// iterate an array
for I := 0 to MyJsonDoc.ChildNodes[‘contribs’].ChildNodes.Count - 1 do
Writeln(MyJsonDoc.ChildNodes[‘contribs’].ChildNodes[I].Text);
Pre režim SAX priraďte anonymnú procedúru k OnParseText pred volaním LoadFromJSON s druhým argumentom nastaveným na True. Spätné volanie (callback) prijíma cestu k uzlu, názov, hodnotu a TALJSONNodeSubType, ktorý identifikuje typ JSON (string, integer, float, boolean atď.). Tento režim nevytvára žiadne alokácie na halde pre uzly, takže sa škáluje na ľubovoľne veľké dokumenty bez preťaženia pamäte.
TALJsonDocument tiež natívne číta a zapisuje BSON; odovzdajte hodnotu True ako príznak BSON do LoadFromFile alebo SaveToFile. Druhý variant, TALJsonDocumentU, používa interne UnicodeString (UTF-16) namiesto AnsiString (UTF-8) pre kontexty, kde okolitý kód pracuje kompletne v Unicode.
Klient MongoDB a connection pooling
MongoDB ovládač od Alcinoe pokrýva bežné dopytovacie operácie a natívne spracováva connection pooling. Jednoduchý klient, TAlMongoDBClient, otvára a zatvára jedno pripojenie na operáciu. Pooled variant, TAlMongoDBConnectionPoolClient, udržiava sadu aktívnych pripojení a poskytuje jedno každému volajúcemu vláknu z fondu, pričom ho vracia po dokončení volania. Tento model zabraňuje tomu, aby sa viacero vlákien navzájom blokovalo pri vytváraní pripojenia, čo je dôležité, keď background workery dopytujú rovnakú databázu súčasne. Pre tailable kurzory na capped kolekciách vlákno TAlMongoDBTailMonitoringThread sleduje nové dokumenty a spúšťa spätné volanie pri ich príchode, čo je štandardný vzor pre log streaming alebo notifikácie o zmenách bez dopytovania (polling).
Ďalšie komponenty, ktoré stojí za to poznať
ALVideoPlayer vykresľuje video do TTexture namiesto prekrývacieho okna (overlay window), takže ostatné ovládacie prvky FireMonkey môžu byť umiestnené nad ním v Z-poradí. Android backend používa ExoPlayer, ktorý pridáva podporu DASH, HLS a SmoothStreaming nad rámec toho, čo zvládne zabudovaný MediaPlayer v Androide. Backend pre iOS používa AVPlayer s ekvivalentnou podporou HLS.
TALWebRTC obaľuje WebRTC stack pre peer-to-peer audio a video. Nevyžaduje prehliadač ani zásuvný modul a pripojenie prechádza cez NAT prostredníctvom štandardnej ICE/STUN/TURN vyjednávacej procedúry, ktorú rieši podkladová knižnica.
TALStringList nahrádza triedenie založené na AnsiCompareText z TStringList ordinálnym porovnávaním nezávislým od národného prostredia a algoritmom quicksort, ktorý je až 10-krát rýchlejší na veľkých zoznamoch. Hashed variant, TALHashedStringList, pridáva internú hašovaciu tabuľku pre O(1) vyhľadávanie za cenu mierne vyššej réžie pri malých zoznamoch. Všimnite si, že TALStringList je 8-bitový zoznam typu AnsiString, nie Unicode. Dobre sa hodí pre kód na strane servera, kde je UTF-8 pracovným kódovaním a surová priepustnosť je dôležitejšia ako lokálne závislé porovnávanie.
Na 64-bitovom systéme Windows sa dedičstvo FastCode, ktoré poskytovalo mnohým reťazcovým rutinám v Alcinoe ich rýchlostnú výhodu (väčšinou ručne písaný x86 assembler), neprenáša. Zostavenia pre Win64 sa vracajú k implementáciám v Pascale, ktoré bežia výrazne pomalšie pri záťaži intenzívnej na reťazce. Projekt demo\ALStringBenchMark vám umožňuje zmerať tento rozdiel na vašom hardvéri predtým, ako sa rozhodnete pre 64-bitové zostavenie, kde je reťazcová priepustnosť úzkym hrdlom.
Úplný zdrojový kód je na adrese github.com/Zeus64/alcinoe.