CPU util. measurements fix (more accurate and steady)
authorimarom <[email protected]>
Thu, 18 Aug 2016 10:49:59 +0000 (13:49 +0300)
committerimarom <[email protected]>
Thu, 18 Aug 2016 10:52:49 +0000 (13:52 +0300)
see #trex-246

scripts/automation/trex_control_plane/stl/console/trex_tui.py
src/bp_sim.cpp
src/main_dpdk.cpp
src/os_time.h
src/utl_cpuu.cpp
src/utl_cpuu.h

index 6dff0a6..e769b9b 100644 (file)
@@ -515,9 +515,31 @@ class ScreenBuffer():
         self.redraw_cb(buffer)
 
         with self.lock:
-            self.snapshot = buffer.getvalue()
+            self.snapshot = buffer
             self.update_flag = False
 
+# a policer class to make sure no too-fast redraws
+# occurs - it filters fast bursts of redraws
+class RedrawPolicer():
+    def __init__ (self, rate):
+        self.ts = 0
+        self.marked = False
+        self.rate = rate
+        self.force = False
+
+    def mark_for_redraw (self, force = False):
+        self.marked = True
+        if force:
+            self.force = True
+
+    def should_redraw (self):
+        dt = time.time() - self.ts
+        return self.force or (self.marked and (dt > self.rate))
+
+    def reset (self, restart = False):
+        self.ts = time.time()
+        self.marked = restart
+        self.force = False
 
 
 # shows a textual top style window
@@ -531,6 +553,7 @@ class TrexTUI():
     MIN_ROWS = 50
     MIN_COLS = 111
 
