Skip to content

Commit bbb63e7

Browse files
committed
[new] Refactor, modernize formatting code
1 parent 236df93 commit bbb63e7

File tree

3 files changed

+102
-140
lines changed

3 files changed

+102
-140
lines changed

src/taoensso/tufte.cljc

Lines changed: 25 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,24 @@
619619

620620
(enc/defaliases
621621
enc/chance
622-
impl/merge-pstats)
622+
impl/merge-pstats
623+
impl/format-pstats
624+
impl/format-grouped-pstats)
625+
626+
(comment
627+
(let [[_ ps1] (profiled {} (p :p1))
628+
[_ ps2] (profiled {} (p :p1))]
629+
(enc/qb 1e5 (merge-pstats ps1 ps2))) ; 74.38
630+
631+
(println
632+
(str "\n"
633+
(format-pstats
634+
(second
635+
(profiled {}
636+
(p :foo (Thread/sleep 200))
637+
(p :bar (Thread/sleep 500))
638+
(do (Thread/sleep 800))))
639+
{:columns [:clock :p50 :p95]}))))
623640

624641
(defn format-id-abbr-fn
625642
"Returns a cached (fn [id]) => abbreviated id with at most `n-full`
@@ -643,28 +660,6 @@
643660

644661
(comment (refer-tufte))
645662

646-
(defn format-pstats
647-
"Formats given pstats to a string table.
648-
Accounted < Clock => Some work was done that wasn't tracked by any p forms.
649-
Accounted > Clock => Nested p forms, and/or parallel threads."
650-
([ps ] (format-pstats ps nil))
651-
([ps opts]
652-
(when ps
653-
(let [{:keys [clock stats]} (if (instance? PStats ps) @ps ps)]
654-
(impl/format-pstats (get clock :total) stats opts)))))
655-
656-
(comment
657-
;; [:n :min :p25 :p50 :p75 :p90 :p95 :p99 :max :mean :mad :clock :sum]
658-
(println
659-
(str "\n"
660-
(format-pstats
661-
(second
662-
(profiled {}
663-
(p :foo (Thread/sleep 200))
664-
(p :bar (Thread/sleep 500))
665-
(do (Thread/sleep 800))))
666-
{:columns [:clock :p50 :p95]}))))
667-
668663
;;;; fnp stuff
669664

670665
(defn- fn-sigs [def? ?meta-id ?fn-sym sigs loc]
@@ -858,53 +853,15 @@
858853

859854
(comment
860855
(def my-sacc (add-accumulating-handler! {:ns-pattern "*"}))
861-
(future (profile {} (p :p1 (Thread/sleep 900))))
862-
(future (profile {:id :foo} (p :p1 (Thread/sleep 900))))
863-
(future (profile {:id :bar} (p :p1 (Thread/sleep 500))))
864-
(println (format-grouped-pstats @my-sacc {}
865-
#_{:format-pstats-opts {:columns [:n]}})))
866856

867-
(defn format-grouped-pstats
868-
"Alpha, subject to change.
869-
Takes a map of {<group-id> <PStats>} and formats a combined
870-
output string using `format-pstats`.
871-
872-
See also example clj project."
873-
([m] (format-grouped-pstats m nil))
874-
([m {:keys [group-sort-fn format-pstats-opts]
875-
:or {group-sort-fn (fn [m] (get-in m [:clock :total] 0))}}]
876-
877-
(when m
878-
(let [m ; {<group-id> <realised-pstats>}
879-
(persistent!
880-
(reduce-kv
881-
(fn [m k v] (assoc! m k (enc/force-ref v)))
882-
(transient m)
883-
m))
884-
885-
sorted-group-ids
886-
(sort-by (fn [id] (group-sort-fn (get m id)))
887-
enc/rcompare (keys m))
888-
889-
^long max-id-width
890-
(reduce-kv
891-
(fn [^long acc _ {:keys [clock stats]}]
892-
(if-let [c (impl/get-max-id-width stats format-pstats-opts)]
893-
(if (> (long c) acc) c acc)
894-
acc))
895-
0
896-
m)]
897-
898-
(enc/str-join "\n\n"
899-
(map (fn [id] (str id ",\n" (format-pstats (get m id) (assoc format-pstats-opts :max-id-width max-id-width)))))
900-
sorted-group-ids)))))
857+
(do
858+
(future (profile {} (p :p1 (Thread/sleep 900))))
859+
(future (profile {:id :foo} (p :p1 (Thread/sleep 900))))
860+
(future (profile {:id :bar} (p :p1 (Thread/sleep 500)))))
901861

902-
(comment
903-
(future
904-
(while true
905-
(when-let [m (not-empty @my-sacc)]
906-
(println (format-grouped-pstats m)))
907-
(Thread/sleep 10000))))
862+
(println
863+
(format-grouped-pstats @my-sacc
864+
{:format-pstats-opts {:columns [:n]}})))
908865

909866
;;;; Deprecated
910867

src/taoensso/tufte/impl.cljc

Lines changed: 75 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -436,50 +436,6 @@
436436

437437
;;;; Formatting
438438

439-
(defn- perc [n d] (str (Math/round (* (/ (double n) (double d)) 100.0)) "%"))
440-
(comment [(perc 1 1) (perc 1 100) (perc 12 44)])
441-
442-
(def ^:dynamic *fmt-opts* {:decimal-separator ".", :thousands-separator ","})
443-
(defn- fmt-num [precision n]
444-
;; Impln is inefficient but sufficient, and consistent between clj/s
445-
(let [n (enc/roundn precision n)
446-
neg? (neg? n)
447-
n-abs (Math/abs n)
448-
n-int-part (long n-abs)
449-
fmt-opts *fmt-opts*]
450-
(str
451-
(when neg? "-")
452-
(->>
453-
(str n-int-part)
454-
(reverse)
455-
(partition 3 3 "")
456-
(mapv str/join)
457-
(str/join (get fmt-opts :thousands-separator))
458-
(str/reverse))
459-
460-
(when-let [n-dec-part (and (pos? (long precision)) (- n-abs n-int-part))]
461-
(str (get fmt-opts :decimal-separator)
462-
(enc/substr (str n-dec-part "000000")
463-
:by-len 2 precision))))))
464-
465-
(comment
466-
(fmt-num 0 123123123.5555) ; "123,123,124"
467-
(fmt-num 2 123123123.5555) ; "123,123,123.56"
468-
(fmt-num 2 123123123) ; "123,123,123.00"
469-
(fmt-num 3 123) ; "123"
470-
)
471-
472-
(defn- fmt-nsecs [nanosecs]
473-
(let [ns (double nanosecs)]
474-
(cond
475-
(>= ns 6e10) (str (fmt-num 2 (/ ns 6e10)) "m")
476-
(>= ns 1e9) (str (fmt-num 2 (/ ns 1e9)) "s")
477-
(>= ns 1e6) (str (fmt-num 0 (/ ns 1e6)) "ms")
478-
(>= ns 1e3) (str (fmt-num 0 (/ ns 1e3)) "μs")
479-
:else (str (fmt-num 0 ns) "ns"))))
480-
481-
(comment (fmt-nsecs 1e3))
482-
483439
(def all-format-columns [:n :min :p25 :p50 :p75 :p90 :p95 :p99 :max :mean :mad :clock :sum])
484440
(def default-format-columns [:n :min #_:p25 :p50 #_:p75 :p90 :p95 :p99 :max :mean :mad :clock :sum])
485441

@@ -493,16 +449,13 @@
493449
(identical? columns all-format-columns) all-format-columns
494450
:else (mapv format-column columns))))
495451

496-
(comment (enc/qb 1e6 (format-columns [:min :n-calls :total])))
497-
498-
(def default-format-id-fn (fn [id] (str id)))
452+
(comment (enc/qb 1e6 (format-columns [:min :n-calls :total]))) ; 152.9
499453

500454
;; id-sstats* => {<id> <sstats>} or {<id> <sstats-map>}
501-
502455
(defn get-max-id-width
503456
[id-sstats*
504457
{:keys [format-id-fn]
505-
:or {format-id-fn default-format-id-fn}}]
458+
:or {format-id-fn (fn [id] (str id))}}]
506459

507460
(when id-sstats*
508461
(reduce-kv
@@ -512,15 +465,18 @@
512465
9 ; (count "Accounted")
513466
id-sstats*)))
514467

515-
(defn format-pstats
468+
(def ^:private format-n (enc/format-num-fn 0 0))
469+
470+
(defn format-pstats*
516471
"Given {<id> <sstats>} or {<id> <sstats-map>} pstats, returns a formatted
517472
table string. Assumes nanosecond clock, and stats based on profiling id'd
518473
nanosecond times."
519474
[clock-total id-sstats*
520475
{:keys [columns sort-fn format-id-fn max-id-width] :as opts
521-
:or {columns default-format-columns
522-
sort-fn (fn [ss] (get (enc/force-ref ss) :sum))
523-
format-id-fn default-format-id-fn}}]
476+
:or
477+
{columns default-format-columns
478+
sort-fn (fn [ss] (get (enc/force-ref ss) :sum))
479+
format-id-fn (fn [id] (str id))}}]
524480

525481
(when id-sstats*
526482
(let [columns (format-columns columns)
@@ -577,7 +533,7 @@
577533
(enc/sb-append sb " "))
578534
(append-col column (get-in column->pattern [column :heading])))
579535

580-
(enc/sb-append sb "\n\n")
536+
(enc/sb-append sb enc/newlines)
581537

582538
; Write id rows
583539
(doseq [id sorted-ids]
@@ -588,36 +544,36 @@
588544
(doseq [column columns]
589545
(enc/sb-append sb " ")
590546
(case column
591-
:n (append-col column (fmt-num 0 n))
592-
:mean (append-col column (fmt-nsecs mean))
593-
:mad (append-col column (str "±" (perc mad mean)))
594-
:sum (append-col column (perc sum clock-total))
595-
:clock (append-col column (fmt-nsecs sum))
596-
(do (append-col column (fmt-nsecs (get ssm column))))))
547+
:n (append-col column (format-n n))
548+
:mean (append-col column (enc/format-nsecs mean))
549+
:mad (append-col column (str "±" (enc/perc mad mean) "%"))
550+
:sum (append-col column (str (enc/perc sum clock-total) "%"))
551+
:clock (append-col column (enc/format-nsecs sum))
552+
(do (append-col column (enc/format-nsecs (get ssm column))))))
597553

598-
(enc/sb-append sb "\n")))
554+
(enc/sb-append sb enc/newline)))
599555

