-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathviper_native.py
126 lines (101 loc) · 3.23 KB
/
viper_native.py
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# (c) 2023 Hermann Paul von Borries
# MIT License
# Viper example to measure time
import machine
machine.freq(240_000_000)
import time
class MeasureTime:
def __init__(self, title ):
self.title = title
def __enter__( self ):
self.t0 = time.ticks_ms()
return self
def __exit__( self, exc_type, exc_val, exc_traceback ):
self.time_msec = time.ticks_diff( time.ticks_ms(), self.t0 )
print(f"MeasureTime {self.title} {self.time_msec} msec" )
@micropython.viper
def v_no_hints(limit:int)->int:
x = 0
while x < limit:
x = x + 1
return x
@micropython.viper
def v_range(limit:int)->int:
x = 0
for i in range(limit):
x = x + 1
return x
@micropython.viper
def v_hints(limit:int)->int:
x:int = 0 # this type hint does nothing
while x < limit:
x = x + 1
return x
@micropython.native
def native_fun(limit):
x = 0
while x < limit:
x = x + 1
return x
def undecorated_fun(limit):
x = 0
while x < limit:
x = x + 1
return x
print("Comparison of viper with hints, no hints, range and native")
limit = 5_000_000
with MeasureTime("viper, no hints"):
assert v_no_hints(limit) == limit
with MeasureTime("viper, with hints"):
assert v_hints(limit) == limit
with MeasureTime("using range"):
assert v_range(limit) == limit
with MeasureTime("native"):
assert native_fun(limit) == limit
#with MeasureTime("undecorated"):
# assert undecorated_fun(limit) == limit
# Result on ESP32-S3 with PSRAM at 240 Mhz
#MeasureTime viper, no hints 271 msec
#MeasureTime viper, with hints 271 msec
#MeasureTime using range 563 msec
#MeasureTime native 3231 msec
#MeasureTime undecorated 8920 msec
print("")
print("Function call overhead")
def undecorated_fun(a,b,c,d,e):
return
@micropython.viper
def viper_fun(a,b,c,d,e):
return
@micropython.viper
def viper_fun_hints(a:int,b:int,c:int,d:int,e:int):
return
@micropython.viper
def viper_fun_no_args():
return
def call_funs(limit):
with MeasureTime( "range only") as range_only:
for i in range(limit):
pass
with MeasureTime("undecorated function") as undecorated:
for i in range(limit):
undecorated_fun(1,2,3,4,5)
with MeasureTime("viper function") as viper:
for i in range(limit):
viper_fun(1,2,3,4,5)
with MeasureTime("viper with hints function") as viper_hints:
for i in range(limit):
viper_fun_hints(1,2,3,4,5)
with MeasureTime("viper with hints function") as no_args:
for i in range(limit):
viper_fun_no_args()
undecorated_time = undecorated.time_msec - range_only.time_msec
viper_time = viper.time_msec - range_only.time_msec
viper_hints_time = viper_hints.time_msec - range_only.time_msec
viper_fun_no_args_time = no_args.time_msec - range_only.time_msec
print(f"{limit} function calls")
print(f"{undecorated_time=}, {undecorated_time/limit*1000:.2f} usec per call")
print(f"{viper_time=} {viper_time/limit*1000:2f} usec per call")
print(f"{viper_hints_time=} {viper_hints_time/limit*1000:2f} usec per call")
print(f"{viper_fun_no_args_time=} {viper_fun_no_args_time/limit*1000:2f} usec per call")
call_funs(1_000_000)