From df3d14b58588689ab382044ffc9f781af1b05f3b Mon Sep 17 00:00:00 2001
From: Eli Barzilay <eli@racket-lang.org>
Date: Mon, 30 Mar 2009 17:00:31 +0000
Subject: [PATCH] avoid divisions by zero when no work is observed

svn: r14360

original commit: 6964e5745d9f3657dd9b90597df848ac717ef65c
---
 collects/profile/render-text.ss |  9 +++++----
 collects/profile/utils.ss       | 20 +++++++++++++++-----
 2 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/collects/profile/render-text.ss b/collects/profile/render-text.ss
index 0688f8f..010f731 100644
--- a/collects/profile/render-text.ss
+++ b/collects/profile/render-text.ss
@@ -52,7 +52,8 @@
   (define total-time    (profile-total-time    profile))
   (define cpu-time      (profile-cpu-time      profile))
   (define sample-number (profile-sample-number profile))
-  (define granularity   (/ total-time sample-number))
+  (define granularity   (if (zero? sample-number) 0
+                            (/ total-time sample-number)))
   (define threads+times (profile-thread-times  profile))
   (define *-node        (profile-*-node profile))
   (define hidden        (get-hidden profile hide-self% hide-subs%))
@@ -100,10 +101,10 @@
       (define name   (node-> 'label node))
       (define total  (node-total node))
       (define totalS (f:msec total))
-      (define total% @string-append{(@(format-percent (/ total total-time)))})
+      (define total% @string-append{(@(format-percent total total-time))})
       (define self   (node-self node))
       (define selfS  (f:msec self))
-      (define self%  @string-append{(@(format-percent (/ self total-time)))})
+      (define self%  @string-append{(@(format-percent self total-time))})
       (define name+src
         (let* ([src      (format-source (node-src node))]
                [src-len  (string-length src)]
@@ -124,7 +125,7 @@
                     #:when (not (or (eq? *-node sub)        ; <-- ...for this
                                     (memq sub hidden))))
           (define name   (node-> 'sub-label sub))
-          (define local% (format-percent (/ (get-node-time edge) total)))
+          (define local% (format-percent (get-node-time edge) total))
           `("" "" "" "" "" "" "" ""
             ,(string-append "  " name) ,local%
             "" "")))
diff --git a/collects/profile/utils.ss b/collects/profile/utils.ss
index 0228ba4..edc76f9 100644
--- a/collects/profile/utils.ss
+++ b/collects/profile/utils.ss
@@ -3,9 +3,17 @@
 (provide format-percent format-source get-hidden)
 (require "analyzer.ss")
 
-(define (format-percent percent)
-  (let ([percent (inexact->exact (round (* percent 1000)))])
-    (format "~a.~a%" (quotient percent 10) (modulo percent 10))))
+;; Format a percent number, possibly doing the division too.  If we do the
+;; division, then be careful: if we're dividing by zero, then make the result
+;; zero.  This is useful if the total time is zero because we didn't see any
+;; activity (for example, the profiled code is just doing a `sleep'), in which
+;; case all times will be 0.
+(define format-percent
+  (case-lambda
+    [(percent)
+     (let ([percent (inexact->exact (round (* percent 1000)))])
+       (format "~a.~a%" (quotient percent 10) (modulo percent 10)))]
+    [(x y) (format-percent (if (zero? y) 0 (/ x y)))]))
 
 (define (format-source src)
   (if src
@@ -16,7 +24,7 @@
               (format "#~a" (srcloc-position src))))
     "(unknown source)"))
 
-;; hide a node if its self time is smaller than the self threshold *and* all of
+;; Hide a node if its self time is smaller than the self threshold *and* all of
 ;; its edges are below the sub-node threshold too -- this avoids confusing
 ;; output where a node does not have an entry but appears as a caller/callee.
 (define (get-hidden profile hide-self% hide-subs%)
@@ -34,4 +42,6 @@
     (and (self% . >= . (/ (node-self node) total-time))
          (hide-sub? node-callees edge-callee edge-caller-time)
          (hide-sub? node-callers edge-caller edge-callee-time)))
-  (if (or (> self% 0) (> subs% 0)) (filter hide? (profile-nodes profile)) '()))
+  (cond [(and (<= self% 0) (<= subs% 0)) '()]
+        [(zero? total-time) (profile-nodes profile)]
+        [else (filter hide? (profile-nodes profile))]))