600556
; Write accounted row
601-
(enc/sb-append sb "\n")
557+
(enc/sb-append sb enc/newline)
602558
(append-col :id "Accounted")
603559
(doseq [column columns]
604560
(enc/sb-append sb " ")
605561
(case column
606-
:sum (append-col column (perc accounted-total clock-total))
607-
:clock (append-col column (fmt-nsecs accounted-total))
562+
:sum (append-col column (str (enc/perc accounted-total clock-total) "%"))
563+
:clock (append-col column (enc/format-nsecs accounted-total))
608564
(do (append-col column ""))))
609565

610566
; Write clock row
611-
(enc/sb-append sb "\n")
567+
(enc/sb-append sb enc/newline)
612568
(append-col :id "Clock")
613569
(doseq [column columns]
614570
(enc/sb-append sb " ")
615571
(case column
616572
:sum (append-col column "100%")
617-
:clock (append-col column (fmt-nsecs clock-total))
573+
:clock (append-col column (enc/format-nsecs clock-total))
618574
(do (append-col column ""))))
619575

620-
(enc/sb-append sb "\n")
576+
;; (enc/sb-append sb enc/newline)
621577
(str sb))))
622578

623579
(comment
@@ -626,11 +582,60 @@
626582

627583
(println
628584
(format-pstats (* 1e6 30)
629-
{:foo (summary-stats (rand-vs 1e4 20))
630-
:bar (summary-stats (rand-vs 1e2 50))
631-
:baz (summary-stats (rand-vs 1e5 30))}
585+
{:foo (stats/summary-stats (rand-vs 1e4 20))
586+
:bar (stats/summary-stats (rand-vs 1e2 50))
587+
:baz (stats/summary-stats (rand-vs 1e5 30))}
632588
{}) "\n"))
633589

