Joomla Extentions Directory and GPL

קיבלתי את האימייל הבא מהצוות שמנהל את אתר ההרחבות של ג'ומלה, שאומר בקצרה שמ 1.7.2009 רק חבילות ברשיון GPL יכללו במאגר ההרחבות של ג'ומלה.
הוספתי את פיירסטטס למאגר ההרחבות לפני שנתיים וחצי, והמערכת קיבלה יופי של תגובות ממשתמשי ג'ומלה.
מכיוון שפיירסטטס לא משוחררת תחת GPL, היא כבר לא מופיעה במאגר.
בבדיקה מול גוגל-קש, מספר ההרחבות במאגר ירד מ4554 ל2990, ירידה של 33%.
לדעתי זו חוצפה ובריונות של של ג'ומלה לדרוש ממפתחי ההרחבות לשנות את הרשיון, וויתרתי על שרותי אתר ההרחבות של ג'ומלה (שזה די חבל, כי הוא הכיל 21 ביקורות על פיירסטטס, רובן המכריע מאוד חיוביות).

האימייל, תגובתי למטה:

Dear "Omry Yadan",

We at the Joomla Extensions Directory want to remind you that, as announced 6 months ago, on 1 July are going to change the directory policy to list GPL Extensions only. As always, commercial and non commercial extensions are welcome on JED as long as they use the GPL license.

The deadline for changing licenses without being unpublished is http://www.timeanddate.com/worldclock/fixedtime.html?month=7&day=2&year=2009&hour=00&min=55&sec=0&p1=103.

This change is intended for to bring it into line with the overall mission of the Joomla Project. After careful thought and reflection, the Joomla! Project determined that the Joomla! Extensions Directory should be a community resource that fully embodies the project's values, especially freedom as exemplified by the GPL license.

Policy changes
We have implemented some policy changes to
– Enhance support of GPL developers
– Address concerns about relicensing.
We think that the best place to get an extension is from the original developer of that extension. Therefore we will not link to collections of GPL extensions that are not submitted by the original developers. These are not requirements of the GPL license but rather fall in line with our "forking" guidelines.

Forked projects

Non-GPL extensions
In order for you as developer to keep a non-GPL extension listed you need to relicense it to GPL.
You do it through to add two elements to each source file of your program:
– a copyright notice
– statement of copying permission, saying that the program is distributed under the terms of the GNU General Public License –
http://www.fsf.org/licensing/licenses/gpl-howto.html
– adding a <license> tag to the header of the extension XML file
– including a copy of the GPL license in your distribution. This does not need to be copied to the user's server on install, but must be included in the distribution.

Note for GPL extensions:

– You need to state on your website that the extensions are distributed with the GPL license
– You can't add any conditions that restricts or contradicts the GPL license.

We thank you for your patience during these transitions. We will  extend any assistance possible to making the transition as painless as possible for everyone involved. The project is committed to providing the information and help that developers need in order to relicense (or to license for the first time, if there is no current license).

The JED editors and members of the Core Team and Open Source Matters board are ready to advise or assist any developer who would like this help. If you have any questions about licensing or want help, then you can contact OSM with the following email address license@opensourcematters.org or the JED editors
team@extensions.joomla.org

Some frequently asked questions

What if I have some GPL and some non-GPL extensions?

This policy refers only to those extensions listed in the JED. Your GPL extensions are permitted to be listed on the JED but your non-GPL extensions are not.

Where can I get information about how to license my product using the GNU GPL?

Every copy of Joomla includes a copy of the GNU GPL with instructions for licensing in the license.php file. Instructions are also available from the Free Software Foundation.

All you need to do is add two elements to each source file of your program: a copyright notice (such as “Copyright 1999 Terry Jones”), and a statement of copying permission, saying that the program is distributed under the terms of the GNU General Public License. (Free Software Foundation)


Can I use GPL v3 to license my extension?

Yes. In particular, you may need to use GPLv3 if you rely on certain third party libraries or APIs for your extension.

Can I use libraries in my GPL extension that are GPL compatible?

Yes.

What GPL version is Joomla! licensed under?

Joomla! is licensed under GPL version 2 or later.

Why are only GNU GPL licensed extensions being listed?

The simple answer is, making the JED a GPL only resource is the easiest and most practical solution. It frees the JED team from having to investigate or worry about licensing issues. It frees OSM from having to create and maintain a list of one or more acceptable licenses. When you break it down, other licenses were created because they opposed one or more parts of the GPL. The only license that truly embodies the spirit of the GPL is the GPL. Throughout the Open Source world, there is plenty of disagreement over what that spirit is and there is even more disagreement over what licenses are compatible and incompatible. In the end, our list of compatible licenses might be very different from yours. Our list of licenses that share the spirit of the GPL will most certainly be different than yours. So, we could waste months of time researching a list and debating which licenses should be included and excluded or we can make it simple and easy to understand for the community, the developers, and the JED team so that we can use those precious months to focus on the real point of this project: making great software.

Can I use a GPL compatible license?

The JED will only list extensions licensed using the GNU GPL.

What if I think my extension doesn't violate the Joomla! license?

This is a policy in favor of software freedom and the mission, vision and values of the Joomla! Project, not one about technical issues in licensing.

What does this mean for enforcement of the Joomla! license more generally?

Enforcement of the Joomla! license is a separate issue from the policies of the JED.
If you have relicensed in recent days, thank you for your cooperation.

תגובתי:

First of all, I am both a user and a developer of several open source projects (some of which are using GPL, although I generally prefer BSD now because it puts less constraints on the end user).

the way I see it, you are trying to FORCE me to change my license, and I find this unacceptable.

FireStats is not a Joomla plugin, it's a full fledged application that happen to support Joomla (and many other systems).

If I will dance to the tunes coming from WordPress, Jooma,Drupal or any other supported app, I will never get anywhere.

I am sorry, but I have no intention of changing my license.

feel free to remove FireStats from the Joomla extentions directory.

if I decide to re-license it under GPL I will list it again.

it is a pity because FireStats got great feedback from the Joomla community, but I am not going to step over my principles because of this.

the license under which I decide to release my software if my own decision, my mine alone.

Omry Yadan,

FireStats developer.

FireStats 1.6.0-stable

בשעה טובה, פיירסטטס 1.6 שוחרר כגרסא יציבה.
אפשר לראות מה חדש מ1.5 פה.

בקצרה:

  • שיפורי ביצועיים משמעותיים
  • דפדפוף בטבלאת הרשומות
  • מספר מנויי RSS בוורדפרס (רק למי שתורם)
  • אפשר להקליט כניסות עם ג'אווה סקריפט
  • תמיכה בוודיג'טים בדש בורד של וורדפרס (כולל 2.7)
  • שיפורים בTAB ניהול האתרים (שימושי במיוחד לאתרי WPMU)
  • ועוד כמה תיקוני באגים חשובים יותר או פחות.

הורידו בהמוניכם.

הבאג שנלכד

