@@ -346,93 +346,91 @@ Base.show(io::IO, t::TrialEstimate) = _show(io, t)
346
346
Base. show (io:: IO , t:: TrialRatio ) = _show (io, t)
347
347
Base. show (io:: IO , t:: TrialJudgement ) = _show (io, t)
348
348
349
- _percentile () = 99 # to tweak this live, TODO remove
350
-
351
349
function Base. show (io:: IO , :: MIME"text/plain" , t:: Trial )
352
-
353
350
pad = get (io, :pad , " " )
354
351
padcolor = :light_black
355
352
356
- showpercentile = _percentile ()
353
+ showpercentile = 99 # used both for display time, and to set right cutoff of histogram
357
354
358
- perm = sortperm (t. times)
359
- times = t. times[perm]
360
- gctimes = t. gctimes[perm]
355
+ allocsstr = if allocs (t) == 0
356
+ " 0 allocations"
357
+ elseif allocs (t) == 1
358
+ " 1 allocation, " * prettymemory (memory (t))
359
+ else
360
+ prettycount (allocs (t)) * " allocations, total " * prettymemory (memory (t))
361
+ end
362
+
363
+ samplesstr = string (
364
+ prettycount (length (t)),
365
+ if length (t) == 1 " sample, with " else " samples, each " end ,
366
+ prettycount (t. params. evals),
367
+ if t. params. evals == 1 " evaluation" else " evaluations" end ,
368
+ )
361
369
362
370
if length (t) == 0
363
371
print (io, " BenchmarkTools.Trial: 0 samples" )
364
372
return
365
373
elseif length (t) == 1
366
- println (io, " BenchmarkTools.Trial:" )
374
+ printstyled (io, " BenchmarkTools.Trial:\n " ; color = padcolor )
367
375
# Time
368
- print (io, pad, " │ Only 1 sample: " )
369
- printstyled (io, prettytime (times[1 ]); color= :green )
376
+ printstyled (io, pad, " │ " ; color= padcolor)
377
+ print (io, " time " )
378
+ printstyled (io, prettytime (t. times[1 ]); color= :green , bold= true )
370
379
371
380
# Memory
372
381
println (io)
373
- print (io, pad, " │ " , prettycount (t. allocs[1 ]), " allocation" , t. allocs[1 ]== 1 ? " " : " s" )
374
- if t. allocs[1 ] > 0
375
- print (io, " , " , prettymemory (t. memory[1 ]))
376
- end
382
+ printstyled (io, pad, " │ " ; color= padcolor)
383
+ print (io, allocsstr)
377
384
378
385
# GC time
379
386
if t. gctimes[1 ] > 0
380
387
println (io)
381
- print (io, pad, " │ GC time: " , prettytime (t. gctimes[1 ]))
388
+ printstyled (io, pad, " │ " ; color= padcolor)
389
+ print (io, " GC time: " , prettytime (t. gctimes[1 ]))
382
390
printstyled (io, " (" , prettypercent (t. gctimes[1 ] / t. times[1 ])," )" ; color= :green )
383
391
end
384
- return
385
- end # done with trivial cases.
386
-
387
- med = median (t)
388
- avg = mean (t)
389
- min = minimum (t)
390
- max = maximum (t)
391
- q99 = quantile (t, showpercentile/ 100 )
392
392
393
- mintime = prettytime (time (min))
394
- medtime = prettytime (time (med))
395
- avgtime = prettytime (time (avg))
396
- q99time = prettytime (time (q99))
397
-
398
- # Mean GC time is just that; then we take the percentage of the mean time
399
- avggctime, avegcpercent = prettytime (mean (gctimes)), prettypercent (mean (gctimes) / mean (times))
400
- q99gctime = prettytime (quantile (gctimes, showpercentile/ 100 ))
401
- # Maximum GC time has a percentage which is of the same run, not necc. the longest run
402
- _t, _i = findmax (gctimes)
403
- maxgctime, maxgcpercent = prettytime (_t), prettypercent (_t / times[_i])
393
+ #
394
+ println (io)
395
+ printstyled (io, pad, " └ " , samplesstr; color= padcolor)
404
396
405
- memorystr = prettymemory ( memory (min))
406
- allocsstr = prettycount ( allocs (min)) * ( allocs (min) == 1 ? " allocation " : " allocations " )
397
+ return
398
+ end # done with trivial cases.
407
399
408
400
# Main text block:
409
-
410
401
printstyled (io, " BenchmarkTools.Trial:\n " ; color= padcolor)
411
402
412
403
printstyled (io, pad, " │ " ; color= padcolor)
413
404
printstyled (io, " min " ; color= :default )
414
- printstyled (io, mintime ; color= :default , bold= true )
405
+ printstyled (io, prettytime ( minimum (t . times)) ; color= :default , bold= true )
415
406
print (io, " , " )
416
407
printstyled (io, " median " ; color= :blue )
417
- printstyled (io, medtime ; color= :blue , bold= true )
418
- printstyled (io, " (½)" ; color= :blue )
408
+ printstyled (io, prettytime ( median (t . times)) ; color= :blue , bold= true )
409
+ # printstyled(io, " (½)"; color=:blue)
419
410
print (io, " , " )
420
411
printstyled (io, " mean " ; color= :green )
421
- printstyled (io, avgtime ; color= :green , bold= true )
422
- printstyled (io, " (*)" ; color= :green )
412
+ printstyled (io, prettytime ( mean (t . times)) ; color= :green , bold= true )
413
+ # printstyled(io, " (*)"; color=:green)
423
414
print (io, " , " )
424
415
print (io, showpercentile, " ᵗʰ " )
425
- printstyled (q99time ; bold= true )
416
+ printstyled (prettytime ( quantile (t . times, showpercentile / 100 )) ; bold= true )
426
417
println (io)
427
418
428
419
printstyled (io, pad, " │ " ; color= padcolor)
429
- print (io, allocsstr)
430
- if allocs (min) != 0
431
- println (io, " , " , memorystr)
432
- else
433
- println (io)
434
- end
435
- if ! all (iszero, gctimes)
420
+ println (io, allocsstr)
421
+
422
+ if ! all (iszero, t. gctimes)
423
+ # Mean GC time is just that; then we take the percentage of the mean time
424
+ avggctime = prettytime (mean (t. gctimes))
425
+ avegcpercent = prettypercent (mean (t. gctimes) / mean (t. times))
426
+
427
+ # Maximum GC time is not taken as the GC time of the slowst run, max(t).
428
+ # The percentage shown is of the same max-GC run, again not the percentage of longest time.
429
+ # Of course, very often the slowest run is due to GC, and these concerns won't matter.
430
+ _t, _i = findmax (t. gctimes)
431
+ maxgctime = prettytime (_t)
432
+ maxgcpercent = prettypercent (_t / t. gctimes[_i])
433
+
436
434
printstyled (io, pad, " │ " ; color= padcolor)
437
435
print (io, " GC time: mean " , avggctime)
438
436
printstyled (io, " (" , avegcpercent, " )" ; color= :green )
@@ -445,7 +443,11 @@ function Base.show(io::IO, ::MIME"text/plain", t::Trial)
445
443
histquantile = showpercentile/ 100
446
444
# The height and width of the printed histogram in characters:
447
445
histheight = 2
448
- histwidth = 74 # fits into 78 chars, as does 1st line with 4 times
446
+ histwidth = 78 - 4 # fits into 78 chars # TODO read this from io?
447
+
448
+ perm = sortperm (t. times)
449
+ times = t. times[perm]
450
+ gctimes = t. gctimes[perm]
449
451
450
452
# This needs sorted times:
451
453
histtimes = times[1 : round (Int, histquantile* end )]
@@ -454,8 +456,7 @@ function Base.show(io::IO, ::MIME"text/plain", t::Trial)
454
456
logbins = get (io, :logbins , nothing )
455
457
bins = bindata (histtimes, histwidth - 1 , histmin, histmax)
456
458
append! (bins, [1 , floor ((1 - histquantile) * length (times))])
457
- # if median size of (bins with >10% average data/bin) is less than 5% of max bin size, log the bin sizes
458
- if logbins === true # || (logbins === nothing && median(filter(b -> b > 0.1 * length(times) / histwidth, bins)) / maximum(bins) < 0.05)
459
+ if logbins === true
459
460
bins, logbins = log .(1 .+ bins), true
460
461
else
461
462
logbins = false
@@ -468,19 +469,31 @@ function Base.show(io::IO, ::MIME"text/plain", t::Trial)
468
469
if delta1 > 0
469
470
medpos = 1 + round (Int, (histtimes[length (times) ÷ 2 ] - histmin) / delta1)
470
471
avgpos = 1 + round (Int, (mean (times) - histmin) / delta1)
472
+ # TODO replace with searchsortedfirst & range?
473
+ q25pos = 1 + round (Int, (histtimes[max (1 ,length (times) ÷ 4 )] - histmin) / delta1)
474
+ q75pos = 1 + round (Int, (histtimes[3 * length (times) ÷ 4 ] - histmin) / delta1)
471
475
else
472
476
medpos, avgpos = 1 , 1
477
+ q25pos, q75pos = 1 , 1
473
478
end
474
479
475
480
# Above the histogram bars, print markers for special ones:
476
- # println(io)
477
481
printstyled (io, pad, " │ " ; color= padcolor)
482
+ istop = maximum (filter (i -> i in axes (hist,2 ), [avgpos, medpos+ 1 , q75pos]))
478
483
for i in axes (hist, 2 )
484
+ i > istop && break
479
485
if i == avgpos
480
- printstyled (io, " *" , color= :green , bold= true ) # or μ, or t̄?
486
+ printstyled (io, " *" , color= :green , bold= true )
481
487
elseif i == medpos || (medpos== avgpos && i== medpos- 1 )
482
488
# marker for "median" is moved one to the left if they collide
483
- printstyled (io, " ½" , color= :blue ) # sadly "㊿" is often double wide. ½, |, ‖, ↓ maybe?
489
+ # printstyled(io, "½", color=:blue)
490
+ printstyled (io, " ◑" , color= :blue )
491
+ elseif i == q25pos
492
+ # printstyled(io, "¼", color=:light_black)
493
+ printstyled (io, " ◔" , color= :light_black )
494
+ elseif i == q75pos
495
+ # printstyled(io, "¾", color=:light_black)
496
+ printstyled (io, " ◕" , color= :light_black )
484
497
else
485
498
print (io, " " )
486
499
end
@@ -489,7 +502,9 @@ function Base.show(io::IO, ::MIME"text/plain", t::Trial)
489
502
for r in axes (hist, 1 )
490
503
println (io)
491
504
printstyled (io, pad, " │ " ; color= padcolor)
505
+ istop = findlast (!= (' ' ), view (hist, r, :))
492
506
for (i, bar) in enumerate (view (hist, r, :))
507
+ i > istop && break # don't print trailing spaces, as they waste space when line-wrapped
493
508
color = :default
494
509
if i == avgpos
495
510
color = :green
@@ -509,43 +524,28 @@ function Base.show(io::IO, ::MIME"text/plain", t::Trial)
509
524
printstyled (io, pad, " └ " ; color= padcolor)
510
525
print (io, minhisttime)
511
526
# Caption is only printed if logbins has been selected:
512
- caption = string (prettycount (length (t)), " sample" , if length (t) > 1 " s" else " " end ,
513
- " , each " , prettycount (t. params. evals), " evaluation" , if t. params. evals > 1 " s" else " " end )
514
- caption = logbins ? (" log(counts) from " * caption) : caption
527
+ caption = logbins ? (" log(counts) from " * samplesstr) : samplesstr
515
528
printstyled (io, " " ^ ((histwidth - length (caption)) ÷ 2 - length (minhisttime)), caption; color= :light_black )
516
529
print (io, lpad (maxhisttime, ceil (Int, (histwidth - length (caption)) / 2 ) - 1 ), " " )
517
530
print (io, " +" )
531
+ # printstyled(io, "●", color=:light_black) # other options...
532
+ # print(io, "⋯")
533
+ # printstyled(io, "¹⁰⁰", color=:light_black)
518
534
end
519
535
520
- # These two functions allow endpoints 6, 7, 8, 10, 15, 20, 30, 40, ... perhaps too coarse?
521
- # exp.(range(log(1), log(10), length=11)) ≈ [1, 1.25, 1.6, 2, 2.5, 3.2, 4, 5, 6.3, 8, 10]
522
-
523
- # round.(0:0.01:10, sigdigits=3, base=2) |> unique # looks good in 1:10, not great outside
536
+ # I wondered about rounding to a few steps per decade. This looks good in 1:10, not great outside:
537
+ # round.(0:0.01:10, sigdigits=3, base=2) |> unique
524
538
function low_edge (times)
525
- # return 0
526
- min = minimum (times)
527
- # return round(min, RoundDown; sigdigits = 3, base = 2)
528
- return round (min, RoundDown; sigdigits = 2 )
529
- # dec = round(min, RoundDown; sigdigits = 1)
530
- # if first(string(dec)) == '1'
531
- # min > 1.5 * dec && return 1.5 * dec
532
- # # min > 1.2 * dec && return 1.2 * dec
533
- # elseif first(string(dec)) == '9'
534
- # return round((8//9) * dec, sigdigits = 2)
535
- # end
536
- # dec
539
+ # _min = minimum(times)
540
+ _min = min (minimum (times), mean (times) / 1.03 ) # demand low edge 3% below mean
541
+ return round (_min, RoundDown; sigdigits = 2 )
542
+
537
543
end
538
544
function high_edge (times)
539
- max = maximum (times)
540
- # return round(max, RoundUp; sigdigits = 3, base = 2)
541
- return round (max, RoundUp; sigdigits = 2 )
542
- # dec = round(max, RoundUp; sigdigits = 1)
543
- # if first(string(dec)) == '2'
544
- # max < 0.75 * dec && return 0.75 * dec
545
- # elseif first(string(dec)) == '9'
546
- # return round((10//9) * dec, sigdigits = 2)
547
- # end
548
- # dec
545
+ # _max = maximum(times)
546
+ # _max = Base.max(maximum(times), 1.07 * low_edge(times)) # demand total width at least 7%
547
+ _max = max (maximum (times), 1.03 * mean (times)) # demand high edge 3% above mean
548
+ return round (_max, RoundUp; sigdigits = 2 )
549
549
end
550
550
551
551
function Base. show (io:: IO , :: MIME"text/plain" , t:: TrialEstimate )
0 commit comments