+
     class ScreenSizeException(Exception):
         def __init__ (self, cols, rows):
             msg = "TUI requires console screen size of at least {0}x{1}, current is {2}x{3}".format(TrexTUI.MIN_COLS,
@@ -585,7 +608,12 @@ class TrexTUI():
         self.pm.init(show_log, locked)
 
         self.state = self.STATE_ACTIVE
-        self.last_redraw_ts = 0
+
+        # create print policers
+        self.full_redraw = RedrawPolicer(0.5)
+        self.keys_redraw = RedrawPolicer(0.05)
+        self.full_redraw.mark_for_redraw()
+
 
         try:
             self.sb.start()
@@ -594,11 +622,10 @@ class TrexTUI():
                 # draw and handle user input
                 status = self.async_keys.tick(self.pm)
 
-                self.draw_screen(status)
-
-                # speedup for keys, slower for no keys
-                if status == AsyncKeys.STATUS_NONE:
-                    time.sleep(0.001)
+                # prepare the next frame
+                self.prepare(status)
+                time.sleep(0.01)
+                self.draw_screen()
 
                 with self.tui_global_lock:
                     self.handle_state_machine()
@@ -611,6 +638,7 @@ class TrexTUI():
 
         print("")
 
+        
 
     # handle state machine
     def handle_state_machine (self):
@@ -641,34 +669,44 @@ class TrexTUI():
                 self.state = self.STATE_LOST_CONT
 
 
-    # draw once
-    def draw_screen (self, status):
+    # logic before printing
+    def prepare (self, status):
+        if status == AsyncKeys.STATUS_REDRAW_ALL:
+            self.full_redraw.mark_for_redraw(force = True)
 
-        t = time.time() - self.last_redraw_ts
-        redraw = (t >= 0.5) or (status == AsyncKeys.STATUS_REDRAW_ALL)
-        if redraw:
+        elif status == AsyncKeys.STATUS_REDRAW_KEYS:
+            self.keys_redraw.mark_for_redraw()
+
+        if self.full_redraw.should_redraw():
             self.sb.update()
-            self.last_redraw_ts = time.time()
-        
+            self.full_redraw.reset(restart = True)
 
+        return
+
+
+    # draw once
+    def draw_screen (self):
+
+        # check for screen buffer's new screen
         x = self.sb.get()
 
         # we have a new screen to draw
         if x:
             self.clear_screen()
-
-            sys.stdout.write(x)
-            self.async_keys.draw(sys.stdout)
+            
+            self.async_keys.draw(x)
+            sys.stdout.write(x.getvalue())
             sys.stdout.flush()
 
-        # we only need to redraw the keys
-        elif status == AsyncKeys.STATUS_REDRAW_KEYS:
+        # maybe we need to redraw the keys
+        elif self.keys_redraw.should_redraw():
             sys.stdout.write("\x1b[4A")
-
             self.async_keys.draw(sys.stdout)
             sys.stdout.flush()
 
-        return
+            # reset the policer for next time
+            self.keys_redraw.reset()
+
 
      
 
index 2d1d020..773e82f 100755 (executable)
@@ -4615,8 +4615,7 @@ double CFlowGenList::GetCpuUtilRaw(){
 
 void CFlowGenList::UpdateFast(){
 
-    int i;
-    for (i=0; i<(int)m_threads_info.size(); i++) {
+    for (int i=0; i<(int)m_threads_info.size(); i++) {
         CFlowGenListPerThread * lp=m_threads_info[i];
         lp->Update();
     }
index 6beb4e3..0ef83c0 100644 (file)
@@ -4126,15 +4126,21 @@ void
 CGlobalTRex::handle_fast_path() {
     /* check from messages from DP */
     check_for_dp_messages();
-    // update CPU%
-    m_fl.UpdateFast();
 
-    if (get_is_stateless()) {
-        m_rx_sl.update_cpu_util();
-    }else{
-        m_mg.update_fast();
+    /* measure CPU utilization by sampling (we sample 1000 to get an accurate sampling) */
+    for (int i = 0; i < 1000; i++) {
+        m_fl.UpdateFast();
+
+        if (get_is_stateless()) {
+            m_rx_sl.update_cpu_util();
+        }else{
+            m_mg.update_fast();
+        }
+
+        rte_pause();
     }
 
+
     if ( is_all_cores_finished() ) {
         mark_for_shutdown(SHUTDOWN_TEST_ENDED);
     }
index b1d44c0..4f10e2b 100755 (executable)
@@ -165,6 +165,17 @@ void delay(int msec){
     nanosleep(&time1,&remain);
 }
 
-
+/**
+ * more accurate sleep by doing spin
+ * 
+ */
+static inline
+void delay_spin(double sec) {
+    double target = now_sec() + sec;
+
+    while (now_sec() < target) {
+        rte_pause();
+    }
+}
 
 #endif
index 47c78c8..c01326d 100755 (executable)
@@ -42,10 +42,11 @@ void CCpuUtlCp::Update(){
     if ( m_dpcpu->sample_data() ) {
         m_work++;
     }
-    if (m_ticks==100) {
+    if (m_ticks==100000) {
         /* LPF*/
-        m_cpu_util_lpf = (m_cpu_util_lpf*0.75)+((double)m_work*0.25);
-        AppendHistory(m_work);
+        double work = (m_work / double(m_ticks)) * 100;
+        m_cpu_util_lpf = (m_cpu_util_lpf*0.75)+(work*0.25);
+        AppendHistory(work);
         m_ticks=0;
         m_work=0;
     }
index b0a76fc..690eb20 100755 (executable)
@@ -47,7 +47,7 @@ public:
 
 
 private:
-    uint8_t m_data;
+    volatile uint8_t m_data;
 } __rte_cache_aligned; 
 
 class CCpuUtlCp {
@@ -62,9 +62,9 @@ public:
     void GetHistory(cpu_vct_st &cpu_vct);
 private:
     void AppendHistory(uint8_t);
-    CCpuUtlDp *         m_dpcpu;
-    uint8_t             m_ticks;
-    uint8_t             m_work;
+    CCpuUtlDp *          m_dpcpu;
+    uint32_t             m_ticks;
+    uint32_t             m_work;
 
     static const int    m_history_size=20;
     uint8_t             m_cpu_util[m_history_size]; // history as cyclic array