מאז שעברתי לשרת החדש, היו לי בעיות עם שרת האפאצ'י: לפעמים הוא פשוט הפסיק לענות לבקשות, וחזר לעצמו רק אחרי restart.
בהתחלה לא היה לי ברור מה גורם לזה. חקרתי איך אפשר לראות מה עושה האפאצ'י בזמן שהוא רץ, וגיליתי את mod-status, שמאפשר לדעת מה עושה כל Worker באפאצ'י, ועוד כמה דברים שימושיים.
חיכיתי בסבלנות שהבעיה תופיעה שוב, וכשהיא קרתה אחרי כמה ימים – גיליתי כמובן שאני לא יכול לגשת לURL של mod-status בגלל הבעיה.
הצעד הבא היה לכתוב סקריפט קטן שידגום את הstatus של האפאצ'י כל שתי דקות וישמור את התשובה לקובץ.
אחרי כמה ימים הבעיה שוב קרתה והפעם ראיתי שרוב הWorkerים בשרת היו עסוקים בלנסות לדבר עם trac, שלא ממש ענה בגלל איזו שהיא בעיה עם בסיס הנתונים שלו.
פניתי לקבוצת הדיון של מפתחי trac, והם הציעו שאני אשדרג את sqlite (שהוא בסיס הנתונים שtrac משתמש בו ברוב ההתקנות), וגם ביקשו דברים שדורשים די הרבה זמן – כמו לקמפל את mod-wsgi עם מידע דיבאג, ולהתחבר אליו עם gdb ברגע שהעסק תקול כדי לראות מה הוא עושה.
שידרגתי, וכמובן שהבעיה לא נפתרה – אבל לא מצאתי זמן לעשות את מה שהם ביקשו.
בשלב הזה כבר הייתי די מעוצבן מזה שכל כמה ימים נופל לי האפאצ'י עד שאני בועט בו, והתקנתי את Monit, שמנתר את השרת ויכול להפעיל אותו מחדש אוטומטית אם הוא נופל (עוד על Monit בקרוב).
Monit איתחל את השרת תוך 4-5 דקות מרגע שהבעיה הופיע, וזה שינה את הסימפטומים מהמצב החמור של "השרת לא עונה לכמה שעות כל כמה ימים" למצב הנסבל של "השרת לא עונה לכמה דקות כל כמה ימים".
נסבל, וכדרכם של עצלנים, סבלתי עד שלפני כמה ימים Monit פישל ולא עבד משום מה, והשרת שוב היה למטה חצי לילה.
פניתי שוב לקבוצת הדיון של trac – הפעם מצויד בכל מידע הדיבאג שהם ביקשו, וסיפרתי להם שלמרות ששידרגתי הבעיה ממשיכה.
בינתיים ניסתי לראות איך אני משחזר את הבעיה – חיפשתי כלי לStress test לשרתי HTTP, משהו פשוט שיאפשר לי להפציץ URL בודד.
מצאתי את Siege, כלי פשוט שנותן בדיוק את זה.
בשימוש פשוט בSiege, גיליתי שאני מצליח להפיל את השרת אם אני מפעיל 15 משתמשים מול הURL של קו הזמן של trac, אחד הדפים הדורשניים ביותר במערכת.

במקביל פניתי לערוץ הIRC של טראק, ודיברתי עם osimons – אחד המפתחים של trac – על הבעיה.
גילינו שכשאני מריץ את Siege, טראק פותח את קובץ בסיס הנתונים מאות פעמים, מה שלא בדיוק הסתדר עם זה שיש בטראק Connection pooling.
המשכתי לחקור את העניין לבד, ובסוף גיליתי שהConnection pooling בכלל מכובה עבור חיבורי SQLite במכונות שלא מריצות… חלונות NT.
הגיוני? לא יודע. הפעלתי מחדש את העסק, ומאז נפתרה הבעיה.

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

עברתי לשרת החדש לפני כמעט חצי שנה, ובשעה טובה נפתרה הבעיה המציקה. לפעמים באגים הם ממש עיקשים וחמקניים.

World of Goo

במהלך חיפוש אחרי המשחק הבא שלי בGamespot גיליתי את World of Goo, משחק פאזלים שקיבל את הציון המבטיח 9.
הורדתי אותו מרשת הביטורנט הקרובה לביתי (ISO פצפון של 150 מגה), התקנתי והתאהבתי במשחק.
עבר הרבה זמן מאז שראיתי משחק מקורי באמת.
המשחק הוא בעצם סימולציה פיזיקלית של ג'יפות קטנות בשם Goo, מכל מני סוגים.
המטרה, בדומה למטרה בלמינגס היא להביא כמות מסויימת של ג'יפוני גו למשאבה שמעבירה אל השלב הבא.
כדי להגיע לשם, בונים מהג'יפונים מגדלים, גשרים ומה לא.
המשחק פשוט כיף צרוף.

אחרי ששיחקתי בו רבע שעה החלטתי שהוא שווה קניה.
קפצתי לאתר של החברה המפתחת, 2dboy , גיליתי שהמשחק פותח על ידי שני חבר'ה בלבד, קייל גבלר ורון כרמל (משלנו?), שיושבים בסן פרנסיסקו.
הדבר הבא שראיתי היה שבקרוב הם ישחררו גרסא ללינוקס.
מייד זיהיתי שמדובר באתר שמריץ וורדפרס, בדיקה נוספת חשפה שהם משתמשים בפיירסטטס.
שלחתי להם אימייל עם הצעה להחלפת רשיון פיירסטטס ברשיון למשחק, אבל הבהרתי באימייל שהם יכולים להמשיך להשתמש בפיירסטטס חופשי, ושאם הם לא רוצים להחליף רשיונות אני אקנה את המשחק.
לשמחתי קייל חזר אלי והסכים מיד.
אז עכשיו יש לי עותק חוקי של המשחק, ואני ממליץ בחום לכל מי שמחפש משחק פאזלים חמוד בטירוף לקנות עותק (רק 20$).

FireStats 1.6.0-beta1

בשעה טובה, נולדה גרסאת פיירסטטס חדשה – פיירסטטס 1.6.0-bete1.
בין השינויים הבולטים (רשימת שינויים עם תמונות):
* תמיכה במנויי רסס (לתורמים בלבד, כן – רק מי שתרם יקבל).
* שיפור ביצועים משמעותי מאוד.
* אפשרות לדפדף בטבלאת הכניסות האחרונות אפילו לדלג לתאריך
* אפשרות להקלטת כניסות באמצעות ג'אווה סקריפט, נסיוני.
* תמיכה בדשבורד של וורדפרס 2.5
* שיפורים בטבלאת ניהול האתרים : חיפוש, דיפדוף. שימושי בעיקר לאתרי WPMU עתירי בלוגים.

תיקוני באגים, ועוד כמה דברים קטנים.

רשימה מלאה של השינויים יש פה.

PHP4 מגיע לסוף החיים, אבל עדיין בשימוש של כ38% מהשרתים

שוחררה הגרסא האחרונה (ככל הנראה) בענף של PHP 4.4.
הגרסא הזו מסמנת את סוף התמיכה הרשמית בPHP4.
PHP5 כבר בחוץ במשך יותר משלוש שנים, אבל עד עכשיו האימוץ שלו היה די איטי, מסיבות של ביצה ודינוזאור:
מפתחי התוכנות לא רצו להפסיק לתמוך בPHP4 כדי לא לאבד משתמשים. חברות אירוח האתרים לא טרחו לשדרג כי כל התוכנות החשובות תמכו גם ככה בPHP4 והמשתמשים, מה איכפת להם?
בשנה שעברה נפתח אתר gophp5.org, ששם לעצמו למטרה לדחוף את האימוץ של PHP5.
הרעיון הוא שאם מסה מספיק גדולה של פרוייקטים תעבור לPHP5, ומסה מספיק גדולה של חברות אירוח תעבור לPHP5, לשאר חברות האירוח לא תהיה ברירה והן תאלצנה לשדרג או לאבד משתמשים, ואז לשאר הפרוייקטים לא תהיה סיבה להשאר בPHP4 והם יוכלו להתחיל סוף סוף לנצל את היכולות של PHP5.
בפברואר 2008 כבר היו מעל 100 פרוייקטי תוכנה שהתחייבו להפסיק לדאוג לתמיכה בPHP4 (זה לא אומר שהם ילכו וישברו את התמיכה בPHP4 בכוונה, פשוט שהם יפסיקו לדאוג שקוד חדש ירוץ בPHP4), ומעל 200 חברות איכסון שתומכות בPHP 5.2 כביררת מחדל וgophp5 טענו להצלחה והפסיקו לאסוף הרשמות.

