diff --git a/README.txt b/README.txt index 009de7d..2031c7b 100644 --- a/README.txt +++ b/README.txt @@ -1,4 +1,4 @@ -Stopwatch Mod v1.1 +Stopwatch Mod v1.2 By Leslie Krause Repository @@ -22,6 +22,10 @@ Version 1.1b (24-Aug-2018) - included working code examples for developers - implemented stack for non-linear testing of code +Version 1.2b (28-Aug-2018) + - major rewrite to improve accuracy and efficiency + - updated code examples with latest feature-set + Installation ---------------------- diff --git a/example.lua b/example.lua index 9310ace..3cb119a 100644 --- a/example.lua +++ b/example.lua @@ -1,17 +1,22 @@ -- measure the performance of table inserts in append vs prepend mode: -local S, S_ = Stopwatch( ) +local S1, S1_ = Stopwatch("table_prepend", "cyan") +local S2, S2_ = Stopwatch("table_append", "yellow") -local y = { } -S( "table prepend" ) -for x = 0, 5000 do - table.insert( y, 1, x ) +for trial = 0, 5 do + local y = {} + S1() + for x = 0, 5000 do + table.insert(y, 1, x) + end + S1_(1) end -S_( ) -y = { } -S( "table append" ) -for x = 0, 5000 do - table.insert( y, x ) +for trial = 0, 5 do + local y = {} + S2() + for x = 0, 5000 do + table.insert(y, x) + end + S2_(1) end -S_( ) diff --git a/init.lua b/init.lua index e4a7c74..d8ac84d 100644 --- a/init.lua +++ b/init.lua @@ -1,55 +1,61 @@ -------------------------------------------------------- --- Minetest :: Stopwatch Mod v1.1 (stopwatch) +-- Minetest :: Stopwatch Mod v1.2 (stopwatch) -- -- See README.txt for licensing and release notes. -- Copyright (c) 2018, Leslie E. Krause -------------------------------------------------------- -function Stopwatch( scale ) +function Stopwatch( id, color, scale, prec ) + local ts + local trials = { } + local factor = scale and ( { us = 1, ms = 1000, s = 1000000 } )[ scale ] or 1000 + local escape = color and ( { none = 0, black = 30, red = 31, green = 32, yellow = 33, blue = 34, magenta = 35, cyan = 36, white = 37 } )[ color ] or 0 + + if not factor then error( "Unknown scale specified, aborting." ) end + if not escape then error( "Unknown color specified, aborting." ) end + if not id then error( "Invalid id specified, aborting." ) end + local clock = minetest.get_us_time local sprintf = string.format - local getinfo = debug.getinfo - local factors = { us = 1, ms = 1000, s = 1000000 } - local origin = getinfo( 2 ).source - local trials = { } - local series = { } + local push = table.insert - if not scale then - scale = "ms" - elseif not factors[ scale ] then - error( "Invalid scale specified, aborting." ) - end + local str_count = sprintf( "** %-16s %13s %9s\n", "series", "count", "rep" ) + .. string.gsub( "** \27[%dm%-16s %10.#f %2s %8dx\27[0m", "#", prec or 3 ) + local str_total = sprintf( "** %-16s %13s %9s %10s %10s %10s %10s %10s\n", "series", "total", "rep", "avg", "min", "max", "med", "dev" ) + .. string.gsub( "** \27[%dm%-16s %10.#f %2s %8dx %10.#f %10.#f %10.#f %10.#f %10.#f\27[0m", "#", prec or 3 ) - local function S( desc ) - local i = getinfo( 2, "lf" ) - id = desc or tostring( i.func ) .. ", line " .. i.currentline - local v = trials[ id ] - if not v then - v = { count = 0, delta_t = 0 } - trials[ id ] = v - end - table.insert( series, id ) - v.start = clock( ) + local function S( ) + ts = clock( ) end local function S_( is_show ) - local id = table.remove( series ) - local v = trials[ id ] - local delta = clock( ) - v.start + if not ts then error( "Trial not initiated, aborting." ) end + + local v = clock( ) - ts + push( trials, v ) if is_show then - print( sprintf( "** trial count = %9.3f %s @%s", delta / factors[ scale ], scale, id ) ) + print( sprintf( str_count, escape, id, v / factor, scale or "ms", #trials ) ) end - v.delta_t = v.delta_t + delta - v.count = v.count + 1 end minetest.register_on_shutdown( function ( ) - local delta_g = 0 - print( "** " .. origin ) - for i, v in pairs( trials ) do - print( sprintf( "** trial total = %9.3f %s %4d tries %8.3f %s each @%s", - v.delta_t / factors[ scale ], scale, v.count, v.delta_t / v.count / factors[ scale ], scale, i ) ) - delta_g = delta_g + v.delta_t + local v_sum = 0 + local v_var = 0 + local v_min, v_max, v_med, v_avg, v_dev + + if #trials > 0 then + for i, v in pairs( trials ) do + v_sum = v_sum + v + v_min = v_min and math.min( v_min, v ) or v + v_max = v_max and math.max( v_max, v ) or v + end + v_avg = v_sum / #trials + for i, v in pairs( trials ) do + v_var = v_var + math.pow( v - v_avg, 2 ) + end + v_dev = math.sqrt( v_var / #trials ) + v_med = v_min + ( v_max - v_min ) / 2 + + print( sprintf( str_total, escape, id, v_sum / factor, scale or "ms", #trials, v_avg / factor, v_min / factor, v_max / factor, v_med / factor, v_dev / factor ) ) end - print( sprintf( "** grand total = %9.3f %s", delta_g / factors[ scale ], scale ) ) end ) return S, S_ end