Technisch Artikel

Alcinoe Componentenbibliotheek en Delphi 11.1 Alexandria Compatibiliteit

Alcinoe is een open-source componentenbibliotheek voor Delphi en C++Builder, onderhouden op GitHub door Zeus64. Het bestrijkt gebieden die de VCL en FireMonkey RTL aan derde partijen overlaten: een GPU-versnelde videospeler, een WebRTC-wrapper, native iOS en Android bewerkingsbesturingselementen, een dual-mode JSON/BSON parser, een MongoDB-client met connection pooling, een ImageMagick-wrapper en een verzameling FireMonkey-besturingselementen die de standaard renderingpijplijn volledig omzeilen. De bibliotheek heeft haar reputatie opgebouwd op Rio (10.3.3) en Sydney (10.4.2), en heeft sindsdien elke Embarcadero-release gevolgd. Op het moment van schrijven is het volledig compatibel met Delphi 11.1 Alexandria en Delphi Athens 12.3

Alcinoe aan een project toevoegen

De installatie splitst zich op één vraag: heeft u ontwerptijdondersteuning nodig voor de visuele componenten van Alcinoe? Zo niet, sla dan het BPL volledig over. Voeg {alcinoe_rootdir}\source toe aan het bibliotheekzoekpad van het project en u bent klaar. Elk niet-visueel component, inclusief de parsers, databaseclients en stringhulpprogramma's, wordt vanuit de broncode gecompileerd zonder iets te registreren

Als u wel ontwerptijdondersteuning nodig heeft, is het proces iets langer. Open Component > Install Packages in de Delphi IDE, blader naar de BPL die overeenkomt met uw versie (bijvoorbeeld {alcinoe_rootdir}\lib\bpl\alcinoe\Win32\alexandria\Alcinoe_alexandria.bpl), installeer het en voeg dan nog steeds {alcinoe_rootdir}\source toe aan het zoekpad. De BPL registreert de componenten; de bronmap is wat de compiler vindt wanneer het uw project compileert

Alcinoe levert optionele patches voor de Embarcadero RTL-broncode. Als u deze wilt, navigeer dan naar {alcinoe_rootdir}\embarcadero\, kies de submap voor uw versie en voer update.bat uit. Het script verwacht GIT in het PATH en gaat uit van een standaard Embarcadero installatielocatie. Het haalt de originele RTL-broncode op en past de patches toe. Zodra dit is voltooid, voegt u die gepatchte bronmap toe aan uw projectzoekpad zodat de compiler deze oppikt vóór de alleen-lezen kopie in de Embarcadero installatiestructuur. Niets hiervan is vereist om aan de slag te gaan; het is alleen van belang als u bugs tegenkomt die door de patches worden aangepakt

Android en de D8 desugaring proxy

Verschillende Alcinoe componenten (WebRTC, door ExoPlayer ondersteunde video) zijn afhankelijk van Java-bibliotheken die Java 8-taalfuncties gebruiken. De Android-toolchain die bij oudere Delphi-versies wordt geleverd, gebruikt dx.bat voor DEX-conversie, wat die bytecodes niet kan verwerken op API-niveaus lager dan 26. De oplossing is desugaring, wat D8 automatisch afhandelt wanneer het direct wordt aangeroepen. Alcinoe biedt een proxyscript op {alcinoe_rootdir}\tools\D8Proxy\dx.bat dat aanroepen van het Delphi-bouwsysteem doorstuurt naar D8, waardoor desugaring transparant wordt. Vervang de originele dx.bat in uw Android SDK build-tools map (meestal C:\SDKs\android\build-tools\30.0.3\) door deze proxy. Embarcadero hield het onderliggende probleem bij via RSP-24155; latere versies van de SDK-tools hebben het direct aangepakt, dus controleer of uw huidige toolchain de tijdelijke oplossing nog nodig heeft

Het FireMonkey renderingprobleem en het antwoord van Alcinoe

De standaard verfcyclus van FireMonkey wordt een knelpunt in UI's met veel scrollen. Een enkele TRectangle met afgeronde hoeken kan ongeveer 3 ms in beslag nemen om opnieuw te tekenen, omdat de standaard implementatie het pad bij elk frame opnieuw berekent. Met 20 van dergelijke componenten zichtbaar, loopt dat op tot 60 ms per frame-doorloop, wat de effectieve framerate ver onder de drempel voor vloeiend scrollen beperkt

Alcinoe pakt dit aan met een GPU-residente buffer per component. De eerste tekening rendert de component naar een TTexture opgeslagen in GPU-geheugen. Latere hertrekkingen 'blitten' die textuur in plaats van het tekenalgoritme opnieuw uit te voeren. Het gemeten resultaat op dezelfde afgeronde rechthoek daalt van ongeveer 3 ms naar ongeveer 0,1 ms. Naast het bufferen vervangt Alcinoe OpenGL pad-tekenen voor basisvormen door native Android en iOS teken-API's, waardoor de kwaliteit/prestatie afweging verbonden aan Form.Quality wordt omzeild. De relevante componenten zijn TALRectangle, TALCircle en een reeks verbeterde lay-outcontainers waaronder een ScrollBox en TabControl