590+
(defn ^:public format-pstats
591+
"Formats given pstats to a string table.
592+
Accounted < Clock => Some work was done that wasn't tracked by any p forms.
593+
Accounted > Clock => Nested p forms, and/or parallel threads."
594+
([ps ] (format-pstats ps nil))
595+
([ps opts]
596+
(when ps
597+
(let [{:keys [clock stats]} (enc/force-ref ps)]
598+
(format-pstats* (get clock :total) stats opts)))))
599+
600+
(defn ^:public format-grouped-pstats
601+
"Alpha, subject to change.
602+
Takes a map of {<profile-id> <pstats>} and formats a combined
603+
output string using `format-pstats`.
604+
605+
See also example Clj project."
606+
([m] (format-grouped-pstats m nil))
607+
([m {:keys [group-sort-fn format-pstats-opts]
608+
:or {group-sort-fn (fn [m] (get-in m [:clock :total] 0))}}]
609+
610+
(when m
611+
(let [m ; {<profile-id> <realised-pstats>}
612+
(persistent!
613+
(reduce-kv
614+
(fn [m k v] (assoc! m k (enc/force-ref v)))
615+
(transient m)
616+
m))
617+
618+
sorted-profile-ids
619+
(sort-by (fn [id] (group-sort-fn (get m id)))
620+
enc/rcompare (keys m))
621+
622+
^long max-id-width
623+
(reduce-kv
624+
(fn [^long acc _ {:keys [clock stats]}]
625+
(if-let [c (get-max-id-width stats format-pstats-opts)]
626+
(if (> (long c) acc) c acc)
627+
acc))
628+
0 m)
629+
630+
sep (str "," enc/newline)
631+
format-pstats-opts
632+
(assoc format-pstats-opts
633+
:max-id-width max-id-width)]
634+
635+
(enc/str-join enc/newlines
636+
(map (fn [id] (str id sep (format-pstats (get m id) format-pstats-opts))))
637+
sorted-profile-ids)))))
638+
634639
;;;; Output handlers
635640

636641
(enc/defonce handlers_ "{<hid> <handler-fn>}" (atom nil))

test/taoensso/tufte_tests.cljc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@
446446
:baz {:n 1}}}))])))]))
447447

448448
(deftest format-pstats
449-
[(testing "Basic format-pstats"
449+
[(testing "Basics"
450450
(let [data {:clock {:total 15}
451451
:stats {:foo {:n 10000
452452
:min 1
@@ -477,7 +477,7 @@
477477
(str/split-lines)
478478
(remove empty?))))]))
479479

480-
(testing "format-pstats with namespaced symbols"
480+
(testing "With namespaced symbols"
481481
(let [data {:clock {:total 15}
482482
:stats {:foo/bar {:n 10000
483483
:min 1

0 commit comments

Comments
 (0)