# עלייה מהירה: הדמון כל הרצה של `pperl` משלמת בדרך כלל את מלוא חשבון העלייה: יצירת תהליך, אתחול המפרש, ו- החלק היקר עבור תוכניות אמיתיות - הידור הסקריפט שלך וכל מודול שהוא טוען ב-`use`. הדמון מאפשר להרצות חוזרות של אותו סקריפט לדלג על החשבון הזה: תהליך תושב שומר תמונה מהודרת במלואה של הסקריפט, וכל הרצה חדשה היא fork של אותה תמונה הניגשת ישירות לביצוע. התכונה היא **בהצטרפות מפורשת** בלבד, לכל הרצה. שום דבר לא משתנה עבור `pperl script.pl` פשוט, ובכל פעם שהדמון אינו יכול לשרת בקשה במדויק, pperl נסוג בשקט להרצה קרה רגילה. הנכונות לעולם אינה תלויה בדמון; רק המהירות תלויה בו. ## התחלה מהירה ```bash pperl --daemon=start # start the daemon (background) PPERL_DAEMON=2 pperl report.pl # first run: compiles, caches PPERL_DAEMON=2 pperl report.pl # every further run: fork + run pperl --daemon=status # what is cached, what is live pperl --daemon=stop # shut it down ``` ההרצה הראשונה של סקריפט שהצטרף בונה את *התבנית* שלו: הדמון מהדר את הסקריפט (כולל כל המודולים הנטענים ב-`use` ובלוקי `BEGIN`) ושומר את התוצאה תושבת. כל הרצה מאוחרת יותר של אותו סקריפט עושה fork לתבנית ורק מבצעת. ## מתי זה משתלם החיסכון הוא זמן ההידור של הסקריפט שלך: ניתוח בתוספת טעינת מודולים בתוספת עבודת `BEGIN`. עבור סקריפט הטוען קומץ מודולים זהו בדרך כלל החלק הדומיננטי של העלייה, והרצת תבנית יכולה להיות מהירה פי כמה מקצה לקצה. עבור סקריפט טריוויאלי שאינו טוען דבר, החיסכון שווה בקירוב לתקורה של הדמון עצמו והתוצאה מתאזנת - לעולם אין הפסד משמעותי. כמו בכל מקום במדריך זה: מדוד את הסקריפט שלך עצמך, על המכונה שלך עצמך, לפני הסקת מסקנות - ראה [מדידה](measuring.md). ## מה משמעות ההרצה מתבנית הרצת תבנית מבצעת אך ורק את *שלב הריצה* של הסקריפט שלך. ההידור כבר קרה, פעם אחת, כאשר התבנית נבנתה. pperl מבטיח שהדברים הבאים טריים ונכונים בכל הרצה: - `@ARGV`, `%ENV`, הספרייה הנוכחית, umask - קלט, פלט ושגיאה תקניים (ההפניות והצינורות שלך) - מזהה התהליך `$$` - קודי יציאה, ומוות באמצעות אות (סקריפט שנהרג הורג את `pperl` הקורא באותו אופן) - הידית `__DATA__` - כל הרצה קוראת אותה מההתחלה, בנפרד מהרצות אחרות מה ש**אינו** נעשה מחדש הוא כל דבר שהקוד שלך עשה בזמן ההידור. בלוקי `BEGIN`, וקוד מודול שבוצע בזמן `use`, רצו פעם אחת כאשר התבנית נבנתה; תופעות הלוואי שלהם הן חלק מהתמונה שכל הרצה יורשת. השלכות שבאחריותך כשאתה מצרף סקריפט: - `$^T` (זמן ההתחלה של הסקריפט) ומצב הזרע האקראי מתוארכים ליצירת התבנית. אם לסקריפט שלך זה חשוב, החתם אותם מחדש בתחילת שלב הריצה: ```perl INIT { $^T = time; srand(); } ``` - ערכים הנקראים מ-`%ENV` *בזמן ההידור* (בתוך `BEGIN` או בזמן `use`) היו הערכים של ההרצה שבנתה את התבנית. קרא את הקונפיגורציה בזמן הריצה, או בבלוק `INIT`, אם עליה לעקוב אחר הסביבה הקוראת. - file handles, סוקטים או חיבורי מסד נתונים שנפתחו בזמן ההידור משותפים לכל הרצה. פתח חיבורים בזמן הריצה - אותו כלל שהתבסס מזמן עבור טעינה מוקדמת של שרתי יישומים. אם סקריפט אינו יכול לעמוד בחוזה זה, פשוט אל תצרף אותו; `PPERL_DAEMON=2` הוא לכל הרצה, לא גלובלי. ## עריכת הסקריפט, והמטמון הדמון מבחין כאשר קובץ הסקריפט עצמו משתנה ובונה מחדש את התבנית אוטומטית בהרצה הבאה - עריכת הסקריפט שלך לעולם אינה מגישה לך תמונה מיושנת. עריכות ל *מודולים* שהסקריפט טוען אינן מזוהות אוטומטית. לאחר שינוי מודול, השלך את התבנית המושפעת ידנית: ```bash pperl --daemon-reset=report.pl # forget this script's template pperl --daemon-reset # forget all templates ``` תבניות הן מטמון חסום: לכל היותר `--daemon-max-scripts` מהן (ברירת מחדל 100), מפונות לפי העיקרון שהכי פחות שימשו לאחרונה, וכל אחת פגה לאחר פסק-זמן חוסר-הפעילות של הדמון (`--daemon-idle`, ברירת מחדל 900 שניות). ## מתי pperl נסוג להרצה קרה הדמון מסרב - והלקוח נסוג להרצה רגילה, בשקט ובאופן נכון - בכל פעם שאינו יכול לשחזר את ההרצה במדויק: - אף דמון אינו רץ עבור קובץ ה-pperl הבינארי הזה - משתני סביבה המעצבים את עליית המפרש שונים מאלה של הדמון (`PERL_HASH_SEED`, `PERL_PERTURB_KEYS`, `PERL_RAND_SEED`, `PERL_INTERNAL_RAND_SEED`, `PERL_UNICODE`, `LANG`, כל `LC_*`, כל `MALLOC_*`) - דגלי שורת הפקודה שונים מאלה שאיתם נבנתה התבנית (תבנית מאחסנת קונפיגורציה אחת) - התבנית עדיין נבנית על ידי הרצה ראשונה מקבילית - ההרצה היא שורת-פקודה בודדת עם `-e` (תבניות שומרות במטמון קובצי סקריפט) - `--interactive` או `--stats` בתוקף ## אבטחה וזהות הדמון משרת בדיוק משתמש אחד: הסוקט שלו שוכן בספרייה עם הרשאות לבעלים בלבד ומזהה המשתמש של העמית בכל חיבור מאומת. הוא גם משרת בדיוק *בנייה* אחת של pperl: הסוקט מקושר לזהות של הקובץ הבינארי (`pperl --build-id` מדפיס אותה), כך שלאחר שדרוג של pperl פשוט לעולם לא פונים שוב לדמון הישן והוא יוצא בפסק-זמן חוסר-הפעילות שלו. ## מגבלות - בקרת המשימות מקורבת: הסקריפט הרץ הוא ילד של הדמון, לא של המעטפת שלך. אותות שאתה שולח ל-`pperl` (כולל `Ctrl-C`) מועברים לסקריפט, אך `Ctrl-Z` משעה רק את `pperl` שבחזית, לא את תהליך הסקריפט. - תבנית אחת לכל נתיב סקריפט, המחזיקה קונפיגורציית דגלים אחת. הרצת אותו סקריפט עם דגלים שונים נסוגה להרצה קרה במקום לבנות מחדש את התבנית. - `PPERL_DAEMON=1` (או `--via-daemon`) קיים כמצב מצומצם העושה fork למפרש מאותחל-מראש אך עדיין מהדר את הסקריפט בכל הרצה. הוא כמעט אינו חוסך דבר ומועיל בעיקר לבדיקת הדמון עצמו; השתמש ב-`PPERL_DAEMON=2` לתועלת האמיתית.