יום שישי, 20 בספטמבר 2013

יצירת Performance Counter

בהמשך לפוסטים האחרונים שלי על Tracing, הנה דרך מצוינת לאסוף סטטיסטיקות על האפליקציה שלנו:

בכל זמן נתון מערכת ההפעלה של Windows אוספת סטטיסטיקות על המערכת (כגון CPU, IO, סטטיסטיקות על IIS ועוד המון אחרים..). את הסטטיסטיקות אפשר לראות דרך ה Perfmon.exe.
בדרך זו אפשר ללמוד המון על המערכת שלנו (למשל כאשר היא רצה בסביבת Production).
יתרון גדול שמערכת ההפעלה מאפשרת לנו הוא שאנחנו יכולים ליצור Counter's משלנו, וכך יכולים לעקוב אחר ביצועי האפליקציה שלנו (למשל נוכל לראות כמה זמן בממוצע לוקח לשרות שלנו לעבד בקשה, כמו login בוצעו לאפליקציה, וכל סטטיסטיקה אחרת שאפשר לדמיין).

באמצעות ה PerformanceCounter class ש .Net מספק לנו, אנחנו יכולים לגשת לנתוני Counter שונים, ואף ליצור Counter חדשים לאפליקציה שלנו.

יש כל מיני Counter Types, אך השכיחים ביותר:
  1. NumberOfItems32- סופר מספר פריטים (למשל אפשר לספור כמה בקשות בוצעו)
  2. AverageTimer32- סופר את הזמן הממוצע שנדרש לפעולה מסוימת להיות מבוצעת
  3. RateOfCountsPerSecond32- סופר את מספר הפעולות שבוצעו בכל שנייה
יצירת Performance Counter חדש:

הדרך הראשונה (והפחות עדיפה) היא דרך ה Server Explorer  ב VS:



הדרך השניה היא ליצור באמצעות קוד שנכתוב:

ניצור את ה Counter באמצעות הקוד (ככה שנראה אותו ב Perfmon..):

 
        if (!PerformanceCounterCategory.Exists("MyNewCategory"))
            {
                CounterCreationDataCollection counters = new CounterCreationDataCollection();

                //counting totals: PerformanceCounterType.NumberOfItems32
                CounterCreationData totalOperations = new CounterCreationData();
                totalOperations.CounterName = "# operations executed";
                totalOperations.CounterType = PerformanceCounterType.NumberOfItems32;
                counters.Add(totalOperations);

                //counting operations per second: PerformanceCounterType.RateOfCountsPerSecond32
                CounterCreationData opsPerSecond = new CounterCreationData();
                opsPerSecond.CounterName = "# operations / sec";
                opsPerSecond.CounterType = PerformanceCounterType.RateOfCountsPerSecond32;
                counters.Add(opsPerSecond);

                //counting average time per operation: PerformanceCounterType.AverageTimer32
                CounterCreationData avgDuration = new CounterCreationData();
                avgDuration.CounterName = "average time per operation";
                avgDuration.CounterType = PerformanceCounterType.AverageTimer32;
                counters.Add(avgDuration);

                //base counter for counting average time per operation: PerformanceCounterType.AverageBase
                CounterCreationData avgDurationBase = new CounterCreationData();
                avgDurationBase.CounterName = "average time per operation base";
                avgDurationBase.CounterType = PerformanceCounterType.AverageBase;
                counters.Add(avgDurationBase);

                // create new category with the counters above
                PerformanceCounterCategory.Create("MyNewCategory", 
                        "Sample category", counters);
            }

שימו לב!! אם יצרתם  AverageTimer אז חייבים מיד אחריו ליצור AverageBase.

לאחר שנריץ את הקוד הנ"ל יהיה אפשר להכנס ל Perfmon ולקבל:


עכשיו כל אפליקציה תוכל לכתוב/לקרוא נתונים על ה Counter שיצרנו (MyNewCategory)

יצירת האובייקט של ה Performance Counter באפליקציה שלנו:

כעת באפליקציה שלנו נרצה לאתחל את ה Counter's כדי שנוכל להתממשק לקטגוריה שיצרנו

     _TotalOps = new PerformanceCounter();
            _TotalOps.CategoryName = "MyNewCategory";
            _TotalOps.CounterName = "# operations executed";
            _TotalOps.MachineName = ".";
            _TotalOps.ReadOnly = false;

            _OpsPerSecond = new PerformanceCounter();
            _OpsPerSecond.CategoryName = "MyNewCategory";
            _OpsPerSecond.CounterName = "# operations / sec";
            _OpsPerSecond.MachineName = ".";
            _OpsPerSecond.ReadOnly = false;

            //another way to create...
            _AvgDuration = new PerformanceCounter("MyNewCategory",
            "average time per operation",
            false);

            _AverageDurationBase = new PerformanceCounter("MyNewCategory",
            "average time per operation base",
            false);

שימו לב!! כשאתחלנו את המשתנים באפליקציה שלנו- אם אחד מהפרמטרים לא תואם את מה שקיים על השרת (על פי מה שיצרנו בשלב הראשון- למשל ה Category שונה או ה CounterName שונה אז נקבל InvalidOperationException

הכנסת הנתונים ל Counter:

מה שנותר לנו כעת זה להכניס נתונים ל Counter..

לדוגמא בעת ריצת האפליקציה הבאה:

      Stopwatch s = new Stopwatch();
    
            for (int i = 0; i < 1000; i++)
            {
                s.Start();
                
                // simply increment the counters
                _TotalOps.Increment();

                _OpsPerSecond.Increment();

                Thread.Sleep(300+10*i);

                // increment the timer 
                _AvgDuration.IncrementBy(s.ElapsedTicks);
                _AverageDurationBase.IncrementBy(1);
            
                s.Stop();
                s.Reset();
            }      
יהיה אפשר לראות ב Perfmon את הסטטיסטיקה הבאה (למשל):


תהנו!

תגובה 1: