Alcinoe er et open-source komponentbibliotek til Delphi og C++Builder, som vedligeholdes på GitHub af Zeus64. Det dækker områder, som VCL og FireMonkey RTL overlader til tredjepart: en GPU-accelereret videoafspiller, en WebRTC-wrapper, native iOS- og Android-redigeringskontroller, en dual-mode JSON/BSON-parser, en MongoDB-klient med connection pooling, en ImageMagick-wrapper og en samling af FireMonkey-kontroller, der helt omgår standard rendering-pipelinen. Biblioteket opbyggede sit omdømme på Rio (10.3.3) og Sydney (10.4.2) og har siden fulgt hver Embarcadero-udgivelse. I skrivende stund er det fuldt kompatibelt med Delphi 11.1 Alexandria og Delphi Athens 12.3
Få Alcinoe ind i et projekt
Installationen afhænger af ét spørgsmål: har du brug for design-time-understøttelse til Alcinoes visuelle kontroller? Hvis ikke, kan du springe BPL helt over. Tilføj {alcinoe_rootdir}\source til projektets bibliotekssøgesti, og du er færdig. Alle ikke-visuelle komponenter, herunder parsere, databaseklienter og strengværktøjer, kompileres fra kildekoden uden at registrere noget
Når du har brug for design-time-understøttelse, er processen lidt længere. Åbn Component > Install Packages i Delphi IDE, find den BPL, der matcher din version (for eksempel {alcinoe_rootdir}\lib\bpl\alcinoe\Win32\alexandria\Alcinoe_alexandria.bpl), installer den, og tilføj derefter stadig {alcinoe_rootdir}\source til søgestien. BPL'en registrerer komponenterne; kildebiblioteket er det, compileren finder, når den kompilerer dit projekt
Alcinoe leverer valgfrie rettelser (patches) til Embarcadero RTL-kilderne. Hvis du ønsker dem, skal du navigere til {alcinoe_rootdir}\embarcadero\, vælge underkataloget for din version og køre update.bat. Scriptet forventer, at GIT er i PATH, og antager en standard Embarcadero-installationsplacering. Det henter den originale RTL-kildekode og anvender rettelserne. Når du er færdig, skal du tilføje dette patchede kildebibliotek til dit projekts søgesti, så compileren vælger det frem for den skrivebeskyttede kopi i Embarcadero-installationstræet. Intet af dette er påkrævet for at komme i gang; det betyder kun noget, hvis du støder på fejl, som rettelserne adresserer
Android og D8-desugaring-proxyen
Flere Alcinoe-komponenter (WebRTC, ExoPlayer-baseret video) afhænger af Java-biblioteker, der bruger Java 8-sprogfunktioner. Android-værktøjskæden, der følger med ældre Delphi-versioner, bruger dx.bat til DEX-konvertering, som ikke kan håndtere disse bytecodes på API-niveauer under 26. Løsningen er desugaring, som D8 håndterer automatisk, når den aktiveres direkte. Alcinoe leverer et proxy-script i {alcinoe_rootdir}\tools\D8Proxy\dx.bat, der videresender kald fra Delphis build-system til D8, hvilket gør desugaring gennemsigtig. Udskift den originale dx.bat i din Android SDK-build-tools-mappe (typisk C:\SDKs\android\build-tools\30.0.3\) med denne proxy. Embarcadero sporede det underliggende problem i RSP-24155; nyere versioner af SDK-værktøjerne adresserede det direkte, så tjek om din nuværende værktøjskæde stadig har brug for denne omvej
FireMonkey-renderingproblemet og Alcinoes svar
FireMonkeys standard tegnecyklus (paint cycle) bliver en flaskehals i scroll-tunge brugergrænseflader. En enkelt TRectangle med afrundede hjørner kan tage omkring 3 ms at genoptegne, fordi standardimplementeringen genberegner stien (path) på hver frame. Med 20 sådanne kontroller synlige, løber det op i 60 ms pr. frame-pass, hvilket begrænser den effektive billedhastighed (frame rate) et godt stykke under tærsklen for flydende scrolling
Alcinoe løser dette med en GPU-residerende buffer pr. kontrol. Den første optegning rendererer kontrollen til en TTexture, der er gemt i GPU-hukommelsen. Efterfølgende genoptegninger kopierer (blit) denne tekstur i stedet for at genudføre tegnealgoritmen. Det målte resultat på det samme afrundede rektangel falder fra omkring 3 ms til omkring 0,1 ms. Ud over bufferingen erstatter Alcinoe OpenGL-stitegning for grundlæggende former med native Android- og iOS-tegne-API'er, hvilket omgår afvejningen mellem kvalitet og ydeevne, der er knyttet til Form.Quality. De relevante kontroller er TALRectangle, TALCircle og et sæt forbedrede layout-containere, herunder en ScrollBox og TabControl
TALJsonDocument: DOM og SAX i én type
TALJsonDocument er Alcinoes JSON- og BSON-parser. Den understøtter to gennemløbsmetoder (traversal modes). DOM-tilstand opbygger et in-memory objektræ, hvilket giver direkte adgang til enhver knude på bekostning af hukommelse proportional med dokumentstørrelsen. SAX-tilstand udløser begivenheder, efterhånden som parseren læser hver token, uden at beholde noget træ, hvilket er det rigtige valg, når du skal filtrere et stort dokument og kun gemme en håndfuld værdier. DOM-parsere i Delphi (DBXJSON, SuperObject og de andre) er typisk tre til fem gange langsommere end en SAX-tilgang til det samme indhold, fordi hver knudetildeling medfører en overhead for oprettelse af objekter oven i selve parseringsarbejdet
Typen følger samme knude-navigationsmønster som TALXMLDocument. En minimal DOM-læsning ser således ud:
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);
For SAX-tilstand skal du tildele en anonym procedure til OnParseText, før du kalder LoadFromJSON med det andet argument sat til True. Callbacket modtager knudestien, navn, værdi og en TALJSONNodeSubType, der identificerer JSON-typen (string, integer, float, boolean osv.). Denne tilstand producerer ingen heap-allokeringer for knuder, så den skalerer til vilkårligt store dokumenter uden at sprænge hukommelsesbudgettet
TALJsonDocument læser og skriver også BSON indbygget; angiv True som BSON-flag til LoadFromFile eller SaveToFile. En anden variant, TALJsonDocumentU, bruger UnicodeString (UTF-16) internt i stedet for AnsiString (UTF-8) til kontekster, hvor den omgivende kode udelukkende fungerer i Unicode
MongoDB-klient og connection pooling
Alcinoes MongoDB-driver dækker de almindelige forespørgselsoperationer og håndterer connection pooling indbygget. Den enkle klient, TAlMongoDBClient, åbner og lukker en enkelt forbindelse pr. operation. Variant med pooling, TAlMongoDBConnectionPoolClient, opretholder et sæt aktive forbindelser og giver en til hver kaldende tråd fra puljen, og returnerer den, når kaldet er fuldført. Denne model forhindrer flere tråde i at blokere hinanden under forbindelsesopsætning, hvilket er vigtigt, når baggrundsprocesser forespørger den samme database samtidigt. For tailable cursors på capped collections overvåger TAlMongoDBTailMonitoringThread efter nye dokumenter og udløser et callback, når de ankommer, hvilket er standardmønsteret for log-streaming eller ændringsmeddelelser uden polling
Andre komponenter der er værd at kende
ALVideoPlayer rendererer video til en TTexture i stedet for et overlay-vindue, så andre FireMonkey-kontroller kan sidde over det i Z-rækkefølge. Android-backend'en bruger ExoPlayer, hvilket tilføjer understøttelse af DASH, HLS og SmoothStreaming ud over, hvad Androids indbyggede MediaPlayer håndterer. iOS-backend'en bruger AVPlayer med tilsvarende HLS-understøttelse
TALWebRTC indpakker WebRTC-stakken til peer-to-peer lyd og video. Det kræver ikke en browser eller et plugin, og forbindelsen krydser NAT gennem den standard ICE/STUN/TURN-forhandling, som det underliggende bibliotek håndterer
TALStringList erstatter TStringLists AnsiCompareText-baserede sortering med en lokalitets-uafhængig ordinal sammenligning og en quicksort, der er op til 10 gange hurtigere på store lister. Den hashede variant, TALHashedStringList, tilføjer en intern hashtabel til O(1) opslag på bekostning af lidt højere overhead på små lister. Bemærk at TALStringList er en 8-bit AnsiString-liste, ikke en Unicode-liste; det passer godt i server-side kode, hvor UTF-8 er arbejdsindkodningen, og rå gennemløbshastighed betyder mere end lokalitetsbevidst sammenligning
På 64-bit Windows overføres FastCode-arven, der gav mange af Alcinoes strengrutiner deres hastighedsfordel (for det meste håndskrevet x86-assembly), ikke. Win64-builds falder tilbage på Pascal-implementeringerne, som kører mærkbart langsommere på strengintensive arbejdsbelastninger. Projektet demo\ALStringBenchMark lader dig måle afstanden på din hardware, før du forpligter dig til et 64-bit build, hvor strenggennemløbshastighed er en flaskehals
Hele kildekoden findes på github.com/Zeus64/alcinoe