אז למה לא לתמוך בPHP4? הנה דוגמא מאתמול:
JSON הוא דרך להעביר מבנה נתונים כלשהו לייצוג של מבנה הנתונים כאובייקט ג'אווה סקריפט, והוא אחת הדרכים הפשוטות והיעילות ביותר להעביר נתונים מקוד בצד השרת לדפדפן (שפשוט מפעיל על הטקסט שחוזר את המפסק (parser) של ג'אווה סקריפט כדי לקבל אובייקט מוכן לשימוש.
למרות שראשי התיבות של AJAX הן Asynchronous Javascript And XML, מעולם לא השתמשתי בAJAX כדי להעביר XML, למעשה אני מוצא את הרעיון מזעזע. הרבה יותר קל להעביר JSON, או אפילו קוד HTML ממש.
JSON משמש בהרבה מאוד פרוייקטים מבוססי AJAX, ומכיוון שאין בPHP4 תמיכה מובנית בJSON (אחרי הכל, PHP4 הוא בן שמונה, וJSON הוא די חדש בשכונה) צריך להשתמש בספריות חיצוניות שיודעות להעביר אובייקט PHP לפורמט JSON, אחת הספריות הנפוצות היא Services_JSON (למעשה אני משתמש בספריה הזו בFireStats).
הספריה כתובה בPHP, ולמרות שהיא עובדת נכון, היא לא ממש עובדת מהר, במיוחד כשממירים מבני נתונים גדולים (לא עצומים, משהו בסדר גודל של מערך עם 1000 אובייקטים טיפה מורכבים) לJSON.
ממש אתמול ניסיתי לשפר ביצועים של ישום PHP, אחרי חפירות גיליתי שאחד הדברים שמאטים מאוד את העסק היה המרה של תשובה לדפדפן לJSON בשימוש בServices_JSON, כשאני אומר איטי, אני מתכוון ל8 שניות.
שמונה שניות שהשרת טוחן את הCPU שלו כדי להכין תשובה ללקוח (במקרה הספציפי הזה, במקרים אחרים עם יותר נתונים זה כמובן יותר גרוע).
ברגע שראיתי את זה, לקח לי בדיוק שניה וחצי להיזכר שPHP5 תומך בJSON. בדיקה מהירה בphp.net הניבה את שתי הפונקציות הפשוטות json_encode וjson_decode. החלפתי את השימוש ב Services_JSON בקריאה לפונקציות של php5, ולא הייתי מופתע במיוחד לראות שהמרה של אותו מבנה נתונים לוקחת פתאום 40 מילישניות.
שיפור של פי 200, בזמן עבודה של כמה שניות (טוב, חוץ מלמצוא את הבעיה 🙂 )
השיפור נובע מכך שהתמיכה של PHP בJSON לא כתובה בPHP אלא בC, ולכן היא הרבה הרבה יותר יעילה.
השיפור הזה התאפשר רק כי הפרוייקט הספציפי הזה לא צריך לתמוך בPHP4.

מה אני אצטרך לעשות בFireStats, שעדיין תומך בPHP4 כדי להנות מהשיפור הזה? לבדוק אם אני על PHP5, ואם כן להשתמש בפונקציות האלו אחרת להשתמש בServices_JSON. לא כיף במיוחד.
ואם לא היתה לי סיפריה כמו Services_JSON (כי אין, או כי תנאי הרשיון לא מתאימים לי), הייתי נאלץ לכתוב אחת או פשוט לעבוד בצורה אחרת, פחות נוחה. גם לא כיף.

אז איך מתקדם האימוץ של PHP5?
החל מFireStats 1.3 ששחרתי לפני יותר משנה, FireStats מכילה רכיב ששולח (באישור המשתמש) מידע מערכת אנונימי. חלק מהמידע הוא גרסאות הPHP והMySQL.
הכוונה היא שאני אוכל להשתמש במידע הזה כדי להחליט בצורה יותר מושכלת במה אני צריך לתמוך.
המידע הצטבר לי בבסיס הנתונים, ונכון לכרגע יש לי מידע על כמעט 12000 התקנות. מה שאומר כמעט 12000 שרתים בעולים (אני מתעלם ממקרים של כמה התקנות על אותו שרת).
למי שתוהה, זה לא אומר שFireStats הותקנה 12000 פעמים, אלא ש12000 פעמים המתקינים הסכימו לשלוח מידע מערכת אנונימי.
מי שרוצה את המידע הגולמי מוזמן לקחת אותם מפה (יצוא MSQL, כ5 מגה דחוסים, 65 מגה פרושים).

אז ישבתי כמה שעות כדי להוציא מהנתונים הגולמיים שני גרפים נחמדים:
הראשון הוא אחוזי ההתקנות של PHP 4 מול PHP 5, במהלך השנה האחרונה.
למרות שאחוזי ההתקנה של PHP4 ירדו במהלך השנה האחרונה מ52% ל38%, עדיין מי אי אפשר להתעלם ממנו. נקווה שהוא ימות סופית בקרוב:
installed php versions
השני הוא אחוזי ההתקנות של הגרסאות המשמעותיות של MYSQL:

