Browse by Tags
All Tags »
Performance (
RSS)
כשבאים לנתח ביצועים של אפליקציית Managed, ורוצים להבין מה הם צווארי הבקבוק שעשויים להכשיל אותה בתרחישי עומס איתם היא אמורה להתמודד, אחד הפרמטרים החשובים שצריך לשים לב אליהם הוא מידת הזמן שהאפליקציה שלנו מבלה ב-GC. בשביל לדעת את זה, תמיד אפשר להריץ במקביל לאפליקציה את Perfmon ולקבל ניתוח כללי של התנהגות ה-GC באפליקציה שלנו, כשהמדד העיקרי שנסתכל עליו בדרך כלל הוא אחוז ה-Time in GC. התבוננת בנתונים האלה יכולים אמנם לתת לנו "מבט כללי" על השפעת ה-GC על ביצועי האפליקציה, אבל הוא פשוט לא מספיק...
למרות שההשלכות של השילוב בין Nagle's Algorithm ו-Delayed ACKs בעבודה עם TCP מתועדות היטב בספרות, עדיין מדובר בפרט שלא פעם קל לשכוח ממנו ולא לקחת אותו בחשבון כשצריך. מאחר ולסימפטומים הבעייתים של השילוב ביניהם יש נטייה לצוף רק תחת אוסף של תנאים מקדימים, יכול לעבור קצת זמן עד שמשייכים את את ה"תופעות המעניינות" לשימוש בשני האלגוריתמים הנ"ל. במקרה הזה, ככל שהסימפטומים שנוצרים עקב השילוב חריפים יותר, כך גם יותר קל להבין את המקור שלהם. אבל קודם כל, נבין מה הרעיון מאחורי כל אחד מהאלגוריתמים...
אחת התורות הנסתרות בפיתוח מקבילי היא השאלה "בכמה ת'רדים צריך להשתמש כדי להגיע לניצול מירבי של החומרה העומדת לרשותנו?". יש שיגידו שמספר הת'רדים צריך להיות כמספר המעבדים, או כמספר המעבדים +1, או אולי בכלל פי 2 ממספר המעבדים. הסיבה שיש כל כך הרבה תשובות לשאלה, היא פשוט בגלל הסיבה שעבור כל תרחיש מסויים, תתאים תשובה אחרת (לכל אפליקציה יש אופי שונה, למשל האם היא מוגבלת על ידי ה-CPU או ה-IO?). אבל בכל אופן, תמיד הנוסחאות האלה מתבססות באיזשהיא צורה על מספר המעבדים הזמינים לנו (סך הכל, אנחנו...
בתקופה האחרונה שמתי לב שהנושא של False Sharing עולה לעתים די קרובות בבלוגים שמפרסמים פוסטים המסבירים במה בעצם מדובר ובאיך אפשר להמנע מהתופעה. כך שכמובן שהגיע הזמן שאתייחס בעצמי לנושא החשוב אך חמקמק הזה. אבל קודם כל, נסביר בקצרה במה בעצם מדובר ובאיפה טמונה הבעיה. אחד הנושאים הרגישים בפיתוח קוד מקבילי הוא הגישה לזיכרון המשותף למספר Thread'ים שונים. (כדי שנשאר ממוקדים בנושא הפוסט, אני אתעלם לרגע מבעיות העלולות להגרם כתוצאה מ-Instruction Reordering או אופטימיזציות אחרות שמבוצעות ברמת הקומפיילר או...
אחד השיעורים הראשונים שכל מפתח דוט-נט לומד לשנן, הוא ש"בכל מקרה בו רוצים לחבר הרבה מחרוזות אחת לשניה, אסור בתכלית האיסור להשתמש באופרטור +, ובמקום זה להשתמש במחלקה StringBuilder". אז אחרי הדקלום המושלם הזה, אתה שואל "אוקיי, אבל למה בעצם?", והתשובה היא בדרך כלל "בגלל שמחרוזות הן Immutable, זה אומר ששימוש באופרטור+ יביא להקצאות מיותרות של מחרוזות שיהווה כל מיני 'שלבי ביניים' עד שנגיע למחרוזת הסופית". כפי שאני רואה את זה, הדקלום הזה יותר מטעה מאשר מה שהוא תורם....
אחד החסרונות/יתרונות של דוט-נט הוא השימוש במנגנון ה-JIT (הלא הוא ה-Just in Time Compilation). למעשה, התהליך שתפקידו להפוך את ה-CIL לשפת מכונה. אפשר להסתכל על המנגנון הזה בתור יתרון מאחר ובצורה הזאת התוכנית מקומפלת על מחשב היעד שבאמת מריץ את התוכנה שלנו. בצורה הזאת, בזמן הקומפילציה ניתן להשתמש בכל היכולות שמעבד היעד תומך בהן. כלומר, בצורה הזאת אנחנו יכולים להגיע לקוד יעיל, ומהיר יותר בהשוואה לאם היינו מקמפלים את התוכנית על מחשב נפרד, בלי לדעת על אילו מחשבים יריצו את התוכנה שלנו (מאחר והיינו צריכים...
אולי לא הייתם מיודעים לכך, אבל בכל פעם שאתם פונים ל-DateTime.Now, אתם גורמים בעקיפין הקצאת זכרון דינאמית על ידי Boxing של Int32. הסיבה לכך טמונה עמוק בתוך המימוש של Now, שאם נסתכל מקרוב, נוכל לראות שהוא למעשה עוטף קריאה ל-UtcNow והמרתו לזמן מקומי על ידי קריאה לפונקציה ToLocalTime. עם הקריאה ל-UtcNow אין בעיה, מאחר ובסך הכל נעשית קריאה פנימית ל- GetSystemTimeAsFileTime , שמחזיר את הזמן הנוכחי בפורמט UTC. הבעיה האמיתית טמונה במימוש של ToLocalTime, או למעשה במחלקה CurrentSystemTimeZone בה היא נעזרת...
כשזה מגיע לתכנות מקבילי, משימה נפוצה למדי היא להשתמש בת'רד נפרד בתוכנית שיטפל בכל מיני קלטים/בקשות שהתוכנית שלנו מקבלת. מה שקורה בדרך כלל הוא שבזמן היצירה של הת'רד, מכניסים אותו לפונקציה עם לולאה אינסופית, ובתוך הלולאה מחכים לקבל Signal על כך ש"יש עבודה" לעשות. בצורה גסה, התבנית הבסיסית נראית כך: AutoResetEvent m_event = new AutoResetEvent ( false ); private void WorkCycles() { while ( true ) { // wait for a signal m_event.WaitOne(); // do work.. } } שימוש ב- AutoResetEvent מאוד...