מה זה PyPy? פיתון מהיר יותר ללא כאבים

פיתון זכה למוניטין של היותו עוצמתי, גמיש וקל לעבוד איתו. מעלות אלו הובילו לשימוש במגוון עצום וגדל של יישומים, תהליכי עבודה ותחומים. אבל העיצוב של השפה - האופי המתפרש שלה, הדינמיות של זמן הריצה - פירושו שפייתון תמיד היה בסדר גודל איטי יותר מאשר שפות מקוריות למכונה כמו C או C ++.

במהלך השנים המפתחים העלו מגוון דרכים לעקיפת הבעיה למגבלות המהירות של פייתון. למשל, אתה יכול לכתוב משימות עתירות ביצועים ב- C ולעטוף אותן בפייתון; ספריות לימוד מכונה רבות עושות בדיוק את זה. לחלופין, תוכל להשתמש ב- Cython, פרויקט המאפשר לך לפזר קוד Python עם מידע מסוג זמן ריצה המאפשר לגבש אותו ל- C.

אך דרכים לעקיפת הבעיה אינן אידיאליות. האם זה לא יהיה נהדר אם נוכל פשוט לקחת תוכנית פייתון קיימת  כמו שהיא ולהפעיל אותה בצורה דרמטית מהר יותר? זה בדיוק מה ש- PyPy מאפשר לך לעשות.

סרטון קשור: שימוש בזמן הריצה של PyPy עבור Python

PyPy לעומת CPython

PyPy הוא תחליף טיפה למתורגמן Python, CPython. בעוד ש- CPython מרכיב את Python לקוד byt ביניים המתפרש לאחר מכן על ידי מכונה וירטואלית, PyPy משתמש באוסף בדיוק בזמן (JIT) כדי לתרגם קוד פייתון לשפת הרכבה מקורית.

בהתאם למשימה שמבוצעת, רווחי הביצוע יכולים להיות דרמטיים. בממוצע, PyPy מאיץ את פייתון בכ- 7.6 פעמים, כאשר משימות מסוימות מואצות פי 50 ומעלה. המתורגמן של CPython פשוט לא מבצע את אותם אופטימיזציות כמו ה- PyPy, וכנראה גם לא יעשה זאת, מכיוון שזו לא אחת ממטרות העיצוב שלה.

החלק הטוב ביותר הוא שנדרש מעט מאמץ מצד היזם כדי לפתוח את הרווחים ש- PyPy מספק. כל שעליך לעשות הוא להחליף את CPython ל- PyPy, ולרוב סיימת. ישנם כמה יוצאים מן הכלל, עליהם נדון להלן, אך מטרתו המוצהרת של PyPy היא להריץ קוד פייתון קיים ולא שונה ולספק לו העלאת מהירות אוטומטית.

PyPy תומך כיום גם בפייתון 2 וגם בפייתון 3, בדרך של גלגולים שונים של הפרויקט. במילים אחרות, עליך להוריד גרסאות שונות של PyPy בהתאם לגירסת ה- Python שתריץ. סניף ה- Python 2 של PyPy כבר הרבה יותר זמן, אך גרסת ה- Python 3 הועלתה למהירות מאוחר. כרגע הוא תומך גם בפייתון 3.5 (איכות ייצור) וגם בפייתון 3.6 (איכות בטא).

בנוסף לתמיכה בכל שפות הליבה של פיתון, PyPy עובד עם הרוב המכריע של הכלים במערכת האקולוגית של פייתון, כמו למשל  pip לאריזות או  virtualenv לסביבות וירטואליות. רוב חבילות ה- Python, אפילו אלה עם מודולי C, צריכות לעבוד כמו שהן, אם כי יש מגבלות שנכנס בהמשך.

איך PyPy עובד

PyPy משתמש בטכניקות אופטימיזציה שנמצאות במהדרים מדויקים אחרים לשפות דינמיות. זה מנתח את הפעלת תוכניות Python כדי לקבוע את סוג המידע של אובייקטים בזמן שהם נוצרים ומשמשים אותם בתוכניות, ואז משתמש במידע מסוג זה כמדריך להאיץ את העניינים. לדוגמה, אם פונקציית Python פועלת רק עם אחד או שניים מסוגי אובייקט שונים, PyPy מייצר קוד מכונה לטיפול במקרים ספציפיים אלה.

