Last active
July 4, 2022 08:57
-
-
Save KvanTTT/e3b355f7e321fe7f52e11ea1aa0ecbce to your computer and use it in GitHub Desktop.
Constant folding benchmark
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from dis import dis | |
import sys | |
import timeit | |
warm_up_count = 4 | |
iteration_count = 256 | |
class C: | |
C0=0 | |
C1=1 | |
C2=2 | |
C3=3 | |
C4=4 | |
C5=5 | |
C6=6 | |
C7=7 | |
C8=8 | |
C9=9 | |
C10=10 | |
C11=11 | |
C12=12 | |
C13=13 | |
C14=14 | |
C15=15 | |
C16=16 | |
C17=17 | |
C18=18 | |
C19=19 | |
C20=20 | |
C21=21 | |
C22=22 | |
C23=23 | |
C24=24 | |
C25=25 | |
C26=26 | |
C27=27 | |
C28=28 | |
C29=29 | |
C30=30 | |
C31=31 | |
def main(argv): | |
check_by_if_test = benchmark_average("check_by_if_test") | |
check_by_range_test = benchmark_average("check_by_range_test") | |
check_by_range_with_literals_test = benchmark_average("check_by_range_with_literals_test") | |
check_by_bitwise_test = benchmark_average("check_by_bitwise_test") | |
print(f"check_by_if_test: {check_by_if_test} ns") | |
print(f"check_by_range_test: {check_by_range_test} ns") | |
print(f"check_by_range_with_literals_test: {check_by_range_with_literals_test} ns") | |
print(f"check_by_bitwise_test: {check_by_bitwise_test} ns") | |
def benchmark_average(func_name): | |
func_call = f"{func_name}(7)" | |
setup_str = f"from __main__ import {func_name}" | |
print(f"function {func_name}:") | |
print("warm up...") | |
timeit.timeit(func_call, setup=setup_str, number=warm_up_count) | |
print("warm up completed.") | |
print("benchmark...") | |
avg_time = timeit.timeit(func_call, setup=setup_str, number=iteration_count) / iteration_count | |
print("benchmark completed.") | |
print("") | |
return int(round(avg_time * 1_000_000_000)) # return result in nanoseconds | |
def check_by_if_test(i): | |
return i == C.C0 or i == C.C1 or i == C.C2 or i == C.C3 or\ | |
i == C.C4 or i == C.C5 or i == C.C6 or i == C.C7 or\ | |
i == C.C8 or i == C.C9 or i == C.C10 or i == C.C11 or\ | |
i == C.C12 or i == C.C13 or i == C.C14 or i == C.C15 or\ | |
i == C.C16 or i == C.C17 or i == C.C18 or i == C.C19 or\ | |
i == C.C20 or i == C.C21 or i == C.C22 or i == C.C23 or\ | |
i == C.C24 or i == C.C25 or i == C.C26 or i == C.C27 or\ | |
i == C.C28 or i == C.C29 or i == C.C30 or i == C.C31 | |
def check_by_range_test(i): | |
return i in [C.C0, C.C1, C.C2, C.C3, | |
C.C4, C.C5, C.C6, C.C7, | |
C.C8, C.C9, C.C10, C.C11, | |
C.C12, C.C13, C.C14, C.C15, | |
C.C16, C.C17, C.C18, C.C19, | |
C.C20, C.C21, C.C22, C.C23, | |
C.C24, C.C25, C.C26, C.C27, | |
C.C28, C.C29, C.C30, C.C31] | |
def check_by_range_with_literals_test(i): | |
return i in [0, 1, 2, 3, | |
4, 5, 6, 7, | |
8, 9, 10, 11, | |
12, 13, 14, 15, | |
16, 17, 18, 19, | |
20, 21, 22, 23, | |
24, 25, 26, 27, | |
28, 29, 30, 31] | |
def check_by_bitwise_test(i): # i within [0..63) | |
return (1 << i) & 0xFFFFFFFF != 0 | |
if __name__ == '__main__': | |
main(sys.argv) | |
print("consts:") | |
dis(check_by_range_test) | |
print("literals:") | |
dis(check_by_range_with_literals_test) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const warmUpCount = 8 | |
const iterationCount = 64 | |
class C {} | |
C.C0=1 | |
C.C1=1 | |
C.C2=2 | |
C.C3=3 | |
C.C4=4 | |
C.C5=5 | |
C.C6=6 | |
C.C7=7 | |
C.C8=8 | |
C.C9=9 | |
C.C10=10 | |
C.C11=11 | |
C.C12=12 | |
C.C13=13 | |
C.C14=14 | |
C.C15=15 | |
no_folding_const_refs_test = benchmarkAverage(no_folding_const_refs_test); | |
no_folding_const_literals_test = benchmarkAverage(no_folding_const_literals_test); | |
folding_test = benchmarkAverage(folding_test); | |
console.log(`no_folding_const_refs_test: ${no_folding_const_refs_test} ns`) | |
console.log(`no_folding_const_literals_test: ${no_folding_const_literals_test} ns`) | |
console.log(`folding_test: ${folding_test} ns`) | |
function benchmarkAverage(func) { | |
console.log(`function ${func.name}:`) | |
console.log("warm up...") | |
for (let i = 0; i < warmUpCount; i++) { | |
func(); | |
} | |
console.log("warm up completed.") | |
console.log("benchmark...") | |
let startTime = process.hrtime(); | |
for (let i = 0; i < iterationCount; i++) { | |
func(); | |
} | |
let elapsed = process.hrtime(startTime); | |
let elapsedNs = Math.round((elapsed[0] * 1e6 + elapsed[1] / 1e3) * 1000 / iterationCount); | |
console.log("benchmark completed.") | |
console.log("") | |
return elapsedNs; | |
} | |
function no_folding_const_refs_test() { | |
return (1 << C.C0) | (1 << C.C1) | (1 << C.C2) | (1 << C.C3) | | |
(1 << C.C4) | (1 << C.C5) | (1 << C.C6) | (1 << C.C7) | | |
(1 << C.C8) | (1 << C.C9) | (1 << C.C10) | (1 << C.C11) | | |
(1 << C.C12) | (1 << C.C13) | (1 << C.C14) | (1 << C.C15); | |
} | |
function no_folding_const_literals_test() { | |
return (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | | |
(1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | | |
(1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | | |
(1 << 12) | (1 << 13) | (1 << 14) | (1 << 15); | |
} | |
function folding_test() { | |
return 0xFFFF | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
import timeit | |
warm_up_count = 1 | |
iteration_count = 64 | |
class C: | |
C0=1 | |
C1=1 | |
C2=2 | |
C3=3 | |
C4=4 | |
C5=5 | |
C6=6 | |
C7=7 | |
C8=8 | |
C9=9 | |
C10=10 | |
C11=11 | |
C12=12 | |
C13=13 | |
C14=14 | |
C15=15 | |
def main(argv): | |
no_folding_const_refs_test = benchmark_average("no_folding_const_refs_test") | |
no_folding_const_literals_test = benchmark_average("no_folding_const_literals_test") | |
folding = benchmark_average("folding_test") | |
print(f"no_folding_const_refs_test: {no_folding_const_refs_test} ns") | |
print(f"no_folding_const_literals_test: {no_folding_const_literals_test} ns") | |
print(f"folding: {folding} ns") | |
def benchmark_average(func_name): | |
func_call = f"{func_name}()" | |
setup_str = f"from __main__ import {func_name}" | |
print(f"function {func_name}:") | |
print("warm up...") | |
timeit.timeit(func_call, setup=setup_str, number=warm_up_count) | |
print("warm up completed.") | |
print("benchmark...") | |
avg_time = timeit.timeit(func_call, setup=setup_str, number=iteration_count) / iteration_count | |
print("benchmark completed.") | |
print("") | |
return int(round(avg_time * 1_000_000_000)) # return result in nanoseconds | |
def no_folding_const_refs_test(): | |
return (1 << C.C0) | (1 << C.C1) | (1 << C.C2) | (1 << C.C3) | \ | |
(1 << C.C4) | (1 << C.C5) | (1 << C.C6) | (1 << C.C7) | \ | |
(1 << C.C8) | (1 << C.C9) | (1 << C.C10) | (1 << C.C11) | \ | |
(1 << C.C12) | (1 << C.C13) | (1 << C.C14) | (1 << C.C15) | |
def no_folding_const_literals_test(): | |
return (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | \ | |
(1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | \ | |
(1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | \ | |
(1 << 12) | (1 << 13) | (1 << 14) | (1 << 15) | |
def folding_test(): | |
return 0xFFFF | |
if __name__ == '__main__': | |
main(sys.argv) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment