Alcinoe är ett komponentbibliotek med öppen källkod för Delphi och C++Builder, som underhålls på GitHub av Zeus64. Det täcker områden som VCL och FireMonkey RTL överlåter till tredje part: en GPU-accelererad videospelare, en WebRTC-wrapper, inbyggda iOS- och Android-redigeringskontroller, en JSON/BSON-parser med dubbla lägen, en MongoDB-klient med anslutningspoolning, en ImageMagick-wrapper och en samling FireMonkey-kontroller som helt går förbi standardrenderingspipelinen. Biblioteket byggde sitt rykte på Rio (10.3.3) och Sydney (10.4.2), och har sedan dess följt varje Embarcadero-utgåva. I skrivande stund är det fullt kompatibelt med Delphi 11.1 Alexandria och Delphi Athens 12.3
Att få in Alcinoe i ett projekt
Installationen delas upp på en fråga: behöver du design-time-stöd för Alcinoes visuella kontroller? Om inte, hoppa över BPL helt och hållet. Lägg till {alcinoe_rootdir}\source i projektets bibliotekssökväg och du är klar. Varje icke-visuell komponent, inklusive parsers, databasklienter och strängverktyg, kompileras från källkod utan att registrera något
När du behöver design-time-stöd är vägen något längre. Öppna Component > Install Packages i Delphi IDE, bläddra till den BPL som matchar din version (till exempel {alcinoe_rootdir}\lib\bpl\alcinoe\Win32\alexandria\Alcinoe_alexandria.bpl), installera den och lägg sedan ändå till {alcinoe_rootdir}\source i sökvägen. BPL registrerar komponenterna; källkodskatalogen är vad kompilatorn hittar när den kompilerar ditt projekt
Alcinoe levereras med valfria korrigeringar (patches) för Embarcaderos RTL-källkoder. Om du vill ha dem navigerar du till {alcinoe_rootdir}\embarcadero\, väljer underkatalogen för din version och kör update.bat. Skriptet förväntar sig att GIT finns i PATH och antar en standardinstallationsplats för Embarcadero. Det hämtar den ursprungliga RTL-källkoden och tillämpar korrigeringarna. När du är klar lägger du till den korrigerade källkodskatalogen i ditt projekts sökväg så att kompilatorn väljer den före den skrivskyddade kopian i Embarcaderos installationsträd. Inget av detta krävs för att komma igång; det spelar bara roll om du stöter på buggar som korrigeringarna åtgärdar
Android och D8-avsockringsproxy (desugaring proxy)
Flera Alcinoe-komponenter (WebRTC, ExoPlayer-stödd video) är beroende av Java-bibliotek som använder språkfunktioner från Java 8. Android-verktygskedjan som levereras med äldre Delphi-versioner använder dx.bat för DEX-konvertering, som inte kan hantera dessa bytekoder på API-nivåer under 26. Lösningen är avsockring (desugaring), vilket D8 hanterar automatiskt när det anropas direkt. Alcinoe tillhandahåller ett proxyskript på {alcinoe_rootdir}\tools\D8Proxy\dx.bat som vidarebefordrar anrop från Delphis byggsystem till D8, vilket gör avsockringen transparent. Byt ut den ursprungliga dx.bat i din Android SDK:s build-tools-katalog (vanligtvis C:\SDKs\android\build-tools\30.0.3\) mot denna proxy. Embarcadero spårade det underliggande problemet på RSP-24155; senare versioner av SDK-verktygen åtgärdade det direkt, så kontrollera om din nuvarande verktygskedja fortfarande behöver den här lösningen
FireMonkeys renderingsproblem och Alcinoes svar
FireMonkeys standardmålningscykel blir en flaskhals i rullningstunga gränssnitt. En enda TRectangle med rundade hörn kan ta cirka 3 ms att rita om eftersom standardimplementeringen räknar om sökvägen på varje bildruta. Med 20 sådana kontroller synliga blir det 60 ms per bildruteomgång, vilket begränsar den effektiva bildfrekvensen långt under tröskeln för flytande rullning
Alcinoe adresserar detta med en GPU-resident buffert per kontroll. Den första målningen renderar kontrollen till en TTexture lagrad i GPU-minnet. Efterföljande ommålningar kopierar (blit) den texturen istället för att köra målningsalgoritmen på nytt. Det uppmätta resultatet på samma rundade rektangel sjunker från cirka 3 ms till cirka 0,1 ms. Utöver buffringen ersätter Alcinoe OpenGL:s banritning för grundläggande former med inbyggda Android- och iOS-ritnings-API:er, vilket kringgår kvalitets/prestanda-avvägningen knuten till Form.Quality. De relevanta kontrollerna är TALRectangle, TALCircle och en uppsättning förbättrade layoutbehållare inklusive en ScrollBox och TabControl
TALJsonDocument: DOM och SAX i en och samma typ
TALJsonDocument är Alcinoes JSON- och BSON-parser. Den stöder två traverseringslägen. DOM-läget bygger ett objekttree i minnet, vilket ger slumpmässig åtkomst till valfri nod på bekostnad av minne som är proportionellt mot dokumentstorleken. SAX-läget utlöser händelser när parsern läser varje token utan att behålla något träd, vilket är rätt val när du behöver filtrera ett stort dokument och bara behålla en handfull värden. DOM-parsrar i Delphi (DBXJSON, SuperObject och de andra) är vanligtvis tre till fem gånger långsammare än en SAX-metod för samma innehåll, eftersom varje nodallokering medför en omkostnad för att skapa objekt utöver själva tolkningsarbetet
Typen följer samma mönster för nodnavigering som TALXMLDocument. En minimal DOM-läsning ser ut så här:
MyJsonDoc.LoadFromJSON(AJsonStr, False {dom mode});
MyJsonDoc.ParseOptions := [poAllowComments];
// läs skalärvärden
ShowMessage(MyJsonDoc.ChildNodes['name'].ChildNodes['first'].Text);
ShowMessage(IntToStr(MyJsonDoc.ChildNodes['_id'].Int32));
// iterera en array
for I := 0 to MyJsonDoc.ChildNodes['contribs'].ChildNodes.Count - 1 do
Writeln(MyJsonDoc.ChildNodes['contribs'].ChildNodes[I].Text);
För SAX-läget tilldelar du en anonym procedur till OnParseText innan du anropar LoadFromJSON med det andra argumentet satt till True. Callback-funktionen tar emot nodens sökväg, namn, värde och en TALJSONNodeSubType som identifierar JSON-typen (sträng, heltal, flyttal, boolesk, och så vidare). Det läget producerar inga heap-allokeringar för noder, så det skalar till godtyckligt stora dokument utan att spränga minnesbudgeten
TALJsonDocument läser och skriver även BSON internt; skicka True som BSON-flagga till LoadFromFile eller SaveToFile. En andra variant, TALJsonDocumentU, använder UnicodeString (UTF-16) internt istället för AnsiString (UTF-8) för kontexter där den omgivande koden arbetar i Unicode hela vägen
MongoDB-klient och anslutningspoolning (connection pooling)
Alcinoes MongoDB-drivrutin täcker de vanliga frågeoperationerna och hanterar anslutningspoolning internt. Den enkla klienten, TAlMongoDBClient, öppnar och stänger en enda anslutning per operation. Den poolade varianten, TAlMongoDBConnectionPoolClient, upprätthåller en uppsättning levande anslutningar och ger en till varje anropande tråd från poolen, och returnerar den när anropet är klart. Den modellen hindrar flera trådar från att blockera varandra vid anslutningsuppsättning, vilket spelar roll när bakgrundsarbetare frågar samma databas samtidigt. För tailing-markörer (tailable cursors) på capped collections, övervakar TAlMongoDBTailMonitoringThread nya dokument och utlöser en callback när de anländer, vilket är standardmönstret för loggströmning eller ändringsmeddelanden utan polling
Andra komponenter värda att känna till
ALVideoPlayer renderar video till en TTexture istället för ett överläggsfönster, så andra FireMonkey-kontroller kan sitta ovanför det i Z-ordning. Android-bakänden använder ExoPlayer, som lägger till DASH-, HLS- och SmoothStreaming-stöd utöver det Androids inbyggda MediaPlayer hanterar. iOS-bakänden använder AVPlayer med motsvarande HLS-stöd
TALWebRTC omsluter WebRTC-stacken för peer-to-peer-ljud och -video. Det kräver varken en webbläsare eller ett plugin, och anslutningen passerar NAT via den standardmässiga ICE/STUN/TURN-förhandlingen som det underliggande biblioteket hanterar
TALStringList ersätter TStringList:s AnsiCompareText-baserade sortering med en platsoberoende ordinaljämförelse och en quicksort som är upp till 10 gånger snabbare på stora listor. Den hashade varianten, TALHashedStringList, lägger till en intern hashtabell för O(1)-sökning på bekostnad av något högre overhead på små listor. Observera att TALStringList är en 8-bitars AnsiString-lista, inte en Unicode-lista; den passar bra i serverkod där UTF-8 är arbetskodningen och ren genomströmning spelar större roll än platsspecifik jämförelse
På 64-bitars Windows överförs inte FastCode-arvet som gav många av Alcinoes strängrutiner deras hastighetsfördel (mestadels handskriven x86-assembler). Win64-byggena faller tillbaka på Pascal-implementeringarna, som körs märkbart långsammare på strängintensiva arbetsbelastningar. Projektet demo\ALStringBenchMark låter dig mäta gapet på din maskinvara innan du bestämmer dig för ett 64-bitars bygge där stränggenomströmning är en flaskhals
Den fullständiga källkoden finns på github.com/Zeus64/alcinoe