האופטימיזציות של PyPy מטופלות אוטומטית בזמן הריצה, כך שבדרך כלל אינך צריך לשנות את הביצועים שלה. משתמש מתקדם עשוי להתנסות באפשרויות שורת הפקודה של PyPy כדי ליצור קוד מהיר יותר למקרים מיוחדים, אך רק לעיתים נדירות הדבר נחוץ.

PyPy יוצא גם מהדרך שבה CPython מטפל בפונקציות פנימיות מסוימות, אך מנסה לשמר התנהגויות תואמות. לדוגמה, PyPy מטפל באיסוף האשפה באופן שונה מ- CPython. לא כל האובייקטים נאספים באופן מיידי ברגע שהם יוצאים מההיקף, כך שתוכנית פייתון הפועלת תחת PyPy עשויה להציג טביעת רגל זיכרון גדולה יותר מאשר בעת ריצה תחת CPython. אבל אתה עדיין יכול להשתמש שולט איסוף אשפה ברמה הגבוהה של פיתון נחשף דרך gcמודול, כגון gc.enable(), gc.disable(), ו gc.collect().

אם אתה רוצה מידע על התנהגות JIT של PyPy בזמן ריצה, PyPy כולל מודול,, pypyjitשחושף ווים רבים של JIT ליישום Python שלך. אם יש לך פונקציה או מודול שנראה כי הם מתפקדים בצורה גרועה עם ה- JIT, pypyjitמאפשר לך לקבל נתונים סטטיסטיים מפורטים אודותיו.

מודול __pypy__אחר ספציפי ל- PyPy, חושף תכונות אחרות הספציפיות ל- PyPy, ולכן יכול להיות שימושי לכתיבת אפליקציות הממנפות את התכונות הללו. בגלל הדינמיות של זמן הריצה של Python, ניתן לבנות אפליקציות Python המשתמשות בתכונות אלה כאשר PyPy קיים ומתעלם מהן כשלא.

מגבלות PyPy

קסום כמו ש- PyPy נראה, זה לא קסם. ל- PyPy יש מגבלות מסוימות שמפחיתות או מייתרות את יעילותה עבור סוגים מסוימים של תוכניות. למרבה הצער, PyPy אינו תחליף אוניברסלי לחלוטין לזמן הריצה של CPython.

PyPy עובד הכי טוב עם יישומי Python טהורים

PyPy תמיד ביצע את הביצועים הטובים ביותר עם יישומי פייתון "טהורים" - כלומר, יישומים שנכתבו בפייתון ולא שום דבר אחר. חבילות פייתון המתממשקות עם ספריות C, כמו NumPy, לא צלחו גם בשל האופן שבו PyPy מחקה את הממשקים הבינאריים המקוריים של CPython. 

מפתחי PyPy התבטלו בנושא זה, והפכו את PyPy לתואם יותר עם רוב חבילות ה- Python התלויים בתוספות C. Numpy, למשל, עובד טוב מאוד עם PyPy עכשיו. אבל אם אתה רוצה תאימות מרבית עם סיומות C, השתמש ב- CPython.

PyPy עובד הכי טוב עם תוכניות הפועלות זמן רב יותר

אחת מתופעות הלוואי של האופן שבו PyPy מייעל את תוכניות ה- Python היא שתוכניות ארוכות יותר מרוויחות יותר מהאופטימיזציות שלה. ככל שהתוכנית פועלת זמן רב יותר, כך מידע מסוג זמן ריצה יותר PyPy יכול לאסוף, וככל שהוא יכול לבצע אופטימיזציות רבות יותר. סקריפטים של פייתון חד פעמי לא ירוויחו מסוג זה. ביישומים שכן נהנים מהם יש בדרך כלל לולאות שפועלות לפרקי זמן ארוכים, או פועלות ברציפות ברקע - מסגרות אינטרנט, למשל.

PyPy לא עושה קומפילציה מבעוד מועד

PyPy  מהדר  קוד Python, אך הוא אינו  מהדר  עבור קוד Python. בגלל האופן שבו PyPy מבצע את האופטימיזציות שלה והדינמיות הטבועה בפייתון, אין שום אפשרות להוציא את קוד ה- JITted שהתקבל כבינארי עצמאי ולהשתמש בו מחדש. יש להרכיב כל תוכנית לכל הפעלה. אם ברצונך להרכיב את פייתון לקוד מהיר יותר שיכול לפעול כאפליקציה עצמאית, השתמש ב- Cython, Numba או בפרויקט Nuitka הניסיוני.