Alcinoe je biblioteka komponenti otvorenog koda za Delphi i C++Builder, koju na GitHubu održava Zeus64. Pokriva područje koje VCL i FireMonkey RTL prepuštaju trećim stranama: video player s GPU ubrzanjem, WebRTC omotač (wrapper), nativne iOS i Android kontrole za uređivanje, JSON/BSON parser s dva načina rada, MongoDB klijent sa združivanjem veza (connection pooling), ImageMagick omotač i kolekciju FireMonkey kontrola koje u potpunosti zaobilaze standardni proces iscrtavanja. Biblioteka je izgradila svoju reputaciju na verzijama Rio (10.3.3) i Sydney (10.4.2), a od tada prati svako izdanje Embarcadera. U trenutku pisanja, u potpunosti je kompatibilna s Delphi 11.1 Alexandria i Delphi Athens 12.3
Uključivanje Alcinoe-a u projekt
Instalacija ovisi o jednom pitanju: trebate li podršku tijekom dizajniranja za Alcinoe-ove vizualne kontrole? Ako ne, u potpunosti preskočite BPL. Dodajte {alcinoe_rootdir}\source na putanju pretraživanja biblioteke projekta (library search path) i gotovi ste. Svaka ne-vizualna komponenta, uključujući parsere, klijente baza podataka i pomoćne funkcije za nizove znakova (stringove), kompajlira se iz izvornog koda bez registracije ičega
Kada vam je potrebna podrška tijekom dizajniranja, put je malo duži. Otvorite Component > Install Packages u Delphi IDE-u, potražite BPL koji odgovara vašoj verziji (na primjer {alcinoe_rootdir}\lib\bpl\alcinoe\Win32\alexandria\Alcinoe_alexandria.bpl), instalirajte ga, a zatim ipak dodajte {alcinoe_rootdir}\source na putanju pretraživanja (search path). BPL registrira komponente; izvorni direktorij je ono što kompajler pronalazi kada kompajlira vaš projekt
Alcinoe isporučuje neobavezne zakrpe (patches) za Embarcadero RTL izvorne kodove. Ako ih želite, idite do {alcinoe_rootdir}\embarcadero\, odaberite poddirektorij za vašu verziju i pokrenite update.bat. Skripta očekuje GIT u PATH-u i pretpostavlja zadanu lokaciju instalacije Embarcadera. Preuzima originalni RTL izvorni kod i primjenjuje zakrpe. Kad završite, dodajte taj zakrpani izvorni direktorij na putanju pretraživanja vašeg projekta kako bi ga kompajler preuzeo ispred kopije samo za čitanje (read-only) u instalacijskom stablu Embarcadera. Ništa od ovoga nije potrebno za početak; važno je samo ako naiđete na greške (bugove) koje zakrpe rješavaju
Android i D8 proxy za uklanjanje sintaktičkog šećera (desugaring proxy)
Nekoliko Alcinoe komponenti (WebRTC, video podržan ExoPlayerom) ovisi o Java bibliotekama koje koriste značajke jezika Java 8. Skup alata (toolchain) za Android koji se isporučuje sa starijim verzijama Delphija koristi dx.bat za konverziju DEX-a, koji ne može obraditi te bajtkodove na API razinama ispod 26. Rješenje je uklanjanje sintaktičkog šećera (desugaring), s kojim D8 automatski rukuje kada se pozove izravno. Alcinoe nudi proxy skriptu na adresi {alcinoe_rootdir}\tools\D8Proxy\dx.bat koja prosljeđuje pozive iz Delphi sustava za izgradnju (build system) prema D8, čineći uklanjanje sintaktičkog šećera transparentnim. Zamijenite originalni dx.bat u vašem Android SDK direktoriju alata za izgradnju (obično C:\SDKs\android\build-tools\30.0.3\) s ovim proxyjem. Embarcadero je pratio temeljni problem u RSP-24155; novije verzije SDK alata izravno su ga riješile, stoga provjerite treba li vašem trenutnom skupu alata i dalje ovo zaobilazno rješenje (workaround)
Problem renderiranja FireMonkey-a i Alcinoeov odgovor
Zadani ciklus iscrtavanja (paint cycle) FireMonkeyja postaje usko grlo u korisničkim sučeljima s puno pomicanja (scroll-heavy). Jedan TRectangle sa zaobljenim kutovima može potrajati oko 3 ms za ponovno iscrtavanje (repaint) jer standardna implementacija ponovno izračunava putanju u svakom okviru (frame). S 20 takvih vidljivih kontrola to iznosi 60 ms po prolazu okvira, što ograničava efektivnu brzinu prikaza okvira (frame rate) znatno ispod praga za fluidno pomicanje
Alcinoe to rješava pomoću GPU-rezidentnog međuspremnika (buffer) po kontroli. Prvo iscrtavanje renderira kontrolu na TTexture pohranjenu u GPU memoriji. Naknadna ponovna iscrtavanja kopiraju (blit) tu teksturu umjesto ponovnog izvođenja algoritma za iscrtavanje. Izmjereni rezultat na istom zaobljenom pravokutniku pada s oko 3 ms na oko 0,1 ms. Izvan samog spremanja u međuspremnik, Alcinoe zamjenjuje OpenGL crtanje putanja za osnovne oblike s nativnim Android i iOS API-jima za crtanje, zaobilazeći kompromis (trade-off) kvalitete/performansi povezan s Form.Quality. Relevantne kontrole su TALRectangle, TALCircle i skup poboljšanih spremnika za izgled (layout containers) uključujući ScrollBox i TabControl
TALJsonDocument: DOM i SAX u jednom tipu
TALJsonDocument je Alcinoe-ov JSON i BSON parser. Podržava dva načina prelaska (traversal modes). DOM način rada gradi stablo objekata u memoriji, dajući nasumični pristup (random access) svakom čvoru po cijenu memorije proporcionalne veličini dokumenta. SAX način rada okida događaje kako parser čita svaki token (token) bez zadržavanja ikakvog stabla, što je pravi izbor kada trebate filtrirati veliki dokument i zadržati samo šačicu vrijednosti. DOM parseri u Delphiju (DBXJSON, SuperObject i drugi) obično su tri do pet puta sporiji od SAX pristupa za isti sadržaj, jer svaka alokacija čvora nosi operativne troškove stvaranja objekta (object-creation overhead) povrh samog parsiranja
Ovaj tip slijedi isti obrazac navigacije čvorovima kao TALXMLDocument. Minimalno čitanje DOM-a izgleda ovako:
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);
Za SAX način rada dodijelite anonimnu proceduru (anonymous procedure) OnParseText prije pozivanja LoadFromJSON s drugim argumentom postavljenim na True. Povratni poziv (callback) prima putanju čvora, naziv, vrijednost i TALJSONNodeSubType koji identificira vrstu JSON-a (string, integer, float, boolean, i tako dalje). Taj način rada ne proizvodi alokacije gomile (heap allocations) za čvorove, tako da se skalira do proizvoljno velikih dokumenata bez probijanja proračuna memorije
TALJsonDocument također čita i zapisuje BSON u izvornom formatu; proslijedite True kao BSON zastavicu u LoadFromFile ili SaveToFile. Druga varijanta, TALJsonDocumentU, interno koristi UnicodeString (UTF-16) umjesto AnsiString (UTF-8) za kontekste gdje okolni kod cijelo vrijeme radi u Unicodeu
MongoDB klijent i združivanje veza (connection pooling)
Alcinoe-ov MongoDB upravljački program (driver) pokriva uobičajene operacije upita i izvorno upravlja združivanjem veza. Jednostavni klijent, TAlMongoDBClient, otvara i zatvara jednu vezu po operaciji. Združena varijanta, TAlMongoDBConnectionPoolClient, održava skup aktivnih veza i po jednu predaje svakoj pozivnoj niti (calling thread) iz baze/spremišta (pool), vraćajući je kad se poziv dovrši. Taj model sprječava da višestruke niti blokiraju jedna drugu pri postavljanju veze, što je bitno kad god radnici u pozadini istovremeno postavljaju upite u istu bazu podataka. Za kursore koji se mogu pratiti (tailable cursors) u ograničenim zbirkama (capped collections), TAlMongoDBTailMonitoringThread nadzire nove dokumente i aktivira povratni poziv (callback) kada oni stignu, što je standardni obrazac za strujanje dnevnika (log streaming) ili obavještavanje o promjenama bez prozivanja (polling)
Ostale komponente koje vrijedi poznavati
ALVideoPlayer renderira video na TTexture umjesto na preklopnom prozoru (overlay window), tako da druge FireMonkey kontrole mogu sjediti iznad njega u Z-redoslijedu. Pozadina sustava Android (Android backend) koristi ExoPlayer, koji dodaje podršku za DASH, HLS i SmoothStreaming povrh onoga što obrađuje ugrađeni MediaPlayer sustava Android. Pozadina sustava iOS koristi AVPlayer s ekvivalentnom podrškom za HLS
TALWebRTC omotava (wraps) WebRTC stog (stack) za ravnopravni audio i video (peer-to-peer). Ne zahtijeva preglednik ili dodatak (plugin), a veza prelazi NAT putem standardnog ICE/STUN/TURN pregovaranja s kojim se upravlja temeljna biblioteka
TALStringList zamjenjuje metodu sortiranja AnsiCompareText komponente TStringList usporedbom redoslijeda koja ne ovisi o lokalitetu te brzim sortiranjem (quicksort) koje je i do 10 puta brže na velikim popisima. Skraćena varijanta (hashed variant), TALHashedStringList, dodaje internu hash tablicu za O(1) pronalaženje po cijeni malo većih operativnih troškova na malim popisima. Imajte na umu da je TALStringList 8-bitni popis (list) AnsiString, a ne Unicode; dobro se uklapa u kod na strani poslužitelja (server-side code) gdje je UTF-8 radno kodiranje, a sirova propusnost (raw throughput) važnija je od usporedbe koja je svjesna lokaliteta (locale-aware comparison)
Na 64-bitnom sustavu Windows, FastCode nasljeđe koje je mnogim Alcinoeovim string rutinama dalo njihovu prednost u brzini (uglavnom ručno pisani asembler x86) ne prenosi se. Win64 verzije vraćaju se na Pascal implementacije, koje rade osjetno sporije pri radnim opterećenjima s velikom upotrebom stringova. Projekt demo\ALStringBenchMark omogućuje vam mjerenje jaza (gap) na vašem hardveru prije nego što se posvetite 64-bitnoj verziji gdje je propusnost niza (string throughput) usko grlo
Potpuni izvorni kod nalazi se na github.com/Zeus64/alcinoe