//#!/usr/bin/env sq // // This is a port of a few of the microbenchmarks in benchmark.hss to Squirrel/Quirrel for comparison NUM_RUNS <- 100 MICRO_LOOPCOUNT <- 1000 IS_QUIRREL <- true try { "string".contains } catch(x) { IS_QUIRREL = false } /****** Helper functions ******/ function sum(arr) { local ret = 0 foreach (x in arr) ret += x return ret } function min(arr) { local ret = 1.79e308 foreach (x in arr) if (x < ret) ret = x return ret } function printnl(str) print(str + "\n") function showarray(arr) { local ret = "[" foreach (i, x in arr) { if (i) ret += ", " ret += "" + x //.tostring() } return ret + "]" } /******************************/ function benchmark_for_loop() { for (local i = 0; i < MICRO_LOOPCOUNT; i++) ; } function benchmark_while_loop() { local i = MICRO_LOOPCOUNT while (i) i -= 1 } function benchmark_continue_loop() { local i = MICRO_LOOPCOUNT while (true) { i -= 1 if (i) continue break } } function benchmark_addition() { local x = 0, y = 0, end = MICRO_LOOPCOUNT / 10 for (local i = 0; i < end; i++) { x + y x + y x + y x + y x + y x + y x + y x + y x + y x + y } } function benchmark_increment() { local x = 0, y = 0, end = MICRO_LOOPCOUNT / 10 for (local i = 0; i < end; i++) { x += y x += y x += y x += y x += y x += y x += y x += y x += y x += y } } function benchmark_array_create_delete() { local arr for (local i = 0; i < MICRO_LOOPCOUNT; i++) { arr = array(8, 0) arr = null } } function benchmark_array_length() { local end = MICRO_LOOPCOUNT / 10 for (local i = 0; i < end; i++) { testarray.len() testarray.len() testarray.len() testarray.len() testarray.len() testarray.len() testarray.len() testarray.len() testarray.len() testarray.len() } } testarray <- array(MICRO_LOOPCOUNT, 0) function benchmark_array_index() { local end = MICRO_LOOPCOUNT / 10 for (local i = 0; i < end; i++) { testarray[i] testarray[i] testarray[i] testarray[i] testarray[i] testarray[i] testarray[i] testarray[i] testarray[i] testarray[i] } } function benchmark_array_foreach() { foreach (val in testarray) val } function benchmark_array_sum() { local total = 0 foreach (val in testarray) // Much faster than for total += val } function benchmark_array_append() { local arr = [] for (local i = 0; i < 100; i++) arr.append(i) } function benchmark_string_append() { local var = "", end = MICRO_LOOPCOUNT / 10 for (local i = 0; i < end; i++) { var += "a" var += "a" var += "a" var += "a" var += "a" var += "a" var += "a" var += "a" var += "a" var += "a" } } /******************************/ function empty_script() { } function empty_multiarg_script(a, b, c, d) { } function benchmark_call_script() { local end = MICRO_LOOPCOUNT / 10 for (local i = 0; i < end; i++) { empty_script() empty_script() empty_script() empty_script() empty_script() empty_script() empty_script() empty_script() empty_script() empty_script() empty_script() } } function benchmark_call_multiarg_script() { local end = MICRO_LOOPCOUNT / 10 + 1 for (local i = 0; i < end; i++) { empty_multiarg_script (i, i, i, i) empty_multiarg_script (i, i, i, i) empty_multiarg_script (i, i, i, i) empty_multiarg_script (i, i, i, i) empty_multiarg_script (i, i, i, i) empty_multiarg_script (i, i, i, i) empty_multiarg_script (i, i, i, i) empty_multiarg_script (i, i, i, i) empty_multiarg_script (i, i, i, i) empty_multiarg_script (i, i, i, i) } } /******************************/ function benchmark_distance() { local x = 300 local y = 400 local res local end = MICRO_LOOPCOUNT / 10 + 1 for (local i = 0; i < end; i++) { res = sqrt((i - x)*(i - x) + (i - y)*(i - x)) res = sqrt((i - x)*(i - x) + (i - y)*(i - x)) res = sqrt((i - x)*(i - x) + (i - y)*(i - x)) res = sqrt((i - x)*(i - x) + (i - y)*(i - x)) res = sqrt((i - x)*(i - x) + (i - y)*(i - x)) res = sqrt((i - x)*(i - x) + (i - y)*(i - x)) res = sqrt((i - x)*(i - x) + (i - y)*(i - x)) res = sqrt((i - x)*(i - x) + (i - y)*(i - x)) res = sqrt((i - x)*(i - x) + (i - y)*(i - x)) res = sqrt((i - x)*(i - x) + (i - y)*(i - x)) } } function benchmark_distance_squared() { local x = 300 local y = 400 local res local end = MICRO_LOOPCOUNT / 10 + 1 for (local i = 0; i < end; i++) { res = (i - x)*(i - x) + (i - y)*(i - y) // Vastly faster than pow(,2) res = (i - x)*(i - x) + (i - y)*(i - y) res = (i - x)*(i - x) + (i - y)*(i - y) res = (i - x)*(i - x) + (i - y)*(i - y) res = (i - x)*(i - x) + (i - y)*(i - y) res = (i - x)*(i - x) + (i - y)*(i - y) res = (i - x)*(i - x) + (i - y)*(i - y) res = (i - x)*(i - x) + (i - y)*(i - y) res = (i - x)*(i - x) + (i - y)*(i - y) res = (i - x)*(i - x) + (i - y)*(i - y) } } function benchmark_manhatten_distance() { local x = 300 local y = 400 local res local end = MICRO_LOOPCOUNT / 10 + 1 for (local i = 0; i < end; i++) { res = abs(i - x) + abs(i - y) // abs is quite slow res = abs(i - x) + abs(i - y) res = abs(i - x) + abs(i - y) res = abs(i - x) + abs(i - y) res = abs(i - x) + abs(i - y) res = abs(i - x) + abs(i - y) res = abs(i - x) + abs(i - y) res = abs(i - x) + abs(i - y) res = abs(i - x) + abs(i - y) res = abs(i - x) + abs(i - y) } } /******************************/ function fibonacci(n) { if (n < 2) return 1 return fibonacci(n-2) + fibonacci(n-1) } function benchmark_recursive_fibonacci() { fibonacci(14) } /******************************/ function FixedMul(a, b) { if (a >= 0) return (a / 0x10000) * b + ((a & 0xffff) * b + 0x8000) / 0x10000 else // fixme: not sure the rounding here is correct return (a / 0x10000) * b - ((-a & 0xffff) * b + 0x8000) / 0x10000 } function benchmark_fixedmul() { local total = 0 for (local i = -100000; i < 100000; i += 8000) for (local j = -100000; j < 100000; j += 8000) total += FixedMul(i, j) return total } //printnl("fixedmul " + benchmark_fixedmul()) //FIXME: returns wrong result /******************************/ function benchmark_string_iter() { for (local i = 0; i < 8; i++) { local s = "The quick onyx goblin jumps over the lazy dwarf. Bright vixens jump, lazy fowl quack. Amazingly few discotheques provide jukeboxes." local words = 1 local hsh = 0 foreach (ch in s) { if (ch == 32) words += 1 hsh += words * ch } //if (i==0) printnl("HASH " + hsh) } } /******************************/ function crappy_sqrt(fi) { local start, divi, approx = -1 if (fi >= 32581) return 181 else { if (fi < 100 ) { start = 0 divi = start * start } else { if (fi >= 22500) start = 150 else { if (fi >= 14400) start = 120 else { if (fi >= 8100) start = 90 else { if (fi >= 4225) start = 65 else { if (fi >= 1600) start = 40 else { if (fi >= 900) start = 30 else { if (fi >= 400) start = 20 else start = 10 } } } } } } divi = start * start if (fi / 3 > divi / 2) { start = (start / 5) * 6 divi = start * start } if (fi / 4 > divi / 3) { start = (start / 7) * 8 divi = start * start } } while (approx == -1) { if (divi >= fi) { approx = start } else { start += 1 divi = start * start } } if (divi == fi) { return approx } else { if ((divi - approx) == fi) return approx - 1 else return fi / approx + 1 } } } // Test flow control function benchmark_crappy_sqrt() { for (local i = 0; i < 81; i++) crappy_sqrt(i) } /******************************/ bubbles <- null function benchmark_bubble_fill() { bubbles = array(40) // This version is about the same speed //foreach (i, _ in bubbles) local size = bubbles.len() for (local i = 0; i < size; i++) bubbles[i] = (24461 * i) % 32767 } function benchmark_bubble_sort() { local size = bubbles.len() for (local i = 1; i < size; i++) { for (local j = 0; j < i; j++) { if (bubbles[j] > bubbles[i]) { local tmp = bubbles[j] bubbles[j] = bubbles[i] bubbles[i] = tmp } } } // foreach (i, val in bubbles) { // if (i > 0) // assert(bubbles[i-1] <= val) // } } /******************************/ function run_benchmark(script, loops, scoremult = 1, init_func = null) { local times = [] for (local i = 0; i < NUM_RUNS; i++) { if (init_func) init_func() local timing = clock() script() times.append(clock() - timing) } if (IS_QUIRREL) // Quirrel printnl(script.getfuncinfos().name) else // Squirrel printnl(script.getinfos().name) local mult, unitname if (loops > 1) { mult = 1e9 / loops unitname = "nanoseconds per loop" } else { mult = 1e6 unitname = "microseconds per run" } printnl(" best " + unitname + ": " + mult * min(times)) times = times.sort().slice(0, times.len()/2 + 1) //printnl(showarray(times)) local displayval = mult * sum(times) / times.len() printnl(" average " + unitname + " (excl. outliers): " + displayval) score += (displayval * scoremult).tointeger() } score <- 0 run_benchmark(benchmark_for_loop, MICRO_LOOPCOUNT) run_benchmark(benchmark_while_loop, MICRO_LOOPCOUNT) run_benchmark(benchmark_continue_loop, MICRO_LOOPCOUNT) run_benchmark(benchmark_addition, MICRO_LOOPCOUNT) run_benchmark(benchmark_increment, MICRO_LOOPCOUNT) run_benchmark(benchmark_array_create_delete, MICRO_LOOPCOUNT, 0.2) run_benchmark(benchmark_array_length, MICRO_LOOPCOUNT) run_benchmark(benchmark_array_index, MICRO_LOOPCOUNT) run_benchmark(benchmark_array_foreach, MICRO_LOOPCOUNT, 0) // mult=0 because HS lacks it run_benchmark(benchmark_array_sum, MICRO_LOOPCOUNT) run_benchmark(benchmark_array_append, 100) run_benchmark(benchmark_string_append, MICRO_LOOPCOUNT, 0.25) run_benchmark(benchmark_call_script, MICRO_LOOPCOUNT) run_benchmark(benchmark_call_multiarg_script, MICRO_LOOPCOUNT) run_benchmark(benchmark_distance, MICRO_LOOPCOUNT) run_benchmark(benchmark_distance_squared, MICRO_LOOPCOUNT) run_benchmark(benchmark_manhatten_distance, MICRO_LOOPCOUNT) printnl("\nGeneral benchmarks\n") run_benchmark(benchmark_recursive_fibonacci, 1, 2) run_benchmark(benchmark_fixedmul, 1) run_benchmark(benchmark_string_iter, 1) run_benchmark(benchmark_crappy_sqrt, 1) run_benchmark(benchmark_bubble_fill, 40) run_benchmark(benchmark_bubble_sort, 1, 1, benchmark_bubble_fill) printnl("Total time: " + score)