כיף לראות שMYSQL 5.0 שולט בשוק, אבל נראה שMYSQL 4.0 הזוועתי נתקע על 7% ולא רוצה למות.
בכל מקרה, MYSQL 4.0 הוא בהחלט מועמד לנטישה, וכבר היום יש לא מעט תכונות חשובות של FireStats שלא נתמכות בגרסא הזו.
installed mysql versions

משתמש תרם שיפורי ביצועים משמעותיים לIP2C

אם יש משהו שאני אוהב בפרוייקטי קוד פתוח, זה שאנשים מוכנים לפעמים לעבוד די קשה כדי לשפר אותם.
את IP2C, ספריה למציאת המדינה של כתובת IP שחררתי לפני כמעט שנתיים, וכתבתי גם פוסט שמספר על המימוש שלה פה.
IP2C ממומשת בPHP ובג'אווה. מה שמיוחד בה זה שהיא מסוגלת לחפש ישירות על הקובץ, מה שאומר שחיפוש בודד הוא מאוד מהיר כי לא צריך להעלות את כל הקובץ לזכרון.
הייתי לגמרי מרוצה מהביצועים של הספריה בPHP (כ1200 חיפושים בשניה במחשב האחרון שמדדתי), אבל הביצועים בג'אווה היו טובים יותר משמעותית – כ8000 חיפושים בשניה על אותו מחשב בעבודה ישירות על קובץ הנתונים.
ההבדל בביצועים בין PHP לג'אווה לא הטריד אותי, כי היה לי ברור שPHP תהיה יותר איטית מג'אווה, אבל הוא כן הטריד את תומס רומר שהתיישב על העסק לילה שלם ושיפור את הביצועים של גרסאת הPHP ב150%.
תומס כתב פוסט מעניין על השינויים שהוא עשה, ושלח לי את השינויים. שבמבט ראשון נראים טובים ואני אקלוט אותם לפרוייקט אחרי בדיקה מעמיקה יותר.

בנוסף דיברנו קצת בIRC, והוא יעבוד על תמיכה בבסיס הנתונים של software77 :
software77 מספקים בסיס נתונים של IP למדינה, שאמור להיות יותר איכותי מבסיס הנתונים שIP2C משתמשת בו כרגע (webhosting.info), אבל יש להם קצת בעיות בעקביות המידע.
התחלתי לעבוד על תמיכה בבסיס הנתונים שלהם לפני כמה חודשים טובים, אבל כשראיתי שזה נמשך יותר מדי הקפאתי את העסק (שעדיין נמצא בTODO שלי, קבור איפשהו 🙂 )
תומס ימשיך מאיפה שהפסקתי.

FireStats 1.5

בשעה טובה, פיירסטטס 1.5 הגיע לגרסא יציבה עם השחרור של 1.5.11-stable.
שדרגו בהמוניכם 🙂

MySQL optimization

לפני כמה שבועות פרסמתי פוסט על אופטימיזציות.
הנה ההמשך.
דוגמא מעשית, שיפור ביצועים של שאילתות בFireStats (לגרסא 1.6)
מנגנון מקובל לשיפור ביצועים הוא מטמון (cache). הרעיון פשוט : בפעם הראשונה ששואלים אותנו משהו אנחנו מחשבים אותו וזוכרים את התוצאה. בפעם השניה אנחנו משתמשים בתוצאה שחישבנו קודם.
כשבודקים ביצועים, חשוב לוודא שהבדיקה נותנת תוצאות זהות בשתי הרצות שונות. במקרים רבים יש מנגנוני מטמון יגרמו לבדיקה לרוץ הרבה יותר מהר בפעם השניה, ובדרך כלל הם רק מפריעים בסיטואציות של בדיקת ביצועים כי אנחנו רוצים למדוד את השיפור שנובע מהקוד שלנו, ולא מזה שהCache הכיל את התוצאה שכבר חישבנו בהרצה הראשונה.
דוגמא לכך היא הCache של MySQL: ההרצה השניה של שאילת תמיד תהיה הרבה יותר מהירה מההרצה הראשונה, כי MySQL זוכר את התוצאות מהפעם הראשונה ואם שום דבר בנתונים לא השתנה הוא פשוט מחזיר את אותה תוצאה.

