Alcinoe היא ספריית רכיבים בקוד פתוח עבור Delphi ו-C++Builder, המתוחזקת ב-GitHub על ידי Zeus64. היא מכסה תחומים ש-VCL ו-FireMonkey RTL משאירים לצדדים שלישיים: נגן וידאו מואץ GPU, מעטפת WebRTC, פקדי עריכה טבעיים ל-iOS ול-Android, מנתח JSON/BSON במצב כפול, לקוח MongoDB עם מאגר חיבורים, מעטפת ImageMagick ואוסף של פקדי FireMonkey שעוקפים לחלוטין את צינור הרינדור הרגיל. הספרייה בנתה את המוניטין שלה על Rio (10.3.3) ו-Sydney (10.4.2), ומאז עקבה אחרי כל גרסה של Embarcadero. נכון לכתיבת שורות אלה, היא תואמת לחלוטין ל-Delphi 11.1 Alexandria ול-Delphi Athens 12.3
הוספת Alcinoe לפרויקט
ההתקנה מתפצלת על שאלה אחת: האם אתה זקוק לתמיכה בזמן עיצוב עבור הפקדים החזותיים של Alcinoe? אם לא, דלג לחלוטין על ה-BPL. הוסף את {alcinoe_rootdir}\source לנתיב החיפוש של ספריית הפרויקט וסיימת. כל רכיב לא חזותי, כולל המנתחים, לקוחות מסד הנתונים וכלי המחרוזות, עובר הידור מהמקור מבלי לרשום דבר
כאשר אתה כן זקוק לתמיכה בזמן עיצוב, הנתיב מעט ארוך יותר. פתח את Component > Install Packages בסביבת הפיתוח (IDE) של Delphi, נווט ל-BPL התואם לגרסה שלך (לדוגמה {alcinoe_rootdir}\lib\bpl\alcinoe\Win32\alexandria\Alcinoe_alexandria.bpl), התקן אותו, ולאחר מכן עדיין הוסף את {alcinoe_rootdir}\source לנתיב החיפוש. ה-BPL רושם את הרכיבים; ספריית המקור היא מה שהמהדר מוצא כאשר הוא מהדר את הפרויקט שלך
Alcinoe מספקת תיקונים אופציונליים למקורות ה-RTL של Embarcadero. אם אתה רוצה אותם, נווט אל {alcinoe_rootdir}\embarcadero\, בחר בתיקיית המשנה של הגרסה שלך והפעל את update.bat. הסקריפט מצפה ל-GIT ב-PATH ומניח מיקום התקנה של Embarcadero כברירת מחדל. הוא מביא את מקור ה-RTL המקורי ומחיל את התיקונים. לאחר סיום, הוסף את ספריית המקור המתוקנת לנתיב החיפוש של הפרויקט שלך כך שהמהדר יבחר בה לפני העותק לקריאה בלבד שבעץ ההתקנה של Embarcadero. כל זה אינו נדרש כדי להתחיל; זה משנה רק אם נתקלת בבאגים שהתיקונים מטפלים בהם
Android ופרוקסי ה-desugaring של D8
מספר רכיבי Alcinoe (כגון WebRTC, וידאו מבוסס ExoPlayer) תלויים בספריות Java המשתמשות בתכונות שפה של Java 8. שרשרת הכלים של Android המסופקת עם גרסאות Delphi ישנות יותר משתמשת ב-dx.bat עבור המרת DEX, שאינו יכול לטפל בקודים אלה ברמות API מתחת ל-26. התיקון הוא desugaring, ש-D8 מטפל בו אוטומטית כאשר הוא נקרא ישירות. Alcinoe מספקת סקריפט פרוקסי ב-{alcinoe_rootdir}\tools\D8Proxy\dx.bat שמעביר קריאות ממערכת הבנייה של Delphi ל-D8, מה שהופך את ה-desugaring לשקוף. החלף את dx.bat המקורי בספריית build-tools של Android SDK שלך (בדרך כלל C:\SDKs\android\build-tools\30.0.3\) בפרוקסי זה. Embarcadero עקבה אחר הבעיה הבסיסית ב-RSP-24155; גרסאות מאוחרות יותר של כלי ה-SDK טיפלו בה ישירות, אז בדוק אם שרשרת הכלים הנוכחית שלך עדיין זקוקה למעקף זה
בעיית הרינדור של FireMonkey והתשובה של Alcinoe
מחזור הציור כברירת מחדל של FireMonkey הופך לצוואר בקבוק בממשקי משתמש כבדי גלילה. TRectangle בודד עם פינות מעוגלות עשוי לקחת כ-3 מילי-שניות לצייר מחדש מכיוון שיישום המלאי מחשב מחדש את הנתיב בכל פריים. עם 20 פקדים כאלה גלויים, זה מסתכם ב-60 מילי-שניות לכל מעבר פריים, מה שמגביל את קצב הפריימים האפקטיבי הרבה מתחת לסף לגלילה חלקה
Alcinoe מטפלת בזה עם חוצץ שיושב ב-GPU לכל פקד. הציור הראשון מרנדר את הפקד ל-TTexture המאוחסן בזיכרון ה-GPU. ציורים מחדש הבאים מבצעים blit לטקסטורה זו במקום להפעיל מחדש את אלגוריתם הציור. התוצאה הנמדדת על אותו מלבן מעוגל יורדת מסביבות 3 מילי-שניות לסביבות 0.1 מילי-שניות. מעבר לחוצץ, Alcinoe מחליפה ציור נתיבי OpenGL עבור צורות בסיסיות בממשקי API של ציור טבעיים של Android ו-iOS, תוך עקיפת הפשרה של איכות/ביצועים הקשורה ל-Form.Quality. הפקדים הרלוונטיים הם TALRectangle, TALCircle, ואוסף של מכלי פריסה משופרים כולל ScrollBox ו-TabControl
TALJsonDocument: DOM ו-SAX בסוג אחד
TALJsonDocument הוא מנתח ה-JSON וה-BSON של Alcinoe. הוא תומך בשני מצבי סריקה. מצב DOM בונה עץ אובייקטים בזיכרון, המעניק גישה אקראית לכל צומת על חשבון זיכרון יחסי לגודל המסמך. מצב SAX יורה אירועים כאשר המנתח קורא כל אסימון מבלי לשמור אף עץ, וזו הבחירה הנכונה כאשר עליך לסנן מסמך גדול ולהחזיק רק קומץ ערכים. מנתחי DOM ב-Delphi (DBXJSON, SuperObject, והאחרים) בדרך כלל איטיים פי שלושה עד חמישה מגישת SAX עבור אותו תוכן, מכיוון שכל הקצאת צומת נושאת תקורה של יצירת אובייקטים בנוסף לעבודת הניתוח עצמה
הסוג עוקב אחר אותה תבנית ניווט בצמתים כמו TALXMLDocument. קריאת DOM מינימלית נראית כך:
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);
עבור מצב SAX, הקצה פרוצדורה אנונימית ל-OnParseText לפני הקריאה ל-LoadFromJSON עם הארגומנט השני מוגדר ל-True. הקריאה החוזרת מקבלת את נתיב הצומת, השם, הערך, ו-TALJSONNodeSubType המזהה את סוג ה-JSON (מחרוזת, מספר שלם, מספר נקודה צפה, בוליאני וכן הלאה). מצב זה לא מייצר הקצאות ערימה עבור צמתים, ולכן הוא מתרחב למסמכים גדולים באופן שרירותי מבלי לחרוג מתקציב הזיכרון
TALJsonDocument גם קורא וכותב BSON באופן טבעי; העבר True כדגל BSON ל-LoadFromFile או ל-SaveToFile. וריאנט שני, TALJsonDocumentU, משתמש ב-UnicodeString (UTF-16) באופן פנימי במקום ב-AnsiString (UTF-8) עבור הקשרים שבהם הקוד שמסביב עובד ב-Unicode לאורכו
לקוח MongoDB ומאגר חיבורים
מנהל ההתקן של Alcinoe עבור MongoDB מכסה את פעולות השאילתה הנפוצות ומטפל במאגר חיבורים באופן טבעי. הלקוח הפשוט, TAlMongoDBClient, פותח וסוגר חיבור יחיד לכל פעולה. הווריאנט בעל המאגר, TAlMongoDBConnectionPoolClient, שומר על קבוצה של חיבורים חיים ומוסר אחד לכל חוט קריאה מהמאגר, ומחזיר אותו כאשר הקריאה מסתיימת. מודל זה מונע מחוטים מרובים לחסום זה את זה בהגדרת החיבור, מה שחשוב בכל פעם שעובדי רקע מתשאלים את אותו מסד נתונים בו זמנית. עבור סמנים מתמשכים (tailable cursors) על אוספים מוגבלים (capped collections), TAlMongoDBTailMonitoringThread צופה במסמכים חדשים ומפעיל קריאה חוזרת כאשר הם מגיעים, וזו התבנית הסטנדרטית להזרמת יומנים או להתראות על שינויים ללא דגימה (polling)
רכיבים נוספים ששווה להכיר
ALVideoPlayer מרנדר וידאו ל-TTexture במקום לחלון כיסוי, כך שפקדי FireMonkey אחרים יכולים לשבת מעליו בסדר Z. המערכת העורפית של Android משתמשת ב-ExoPlayer, המוסיף תמיכה ב-DASH, HLS, ו-SmoothStreaming מעבר למה ש-MediaPlayer המובנה של Android מטפל בו. המערכת העורפית של iOS משתמשת ב-AVPlayer עם תמיכת HLS מקבילה
TALWebRTC עוטף את מחסנית ה-WebRTC עבור שמע ווידאו מעמית-לעמית (peer-to-peer). הוא אינו דורש דפדפן או תוסף, והחיבור חוצה NAT דרך משא ומתן סטנדרטי של ICE/STUN/TURN שהספרייה הבסיסית מטפלת בו
TALStringList מחליף את המיון מבוסס AnsiCompareText של TStringList בהשוואה אורדינלית שאינה תלויה באזור (locale-independent) ובמיון מהיר (quicksort) שהוא עד פי 10 מהיר יותר ברשימות גדולות. הווריאנט המגובב, TALHashedStringList, מוסיף טבלת גיבוב פנימית עבור בדיקה ב-O(1) במחיר של תקורה מעט גבוהה יותר ברשימות קטנות. שים לב ש-TALStringList היא רשימת AnsiString של 8 סיביות, לא רשימת Unicode; היא מתאימה היטב בקוד צד שרת שבו UTF-8 הוא קידוד העבודה ותפוקה גולמית חשובה יותר מהשוואה מודעת-אזור
ב-Windows 64 סיביות, המורשת של FastCode שהעניקה לרבות משגרות המחרוזות של Alcinoe את יתרון המהירות שלהן (לרוב שפת סף x86 בכתב יד) לא עוברת. הבנייות של Win64 נופלות חזרה ליישומי ה-Pascal, שרצים בצורה ניכרת לאט יותר בעומסי עבודה עתירי מחרוזות. פרויקט demo\ALStringBenchMark מאפשר לך למדוד את הפער על החומרה שלך לפני התחייבות לבניית 64 סיביות שבה תפוקת מחרוזות היא צוואר בקבוק
המקור המלא נמצא בכתובת github.com/Zeus64/alcinoe