אני מתקין בימים אלה עבור לקוח ביוון שרת Reverse caching proxy,
הלקוח מפעיל אתר חדשות על בסיס WordPress עם mysql, php-cgi ו-Apache, ויש המון קפיצות תעבורה פתאומיות (מ-350 בקשות בשנייה ל-1800), בנוסף יש לגולשים אפליקציה שמקבלת את הנתונים מהאתר באמצעות XML.
השרת של הלקוח נחנק מספר פעמים ביום עקב העומס, הצעתי לו שאני אתקין את Nginx לפני Apache וש-Nginx ישמור דפים דינאמים ו-XML במשך 3 דקות למשתמשים בלי עוגייה ובנוסף יגיש את התוכן הסטטי ישירות מה-HD.
התוצאה: כרגע (שעת הלחץ של האתר) יש 2500 איש באתר שמחוברים מ-PC, ועוד 10,000 בקשות בדקה ל-XML שונים, ה-Load avarage עומד על 0.55, ו-Apache מקבל בסה"כ 100 בקשות בדקה (לפני ההתקנה המספר הזה עמד על 5 ספרות).
יש לכם אתר עם עשרות אלפי מבקרים בדקה, אתם מפעילים שרת Reverse Proxy עם Cache ויש לכם בממוצע 50 אלף איש באתר בדקה, נניח שתוקף העמוד הראשי פג (Cache-Control) ויש 5000 בקשות לדף הבית באותו רגע, ללא קינפוג נכון של שרת ה-Reverse Proxy, כדי לרענן את דף הבית השרת יעביר את כל הבקשות לשרתי ה-Backend, שרתי ה-Backend לא יכולים לעמוד בעומס כזה ולכן ייתקעו, כמה שניות לאחר מכן שרת ה-Reverse Proxy יעביר עוד אלפי בקשות ל-Backend התקוע ויתחיל להחזיר אלפי הודעות שגיאה עם Proxy read timeout למאות הבקשות הראשונות והמרחק מכאן לקדחת לא רחוק בכלל.
בדיוק בשביל זה יש את proxy_cache_lock, במקרה שיש מספר בקשות קובץ/דף ספציפי באותו הזמן, Nginx יחזיק את כל הבקשות בהמתנה ויעביר בקשה אחת בלבד אחורה ל-Backend, כאשר הפלט של הבקשה יתקבל, Nginx ישמור את הבקשה ב-Cache ויעביר את הפלט לכל אותם אלפי הבקשות שבהמתנה.
לפני מספר ימים כתבתי על האצת אפליקציה על גבי שימוש ב-Reverse Proxy, הפתרון יעיל כמו CDN (ועולה רבע מהעלות של CDN) ומאפשר לשמור על גמישות מבחינת הפעלת המערכת (לדוגמא – הטמעת Memcached בעתיד),
בפרויקט אני משתמש ב-Nginx (הלחם מילים של Engine-X), אבל ל-Nginx יש חיסרון אחד כ-Reverse Proxy, הוא לא תומך ב-KeepAlive, ולכן כל פניה לשרת המקור, דורש פתיחת חיבור TCP חדש וככל שהמרחק הפיזי בין שרת ה-Reverse Proxy לשרת המקור גדל כך זמן פתיחת חיבור ה-TCP.
כדי לתאר איך עובד KeepAlive – תחשבו על צינור מים של 10 מטר:
ללא KeepAlive – הצינור מתרוקן בין פעילות לפעילות ועוברות מספר שניות מרגע פתיחת הזרם (פתיחת החיבור) עד ליציאת המים בקצה הצינור (תחילת הגעת המידע – TTFB).
עם KeepAlive – בין פעילות לפעילות עוברים בצינור כמות מזערית של מים, כדי שבעת פתיחת הברז מיד יצאו המים.
כדי לייעל את ה-Reverse Proxy, הקמתי SSH Tunnel בין ה-Reverse Proxy לשרת המקור, SSH Tunnel יוצר חיבור (מוצפן) בין שני השרתים והחיבור הזה מתפקד (במקרה הזה) כתחליף ל-KeepAlive, כאשר ה-Reverse Proxy משתמש בחיבור הקיים של ה-SSH Tunnel ומעביר דרכו את הבקשות לשרת המקור.
כדי להציג את ההבדלים בין SSH Tunnel לחיבור ישיר, הקמתי שרת Reverse Proxy ע"ג Nginx בשרת בקנדה ופתחתי SSH Tunnel בין השרת בקנדה לשרת נוסף בישראל כאשר ה-Caching מבוטל (כל בקשה מועברת לשרת המקור בישראל):
הערה: מדובר ב-2 בקשות זהות, לקובץ במשקל של 5Kb, בקשה אחת ב-HTTP והנוספת ב-HTTPS SSL
באמצעות חיבור ישיר:
הזמן שעובר משליחת הבקשה עד לקבלת הביט הראשון (TTFB) בבקשת HTTP רגילה: 660MS.
הזמן שעובר משליחת הבקשה עד לקבלת הביט הראשון (TTFB) בבקשת HTTPS מוצפנת: 760MS.
Reverse Proxy Over SSH Tunnel:
הזמן שעובר משליחת הבקשה עד לקבלת הביט הראשון (TTFB) בבקשת HTTP רגילה: 310MS.
הזמן שעובר משליחת הבקשה עד לקבלת הביט הראשון (TTFB) בבקשת HTTPS מוצפנת: 400MS.
שימו לב להבדל, בזמני ה-TTFB:
ב-HTTP, שימוש ב-SSH Tunnel השיג שיפור של 350MS, שיפור של 53%!
ב-HTTPS, שימוש ב-SSH Tunnel השיג שיפור של 360MS, שיפור של 52%!
לסיכום, ניתוב בקשות שרת Reverse Proxy דרך SSH Tunnel משפר ביצועים פי 2, עכשיו נותר רק לבדוק את אחוז השיפור עם 100 בקשות בשנייה (SSH Tunnel מצפין את התוכן ולכן יש זמן מעבד המושקע בהצפנה).
אני כותב אפיון לאפליקציה חדשה שאני מתכנן לסמארטפונים, האפליקציה היא בינלאומית ואמורה לשלוף נתוני XML מהשרת במהירות האפשרית באמצעות API בעת פעולה מסוימת (אני לא יכול לחשוף במה מדובר, אבל נניח שמדובר בהצגת התחזית בעיר מיד בעת צלצול שעון מעורר).
בגלל שמדובר רשת סלולרית, ה-Latency גבוה ולכן יש חשיבות גדולה מאוד ל-API מהיר במיוחד. בנוסף, ה-API חייב להכיל Secure Token כדי להגן על מסד הנתונים מפני שימוש בלתי מורשה/הצפה של המערכת וכדי להגן על משתמש האפליקציה (מהסביבה שלו) בעת שימוש ב-WIFI כל המידע יעבור דרך SSL.
"אז מה הבעיה? תשתמש ב-CDN"
יש כמה סיבות למה לא כדאי להשתמש ב-CDN:
השימוש ב-SSL יצרוך תעבורה נוספת והעלות תהיה גבוהה עוד יותר.
מדובר בפרויקט לטווח ארוך ובמידה והאפליקציה תצליח, העלויות הגבוהות של שימוש ב-CDN יגמרו את כל התקציב לפני שהפרויקט יגיע לאיזון כלכלי.
כמעט שום חברת CDN לא מאפשרת שימוש ב-Secure token, בודדות החברות שכן (הן דורשות SSL ועוד 200$~ כל חודש בשביל האפשרות הזאת) ואני לא מעוניין בחתונה קתולית עם שום חברה.
כבר היום יש לי שרתים בארה"ב ובאירופה שניתן להשתמש בהם.
בעתיד אני יכול להשיג ביצועים טובים יותר באמצעות הטמעת Memcached במערך (שכפול המסד ל-Memcached ופיזור הנתונים ב-3 שרתי Memcached – שרת בכל יבשת).
הפתרון: שימוש בשרתי GeoIP Reverse proxy עם Secure Tokens:
שרת ה-WEB הראשי ומסדי הנתונים יישבו בישראל, (כדי להפעיל את השירות בצורה מיטבית אני צריך שרתי Daemon הפזורים ב-3 יבשות (בנקודות הביקוש הגדולות ביותר), השרתים צריכים לתמוך ב:
HTTPS (תמיכה ב-SSL).
Reverse Proxy & Cache.
שרת קליל שיכול לעמוד בעומס של המון בקשות.
Secure tokens.
שינוי קונפיגורציה ללא Restart.
לסיכום:
ה-Reverse proxy היעיל ביותר שתומך בכל הפונקציות האלו הוא Nginx ולכן גם אשתמש בו לפרויקט, לצערי הוא לא השרת המהיר ביותר, Varnish יכול לטפל בעשרות אלפי בקשות בשנייה, אבל Varnish לא תומך ב-Secure tokens וב-SSL).
אני עובד בימים אלה על אפיון אפליקציה חדשה לסמארטפון, האפליקציה יוצרת קשר עם השרת מעת לעת ונושא הביצועים חשוב מאוד, כמו כן, כדי להגן על המשתמש (מהסביבה שלו), כאשר המשתמש מחובר באמצעות WIFI החיבור מתבצע באמצעות SSL.
בגלל שנושא הביצועים מאוד חשוב באפליקציה מהסוג הזה, אני מבצע מספר בדיקות ביצועים בצד ה-Backend לבדיקת תפקוד השרת בזמנים עמוסים כחלק מכתיבת האפיון. צד השרת רץ על VPS בארה"ב, באמצעות Nginx עם Secure links (שימוש באסימון – Token) כאשר כל הנתונים נמשכים באמצעות Reverse proxy משרת Apache בישראל ונשמרים ב-Cache ל-8 שעות.
הנתונים שמוצגים בגרף הם טעינה של 18 אלמנטים, כולם ב-Cache, ב-3 מצבים שונים (מימין לשמאל):
כאשר יש פנייה מגולש אחד מהאפליקציה לשרת.
כאשר יש פנייה מ-100 גולשים באפליקציה לשרת.
כאשר יש פנייה מ-250 גולשים באפליקציה לשרת.
מפל המים מורכב ממספר אלמנטים:
האלמנט הראשון הוא קובץ טקסט שמכיל 17 קישורים שונים לאותו הקובץ, קריאה אחת ב-HTTP, קריאה שאחריה ב-HTTPS וחוזר חלילה.
אלמנטים 2-17 הם אותו הקובץ שנטען כל פעם מחדש.
אלמנט 18 הוא קובץ favicon.ico.
שימו לב למסקנות המפתיעות:
בקפיצה ממשתמש 1 ל-100, זמן הקריאה ב-HTTP גדל ב-100MS בממוצע, זמן הקריאה ב-HTTPS גדל פי 2 בממוצע.
בקפיצה מ-100 משתמשים ל-250 משתמשים, זמן הקריאה ב-HTTP גדל ב-30MS בממוצע, זמן הקריאה ב-HTTPS גדל ב-30MS בממוצע. – גידול של פי 1.5 בכמות הבקשות, אך זמן הקריאה גדל ב-30MS בממוצע.
בקפיצה ממשתמש 1 ל-250, זמן הקריאה ב-HTTP גדל פי 1.2 בממוצע, זמן הקריאה ב-HTTPS גדל פי 2.1 בממוצע.
Nginx בקושי העמיס על ה-VPS, לא ניצל את כל המעבד, וזה דיי מפתיע, עדיף NGINX מעמיס ומהיר מאשר NGINX קליל ואיטי.
הערה: בדיקות מפלי המים בוצעו באמצעות Webpagetest.org, בדיקות העומס בוצעו באמצעות Blitz.io.
בפוסט הבא אני רוצה להציג פתרון לבעיה שקיימת בהרבה אתרים, כשה-Time to first byte (הזמן העובר מתחילת החיבור לשרת עד שהביט הראשון נשלח מהשרת לדפדפן) גבוהה מדי.
היחס הממוצע בזמן המושקע בגלישה בעמוד בין ה-Backend (השרת מייצר את התוכן) ל-Frontend (הדפדפן מוריד את התוכן ופורס את העמוד) עומד על 20%/80%. כלומר, אם דף הבית (הדף עצמו, ללא תמונות/JS וכו') נטען תוך 2 שניות, 400 מילישנייה מוקדשים ליצירת העמוד.
הזמן האופטימלי ל-TTFB הוא 200 מילישנייה, אבל, כאשר באתר שלך יש:
שאילתות SQL מורכבות.
שאילתות SQL שלא כתובות כהלכה – לדוגמא: Order by rand().
שימוש ב-API בתוך הקוד (ה-TTFB של ה-API מאט את יצירת העמוד).
קוד בעייתי (sleep?).
יצירת העמוד מתעכבת, ובזמן הזה שהדפדפן ממתין לקבלת הדף, לא מתבצעת שום פעולה נוספת בצד הדפדפן, למעט בזבוז זמן.
כדי לייעל את טעינת העמוד, אנו מעוניינים לשלוח לדפדפן את ה-Header בזמן שהשרת ממשיך ביצירת ה-Body וה-Footer , בזמן הזה, הדפדפן כבר יוריד/יטען מה-Cache את קבצי ה-CSS, JS, תוספים חברתיים וכו' המופיעים ב-Header וטעינת האתר ופריסתו תהיה מהירה יותר.
כדי לשלוח את ה-Header, נשתמש בפונקציה Flush, ונמקמה בתחתית ה-Header – כדי לשלוח כמה שיותר תוכן לדפדפן.
איך זה נראה בפועל?
כדי להציג את ההבדלים בין שימוש ב-Flush לבין עבודה ללא Flush, אציג את השינוי באתר Fmylife.co.il (אתר Development לפרויקט עתידי).
כמה מילים על Fmylife: הסקריפט בנוי ב-PHP, הטמפלייט ב-Smarty, ביצעתי מס' תיקונים ושינויים בסקריפט, בנוסף, מאחר ומדובר בסקריפט "חברתי" (במערכת יש שימוש ב-Google plus, FB Like ו-Twitter), האתר נטען תוך 6 שניות בממוצע (תלוי במצבי רוח של טוויטר).
זמן טעינת עמוד הבית ללא פונקציית Flush:
מקרא:
כתום – יצירת חיבור.
ירוק – TTFB.
כחול – זמן הורדה.
קו ירוק (בצמוד ל-1.2) – תחילת פריסת העמוד בדפדפן)
מבחינת ביצועים המצב לא מושלם, זמן ה-TTFB עומד על 500 מילישנייה ותחילת טעינת CSS הוא לאחר 700 מילישנייה מטעינת דף הבית, הדפדפן מתחיל לפרוס את העמוד לאחר 1.1 שנייה מתחילת הטעינה (מומלץ לסיים את טעינת הדף תוך 2 שניות). בשורה התחתונה – יש מה לשפר.
שימו לב להבדל, קודם, ללא Flush, אלמנט ה-CSS מתחיל להיטען בסביבות 0.72, עם Flush, הטעינה מתחילה ב-0.22, כחצי שנייה קודם לכן, אומנם זמן טעינת העמוד הוא כמעט אותו הדבר (ואם אני אחזור על הבדיקה 100 פעם, לפחות ב-20 השוואות שני העמודים ירדו באותו הזמן), אך הדף עם Flush נטען מוקדם יותר ומהר יותר כפי שתראו בפסקה הבאה.
השוואה בין שני המצבים
הסרטון הבא מציג את טעינת FMyLife ב-2 מצבים, בצד שמאל – באמצעות Flush, ובצד ימין, ללא Flush. טעינה מלאה של שני המצבים לוקחת אותו הזמן (בגלל טוויטר, FB וגוגל פלוס), אך שימו לב לטעינת התוכן בדף, בטעינה עם Flush תוכן האתר נטען מהר יותר.
לסיכום:
בפוסט הזה הצגתי שיפור של חצי שנייה בטעינת התוכן באמצעות הוספת שורה אחת ב-PHP בסוף ה-Header:
flush();
וב-Smarty:
{php}flush();{/php}
תכננו מראש את האתר שלכם לשימוש נכון בשאילתות SQL, קבלת נתונים מ-API חיצוני ע"י AJAX ובכלל, בנו אתר יעיל.
בעקבות הפיגוע בבורגס בשבוע שעבר, אתר רוטר לא עמד בעומס הגולשים ולא עבד לפרקים, לאחר מכן, ביום חמישי האחרון (ה-19/7) עלתה בפורום הסקופים של רוטר (עליו כתבתי בעבר) הודעה, אחד הגולשים קרא את הפוסט בבלוג הזה וכתב עליו ונתן קישור לבלוג בפורום, בפורום רוטר התפתח דיון והיו למעלה מ-13000 צפיות להודעה בפורום רוטר.
מתוך 13,000 צפיות, 420 איש נכנסו לפוסט בבלוג וקראו אותו, מצ"ב קישור לסטטיסטיקות הבלוג בשבוע האחרון:
בהמון אתרים ישראלים אני רואה שוב ושוב שימוש מיותר בטעינת תוספים חיצוניים או טעינת מחלקת jquery, נפריד בינהם:
jquery:
מדובר בספריית הכתובה ב-javascript (ולכן טעינה שלה מעכבת את רינדור שאר העמוד/הורדת תכנים נוספים) שמאפשרת שימוש נרחב יותר ב-javascript, המון אתרים משתמשים ב-google לטעינת הספרייה וזה טוב:
לגוגל יש תשתית שרתים חזקה ומהירה (TTFB נמוך).
בגלל השימוש הנרחב על ידי הרבה אתרים המון פעמים הקובץ כבר נמצא ב-cache של הגולש וכך בעצם, הקובץ נטען מהמחשב וטעינת העמוד מהירה יותר.
ויש גם חסרונות:
במידה וגוגל עמוסים או לא מתפקדים (לעיתים רחוקות מאוד) מדובר בנקודת כשל שתתקע את כל האתר (SPOF).
במידה וטוענים את הקובץ מגוגל, גם אם נחבר את יתר קבצי ה-JS לקובץ אחד, עדיין יהיו 2 בקשות לקובצי JS.
הטעות שהרבה בעלי אתרים עושים, הם טוענים את הקובץ באמצעות HTTPS, ניתן לטעון את הקובץ באמצעות HTTP ואין שום השפעה על האתר אם נעשה כך. ההבדל בין HTTPS ל-HTTP (מלבד ההצפנה) היא שחיבור SSL לוקח בין 100-250 מילישניה יותר מחיבור HTTP ולכן חיבור HTTPS הוא איטי
יותר.
תוספים חברתיים:
את התוספים הנפוצים ביותר (plusone.js של גוגל, all.js של פייסבוק ו-widgets.js של טוויטר) ניתן לטעון גם באמצעות HTTP וגם באמצעות HTTPS, השימוש ב-HTTPS נועד לאפשר טעינת התוספים באתרים מאובטחים (לדוגמא: בחנות שסולקת כרטיסי אשראי), שימוש ב-HTTPS באתר שלא דורש תקשורת מאובטחת, הוא מיותר ומאט את האתר.
לסיכום:
במידה ואינכם דורשים מהגולשים שלכם לעבוד בסביבה מאובטחת, טעינת קבצי Javascript באמצעות HTTPS היא מיותרת.
עריכה 03/06/2013: שנה אחרי שכתבתי את הפוסט, חל שיפור עצום במערכות של רוטר והיום האתר עובד מהר יותר ונכון להיום, הפוסט הזה לא רלוונטי לאתר רוטר.
פורום הסקופים של רוטר הוא פורום הנותן במה לגולשים ולעיתונאים ברחבי הארץ לפרסם מידע ראשוני, חדשות וסקופים אודות אירועים בארץ ובעולם, בגלל שהתוכן מוזן ע"י הגולשים, הוא מקדים בהרבה את כל אתרי החדשות בארץ.
הפורום משתמש בסקריפט DC Forum, בגירסת ה-PERL (יש גם גירסת PHP), זה סקריפט מיושן (אם כי בעבר היתרון שלו על פורמים אחרים היה שאת הפוסטים עצמם הסקריפט שומר כ-HTML ללא קריאות ל-SQL וכו'), עם לא מעט באגים (פוסטים מאוד מבוקשים עם הרבה פעולות כתיבה פשוט קורסים ונעלמים), למרות זאת, המפעיל של האתר, לא ממהר להחליף את המערכת/עיצוב ומסביר כי: "מה שעובד לא מחליפים."
אחד החסרונות הבולטים של האתר, כשיש אוסף של אירועים (כמו, מתקפת קסאמים, מבצע צבאי או מלחמה), האתר פשוט לא מגיב, הוא קורס תחת העומס, בגלל שמאות גולשים מרעננים את האתר עשרות אלפי פעמים ביום.
עברתי על האתר כדי לנסות ולבדוק איפה אפשר לצמצם את העומס על השרת בלי להשקיע מאות שעות עבודה של מתכנתים:
Time To First Byte:
ה-TTFB של עמוד הסקופים לאורחים עומד על 900 מילישנייה, הזמן הזה מורכב מ:
Apache מנתח את הבקשה.
מפעיל פרוסס perl.
הפרוסס מעבד את הקובץ ע"פ הפרמטרים שהתקבלו ומעביר את הפלט ל-Apache.
Apache מעביר את הפלט לגולש.
אני מניח שעיקר הזמן מושקע בשליפת הפוסטים, אין טעם לבצע את הפעולה כל פעם מחדש (במיוחד כשיש רגעים שיש 800 בקשות בשנייה), אפשר לייצא את פלט הפוסטים לקובץ סטטי ולעדכנו כל 2 שניות למשתמשים רשומים וליצור קובץ נוסף המכיל את כל העמוד לאורחים, ולעדכנו כל 3 שניות.
KeepAlive:
כתבתי על הפונקציה הזו בעבר, בקצרה, הפונקציה מאפשרת להשתמש באותו החיבור בין הגולש לשרת כדי להוריד קבצים נוספים, ברוטר, הפונקציה הזו מבוטלת. לכן, כל פעם שגולש מבקש את העמוד הראשי הוא יוצר 51 חיבורים לשרת, 51 פרוססים של Apache. במידה ורוטר יפעילו KeepAlive בשרתים שלהם, גולש ב-IE8 יפתח 6 חיבורים בלבד להורדת האלמנטים. 45 פרוססים פחות.
Gzip (דחיסת HTTP):
כתבתי על הפונקציה הזו בעבר, בקצרה, כדי לצמצם את התעבורה ברשת ולאפשר טעינה מהירה יותר, השרת דוחס את הפלט ומעביר פלט דחוס לגולש. יש כאלה שחוששים להפעיל את הפונקציה בגלל ההשפעה של הפעולה הנוספת על המעבד, אין ממה לחשוש ומי שרוצה להגדיל ראש יכול לדחוס אלמנטים מראש (ע"י שימוש ב-gzip_static ב-nginx לדוגמא).
המשקל של פורום הסקופים עומד בממוצע על 80KB, במידה וה-Gzip יופעל, התעבורה בין השרת לגולש תעמוד על 12KB, חסכון עצום של 68KB.
הנה השוואה בין זמן טעינת הפורום עם אופטמזציה שלי למול הפורום:
מקרא:
כתום – יצירת חיבור.
ירוק – TTFB.
כחול – זמן הורדה.
הורדת הקובץ עם דחיסה: 80 מילישנייה.
הורדת הקובץ ללא דחיסה: 500 מילישנייה.
סה"כ שיפור: 420 מילישנייה בממוצע.
Cookieless domain:
כשגולש מבקש את העמוד הראשי ה-Header כולל 2 שורות Set-Cookie, מעתה, בכל בקשה נוספת לדומיין rotter.net, הגולש ישלח את הפלט Set-Cookie שהתקבלו בבקשה הראשונה, מדובר בתעבורה מיותרת לכל בקשות הקבצים הסטטים. אם נשתמש בכתובת אחרת לטעינת האלמנטים (או נגביל את ה-Cookie ליעד ספציפי), נחסוך תעבורה ונקבל זמן טעינה מהיר יותר.
Cache-Control:
כתבתי על Cache-Control בעבר, הפונקציה הזו מאפשרת לשרת להודיע לדפדפן בעת בקשת קובץ, לשמור את הקובץ במחשב ולא להוריד אותו שוב מהשרת למשך X שניות (יום/שבוע/חודש/שנה – תלוי מתי הקובץ מתחדש).
שימוש ב-Cache-Control יחסוך את טעינת כל 50 האלמנטים הסטטים באתר כאשר גולש מרענן את עמוד הסקופים, מדובר בחיסכון משאבים אדיר.
השוואה בין רוטר לאופטמזציה שלי:
הורדתי את פורום הסקופים לשרת שלי, וביצעתי את כל השינויים שכתבתי, הנה השוואה בין טעינת העמוד מישראל עם IE8 ומטמון ריק של פורום הסקופים והשרת שלי:
*** בעת ביצוע ההשוואה בוטלו כל הפירסומות.
בעזרת יישום הסעיפים שציינתי קודם, פורום הסקופים של רוטר יכול להיטען 2 שניות מהר יותר. שיפור שכזה יקטין את אחוז הנטישה, והגדלת הכנסות לבעל האתר.