כדי לבטל את אותו Cache, אפשר להשתמש בפקודת הMySQL:
[code lang="sql"]
SET GLOBAL query_cache_size = 0;
[/code]

FireStats תומך בגרסאות MySQL ממשפחת 4.0, 4.1 ו5.0, כאשר ההבדל בין 4.0 ל4.1 כל כך משמעותי שיש שאילתות בFireStats שכתובות אחרת לכל אחת מהגרסאות.
נסיון לשיפור ביצועים, במיוחד כזה שמבוסס על שינויים בסכמת הנתונים יצריך שינויים בקוד שמטפל ב4.0 ובקוד של 4.1, לכן כדאי לבדוק שהכל עובד על השרת הרלוונטי. בנוסף, מכיוון שרוב (60%) משתמשי FireStats עובדים עם MySQL 5.X, כדי גם לבדוק את השיפור על השרת הזה.
כדי לבצע את זה, הרמתי שלושה שרתי MySQL, נציג אחד מכל משפחת גרסאות, והכנסתי לכל שרת חבילת נתונים די כבדה (וזהה בין השרתים) שמבוססים על סטטיסטיקות מהשרת שלי.
ובכל אחד מהשרתים ביטלתי את מטמון השאילתות (query_cache_size).
יצרתי טבלא בגנומטיק (כמו אקסל), שנראית ככה (תת טבלא כזו לכל בדיקה שאני רוצה)
fs-opt.jpg

נניח שהפונקציה שאני רוצה לשפר היא:
[code lang="php"]
function foo()
{
$sql = "SELECT * from …";
return query($sql);
}
[/code]

קודם כל הכפלתי את הקוד והוספתי הדפסה של שאילת הSQL שנשלחת לשרת:
[code lang="php"]
function foo()
{
if (true) // old code
{
$sql = "SELECT * from …";
echo $sql; return;
return query($sql);
}else{
$sql = "SELECT * from …";
echo $sql; return;
return query($sql);
}
}
[/code]
מכאן זו היתה שיטת העבודה:
1. הרצה של הקוד במצב הישן.
2. העתקה של השאילתה שהודפסה, והרצה שלה ישירות על כל אחד משלושת בסיסי הנהנתונים. ושמירה של הזמן שנדרש בטבלא מסודרת.
3. מעבר למצב חדש (פשוט לשנות את הfalse לtrue בראש הפונקציה), אופטימיזציה של השאילתה וחזרה על הבדיקה מול כל אחד מהשרתים, ושוב שמירה של התוצאות בטבלא, הפעם בעמודה של תוצאות אחרי אופטימיזציה.

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