TALJsonDocument: DOM en SAX in één type

TALJsonDocument is Alcinoe's JSON en BSON parser. Het ondersteunt twee navigatiemodi. De DOM-modus bouwt een in-memory objectboom, wat willekeurige toegang geeft tot elk knooppunt ten koste van geheugen dat proportioneel is aan de documentgrootte. De SAX-modus vuurt gebeurtenissen af terwijl de parser elk token leest zonder een boom te behouden, wat de juiste keuze is wanneer u een groot document moet filteren en slechts een handvol waarden hoeft vast te houden. DOM-parsers in Delphi (DBXJSON, SuperObject en de anderen) zijn typisch drie tot vijf keer langzamer dan een SAX-benadering voor dezelfde inhoud, omdat elke knooppunttoewijzing objectcreatie-overhead met zich meebrengt bovenop het daadwerkelijke parseerwerk

Het type volgt hetzelfde knooppuntnavigatiepatroon als TALXMLDocument. Een minimale DOM-lezing ziet er als volgt uit:

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);

Wijs voor de SAX-modus een anonieme procedure toe aan OnParseText voordat u LoadFromJSON aanroept met het tweede argument ingesteld op True. De callback ontvangt het knooppuntpad, de naam, de waarde en een TALJSONNodeSubType dat het JSON-type identificeert (string, integer, float, boolean enzovoort). Die modus produceert geen heaptoewijzingen voor knooppunten, dus schaalt het naar willekeurig grote documenten zonder het geheugenbudget te overschrijden

TALJsonDocument leest en schrijft BSON ook native; geef True door als de BSON-vlag aan LoadFromFile of SaveToFile. Een tweede variant, TALJsonDocumentU, gebruikt intern UnicodeString (UTF-16) in plaats van AnsiString (UTF-8) voor contexten waarbij de omringende code volledig in Unicode werkt

MongoDB client en connection pooling

Alcinoe's MongoDB-driver bestrijkt de gebruikelijke query-bewerkingen en handelt connection pooling native af. De eenvoudige client, TAlMongoDBClient, opent en sluit een enkele verbinding per bewerking. De gepoolde variant, TAlMongoDBConnectionPoolClient, onderhoudt een set actieve verbindingen en geeft er een aan elke aanroepende thread vanuit de pool, en neemt deze weer terug wanneer de aanroep is voltooid. Dat model voorkomt dat meerdere threads elkaar blokkeren bij het opzetten van verbindingen, wat van belang is wanneer achtergrondwerkers tegelijkertijd dezelfde database bevragen. Voor tailable cursors op gecapte collecties observeert TAlMongoDBTailMonitoringThread nieuwe documenten en vuurt een callback af wanneer ze aankomen, wat het standaardpatroon is voor logstreaming of wijzigingsnotificaties zonder te pollen

Andere componenten die het weten waard zijn

ALVideoPlayer rendert video naar een TTexture in plaats van een overlayvenster, zodat andere FireMonkey componenten erboven kunnen worden geplaatst in Z-volgorde. De Android backend gebruikt ExoPlayer, wat DASH, HLS en SmoothStreaming ondersteuning toevoegt bovenop wat de ingebouwde MediaPlayer van Android aankan. De iOS backend gebruikt AVPlayer met gelijkwaardige HLS-ondersteuning

TALWebRTC verpakt de WebRTC-stack voor peer-to-peer audio en video. Er is geen browser of plug-in voor nodig, en de verbinding gaat door NAT via de standaard ICE/STUN/TURN onderhandeling die de onderliggende bibliotheek afhandelt

TALStringList vervangt de op AnsiCompareText gebaseerde sortering van TStringList door een locale-onafhankelijke ordinale vergelijking en een quicksort die tot 10x sneller is op grote lijsten. De gehashte variant, TALHashedStringList, voegt een interne hashtabel toe voor O(1) opzoeken ten koste van een iets hogere overhead op kleine lijsten. Let op dat TALStringList een 8-bit AnsiString-lijst is, geen Unicode-lijst; het past goed in server-side code waar UTF-8 de werkende codering is en ruwe doorvoer belangrijker is dan locale-bewuste vergelijking

Op 64-bit Windows gaat de FastCode-erfenis die veel van Alcinoe's stringroutines hun snelheidsvoordeel gaf (meestal handgeschreven x86-assembly) niet mee. De Win64 builds vallen terug op de Pascal implementaties, die aanzienlijk langzamer draaien op string-intensieve workloads. Het demo\ALStringBenchMark project stelt u in staat de kloof op uw hardware te meten voordat u zich vastlegt op een 64-bit build waarbij stringdoorvoer een knelpunt is

De volledige broncode staat op github.com/Zeus64/alcinoe