אז מה בעצם עשיתי?
פיירסטטס תומך בכמה אתרים בו זמנית, ולכן יש בו מזהה אתר. בהתחלה שמרתי את מזהה האתר בטבלאת הכניסות, בשלב מסויים הבנתי שאני צריך מזהה אתר גם בטבלאת הכתובות (URLים), כי הרי כל URL שיך לכל היותר לאתר אחד.
אז הוספתי את העמודה, אבל שכחתי למחוק את העמודה מטבלאת הכניסות.
מצב כזה של כפילות נתונים הוא לא מומלץ לפי הגישה המקובלת בתכנון בסיסי נתונים, כי הוא מאפשר מצבים של חוסר עקביות במידע.
באחת הגרסאות האחרונות של פיירסטטס תיקנתי את המעוות: הסרתי את העמודה מטבלאת הכניסות ותיקנתי את כל הקוד שהושפע מזה לבצע join עם טבלאת הכתובות כשהוא צריך גישה לאתר.
על פניו הדבר הנכון לעשות: אבל זה יצר בעיה חדשה:
כמעט כל השאילתות דרשו עכשיו join נוסף. עבור משתמשים עם בסיסי נתונים קטנים (נניח עד חצי מליון כניסות בטבלאת הכניסות ועד 50 אלף כתובות בטבלאת העסק עבד סביר, אבל עבור משתמשים עם בסיסי נתונים גדולים יותר העומס על השרת התחיל לגדול בצורה חדה ככל שנפח הנתונים עלה.
הפתרון שלי הוא לחזור בי מהדבר "הנכון" שעשתי קודם, כלומר להחזיר את עמודת הsite_id לטבלאת הכניסות, שתשמש לצרכי פילטור בזמן השאילות כדי להמנע מהjoin עם טבלאת הכתובות.

שיפור נוסף נבע משינוי מבני של השאילות ככה שיעבדו בצורה יותר יעילה.
כדי לעשות את זה, חשוב להבין מה עושה בסיס הנתונים כדי לחשב את השאילתה.
לשם כך אפשר להשתמש בפקודה explain, שמחזירה תיאור של האסטרטגיה שבה בסיס הנתונים יחשב את התוצאות.
explain מחזיר תוצאות די קריפטיות, לא משהו שתבינו בלי לקרוא את התיעוד.
בכך מקרה, חשוב לשים לב לעובדות הבאות:
בכל שלב, MySQL משתמש באינדקס אחד בלבד לכל היותר (אם יש אינדקס מתאים). ככל שהאינדקס יהיה יותר ספציפי ככה הביצועים יכולים להיות טובים יותר.
(יתכן שגרסאות עתידיות של MySQL ידעו להשתמש בכמה אינדקסים בשלב, אבל לדעתי זה עדיין לא פה).

ככה נראית הטבלא שלי אחרי שמילאתי אותה:

Query name MySQL Version 4.0.17 4.1 5.0.51
Num page views for all hits in site=1 Original query time sec 1.20 0.93 0.84
Optimized query time sec 0.10 0.06 0.06
Improvement % 91.67% 93.55% 92.86%
Num page views for all hits in all sites Original query time sec 1.17 0.91 0.84
Optimized query time sec 0.11 0.08 0.08
Improvement % 90.60% 91.21% 90.48%
Num page views for for last last 14 days for all sites Original query time sec 0.19 0.16 0.16
Optimized query time sec 0.12 0.09 0.11
Improvement % 36.84% 43.75% 31.25%
Num all unique visitors for site_id = 1 Original query time sec 2.93 1.24 1.13
Optimized query time sec 1.75 0.68 0.72
Improvement % 40.27% 45.16% 36.28%
Num all unique visitors for all sites Original query time sec 2.09 1.24 1.15
Optimized query time sec 1.26 0.47 0.47
Improvement % 39.71% 62.10% 59.13%
Num unique visitors for last 14 days for all sites Original query time sec 0.32 0.18 0.18
Optimized query time sec 0.28 0.16 0.15
Improvement % 12.50% 11.11% 16.67%
Recent referrers for all sites Original query time sec 2.54 3.01 3.01
Optimized query time sec 2.30 1.54 1.78
Improvement % 9.45% 48.84% 40.86%
Recent referrers for site_id = 1 Original query time sec 2.48 2.71 2.76
Optimized query time sec 2.65 1.65 1.90
Improvement % −6.85% 39.11% 31.16%
Search terms for site_id = 1 Original query time sec 1.67 2.14 2.75
Optimized query time sec 1.67 0.84 0.91
Improvement % Not optimized 60.75% 66.91%
Popular pages (all) Original query time sec 1.88 4.67 4.80
Optimized query time sec 1.73 1.96
Improvement % Not optimized 62.96% 59.17%
Popular pages (site_id = 1) Original query time sec 1.93 4.07 4.09
Optimized query time sec 1.88 2.11
Improvement % Not optimized 53.81% 48.41%
get questagents (180 days, site_id = 1) Original query time sec 6.89 2.90 2.35
Optimized query time sec 5.07 1.00 1.10
Improvement % 26.42% 65.52% 53.19%
Countries (20 countries, 180 days, site_id = 1) Original query time sec 1.95 1.08 1.08
Optimized query time sec 0.30 0.20 0.23
Improvement % 84.62% 81.48% 78.70%
Hits table (100) Original query time sec 0.30 0.61 0.42
Optimized query time sec
Improvement % Not optimized Not optimized Not optimized