Skip to content

Commit d06ed1d

Browse files
committed
[GR-11308] add support for warmup curves
PullRequest: graalpython/170
2 parents 3d9b73c + 30abc62 commit d06ed1d

31 files changed

+312
-394
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ language
5050
Python3.g4.stamp
5151
*.orig
5252
/graalpython/com.oracle.graal.python.test/src/tests/cpyext/Py*.c
53+
/graalpython/com.oracle.graal.python.test/src/tests/cpyext/Test*.c
5354
/*.diff
5455
## generated from: pyhocon -i ci.hocon -f json -o ci.json
5556
/ci.json

ci.jsonnet

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
overlay: "c3f1ef1ed72e05b6096e935e9c87cb05855ac5ea",
2+
overlay: "2562524065c42e18d4a5ea57e8cbf6cac6b9bdda",
33

44
// ======================================================================================================
55
//

graalpython/benchmarks/src/harness.py

+159
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
2+
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3+
#
4+
# The Universal Permissive License (UPL), Version 1.0
5+
#
6+
# Subject to the condition set forth below, permission is hereby granted to any
7+
# person obtaining a copy of this software, associated documentation and/or
8+
# data (collectively the "Software"), free of charge and under any and all
9+
# copyright rights in the Software, and any and all patent rights owned or
10+
# freely licensable by each licensor hereunder covering either (i) the
11+
# unmodified Software as contributed to or provided by such licensor, or (ii)
12+
# the Larger Works (as defined below), to deal in both
13+
#
14+
# (a) the Software, and
15+
#
16+
# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
17+
# one is included with the Software each a "Larger Work" to which the Software
18+
# is contributed by such licensors),
19+
#
20+
# without restriction, including without limitation the rights to copy, create
21+
# derivative works of, display, perform, and distribute the Software and make,
22+
# use, sell, offer for sale, import, export, have made, and have sold the
23+
# Software and the Larger Work(s), and to sublicense the foregoing rights on
24+
# either these or other terms.
25+
#
26+
# This license is subject to the following condition:
27+
#
28+
# The above copyright notice and either this complete permission notice or at a
29+
# minimum a reference to the UPL must be included in all copies or substantial
30+
# portions of the Software.
31+
#
32+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38+
# SOFTWARE.
39+
40+
import _io
41+
import os
42+
import sys
43+
from time import time
44+
45+
_HRULE = '-'.join(['' for i in range(80)])
46+
ATTR_BENCHMARK = '__benchmark__'
47+
ATTR_PROCESS_ARGS = '__process_args__'
48+
49+
50+
def _as_int(value):
51+
if isinstance(value, (list, tuple)):
52+
value = value[0]
53+
54+
if not isinstance(value, int):
55+
return int(value)
56+
return value
57+
58+
59+
class BenchRunner(object):
60+
def __init__(self, bench_file, bench_args=None, iterations=1, warmup=0):
61+
if bench_args is None:
62+
bench_args = []
63+
self.bench_module = BenchRunner.get_bench_module(bench_file)
64+
self.bench_args = bench_args
65+
self.iterations = _as_int(iterations)
66+
assert isinstance(self.iterations, int)
67+
self.warmup = _as_int(warmup)
68+
assert isinstance(self.warmup, int)
69+
70+
@staticmethod
71+
def get_bench_module(bench_file):
72+
name = bench_file.rpartition("/")[2].partition(".")[0].replace('.py', '')
73+
directory = bench_file.rpartition("/")[0]
74+
pkg = []
75+
while any(f.endswith("__init__.py") for f in os.listdir(directory)):
76+
directory, slash, postfix = directory.rpartition("/")
77+
pkg.insert(0, postfix)
78+
79+
if pkg:
80+
sys.path.insert(0, directory)
81+
bench_module = __import__(".".join(pkg + [name]))
82+
for p in pkg[1:]:
83+
bench_module = getattr(bench_module, p)
84+
bench_module = getattr(bench_module, name)
85+
return bench_module
86+
87+
else:
88+
bench_module = type(sys)(name, bench_file)
89+
with _io.FileIO(bench_file, "r") as f:
90+
bench_module.__file__ = bench_file
91+
exec(compile(f.readall(), bench_file, "exec"), bench_module.__dict__)
92+
return bench_module
93+
94+
def _get_attr(self, attr_name):
95+
if hasattr(self.bench_module, attr_name):
96+
return getattr(self.bench_module, attr_name)
97+
98+
def _call_attr(self, attr_name, *args):
99+
attr = self._get_attr(attr_name)
100+
if attr and hasattr(attr, '__call__'):
101+
return attr(*args)
102+
103+
def run(self):
104+
print(_HRULE)
105+
print("### %s, %s warmup iterations, %s bench iterations " % (self.bench_module.__name__, self.warmup, self.iterations))
106+
107+
# process the args if the processor function is defined
108+
args = self._call_attr(ATTR_PROCESS_ARGS, *self.bench_args)
109+
if args is None:
110+
# default args processor considers all args as ints
111+
args = list(map(int, self.bench_args))
112+
113+
print("### args = %s" % args)
114+
print(_HRULE)
115+
116+
bench_func = self._get_attr(ATTR_BENCHMARK)
117+
if bench_func and hasattr(bench_func, '__call__'):
118+
if self.warmup:
119+
print("### warming up for %s iterations ... " % self.warmup)
120+
for _ in range(self.warmup):
121+
bench_func(*args)
122+
123+
for iteration in range(self.iterations):
124+
start = time()
125+
bench_func(*args)
126+
duration = "%.3f" % (time() - start)
127+
print("### iteration=%s, name=%s, duration=%s" % (iteration, self.bench_module.__name__, duration))
128+
129+
130+
def run_benchmark(prog, args):
131+
warmup = 0
132+
iterations = 1
133+
bench_file = None
134+
bench_args = []
135+
136+
i = 0
137+
while i < len(args):
138+
arg = args[i]
139+
if arg == '-i':
140+
i += 1
141+
iterations = _as_int(args[i])
142+
elif arg.startswith("--iterations"):
143+
iterations = _as_int(arg.split("=")[1])
144+
elif arg == '-w':
145+
i += 1
146+
warmup = _as_int(args[i])
147+
elif arg.startswith("--warmup"):
148+
warmup = _as_int(arg.split("=")[1])
149+
elif bench_file is None:
150+
bench_file = arg
151+
else:
152+
bench_args.append(arg)
153+
i += 1
154+
155+
BenchRunner(bench_file, bench_args=bench_args, iterations=iterations, warmup=warmup).run()
156+
157+
158+
if __name__ == '__main__':
159+
run_benchmark(sys.argv[0], sys.argv[1:])

graalpython/benchmarks/src/micro/arith-binop.py

+2-13
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
2323
# OF THE POSSIBILITY OF SUCH DAMAGE.
2424
# arithmetic ops (partially extracted from spectralnorm)
25-
import time
2625

2726

2827
def docompute(num):
@@ -37,20 +36,10 @@ def docompute(num):
3736

3837

3938
def measure(num):
40-
print("Start timing...")
41-
start = time.time()
42-
4339
for run in range(num):
4440
sum_ = docompute(10000) # 10000
45-
4641
print("sum", sum_)
4742

48-
duration = "%.3f\n" % (time.time() - start)
49-
print("arith-binop: " + duration)
50-
51-
52-
print('warming up ...')
53-
for run in range(2000):
54-
docompute(10) # 1000
5543

56-
measure(5)
44+
def __benchmark__(num=5):
45+
measure(num)

graalpython/benchmarks/src/micro/arith-modulo.py

+2-12
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
2323
# OF THE POSSIBILITY OF SUCH DAMAGE.
2424
# modulo ops
25-
import time
2625

2726

2827
def docompute(num):
@@ -42,20 +41,11 @@ def docompute(num):
4241

4342

4443
def measure(num):
45-
print("Start timing...")
46-
start = time.time()
47-
4844
for run in range(num):
4945
sum = docompute(5000) # 5000
5046

5147
print("sum", sum)
5248

53-
duration = "%.3f\n" % (time.time() - start)
54-
print("arith-modulo: " + duration)
55-
56-
57-
print('warming up ...')
58-
for run in range(2000):
59-
docompute(10) # 1000
6049

61-
measure(50)
50+
def __benchmark__(num=50):
51+
measure(50)

graalpython/benchmarks/src/micro/attribute-access-polymorphic.py

+2-15
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
2323
# OF THE POSSIBILITY OF SUCH DAMAGE.
2424
# micro benchmark: attribute access polymorphic inspired by richards
25-
import time
2625

2726
iteration = 20000 # 50000
2827

@@ -73,23 +72,11 @@ def do_stuff():
7372

7473

7574
def measure(num):
76-
for i in range(3):
77-
do_stuff()
78-
79-
print("Start timing...")
80-
start = time.time()
81-
8275
for i in range(num): # 50000
8376
result = do_stuff()
8477

8578
print(result)
86-
duration = "%.3f\n" % (time.time() - start)
87-
print("attribute-access-polymorphic: " + duration)
88-
8979

90-
# warm up
91-
print('warming up ...')
92-
for i in range(1000):
93-
do_stuff()
9480

95-
measure(1000)
81+
def __benchmark__(num=1000):
82+
measure(num)

graalpython/benchmarks/src/micro/attribute-access.py

+3-13
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
2323
# OF THE POSSIBILITY OF SUCH DAMAGE.
2424
# micro benchmark: attribute access
25-
import time
2625

2726
iteration = 50000 # 50000
2827

@@ -41,20 +40,11 @@ def do_stuff(foo):
4140

4241

4342
def measure(num):
44-
print("Start timing...")
45-
start = time.time()
46-
4743
for i in range(num): # 50000
4844
result = do_stuff(Foo(42))
4945

5046
print(result)
51-
duration = "%.3f\n" % (time.time() - start)
52-
print("attribute-access: " + duration)
53-
54-
55-
# warm up
56-
print('warming up ...')
57-
for i in range(2000):
58-
do_stuff(Foo(42))
47+
5948

60-
measure(5000)
49+
def __benchmark__(num=5000):
50+
measure(num)

graalpython/benchmarks/src/micro/attribute-bool.py

+2-12
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
2323
# OF THE POSSIBILITY OF SUCH DAMAGE.
2424
# micro benchmark: boolean attribute access
25-
import time
2625

2726
iteration = 500000
2827

@@ -66,20 +65,11 @@ def do_stuff():
6665

6766

6867
def measure(num):
69-
print("Start timing...")
70-
start = time.time()
71-
7268
for i in range(num):
7369
result = do_stuff()
7470

7571
print(result)
76-
duration = "%.3f\n" % (time.time() - start)
77-
print("attribute-bool: " + duration)
78-
7972

80-
# warm up
81-
print('warming up ...')
82-
for i in range(2000):
83-
do_stuff()
8473

85-
measure(3000)
74+
def __benchmark__(num=3000):
75+
measure(num)

graalpython/benchmarks/src/micro/boolean-logic.py

+2-12
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
2323
# OF THE POSSIBILITY OF SUCH DAMAGE.
2424
# micro benchmark: method call polymorphic inspired by richards
25-
import time
2625

2726
iteration = 50000
2827

@@ -85,20 +84,11 @@ def no_object_do_stuff():
8584

8685

8786
def measure(num):
88-
print("Start timing...")
89-
start = time.time()
90-
9187
for i in range(num): # 50000
9288
result = do_stuff()
9389

9490
print(result)
95-
duration = "%.3f\n" % (time.time() - start)
96-
print("boolean-logic: " + duration)
97-
9891

99-
# warm up
100-
print('warming up ...')
101-
for i in range(1000):
102-
do_stuff()
10392

104-
measure(1000)
93+
def __benchmark__(num=1000):
94+
measure(num)

graalpython/benchmarks/src/micro/builtin-len-tuple.py

+2-14
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
2323
# OF THE POSSIBILITY OF SUCH DAMAGE.
2424
# builtin function len()
25-
import time
26-
2725

2826
def call_len(num, ll):
2927
length = 0
@@ -34,21 +32,11 @@ def call_len(num, ll):
3432

3533

3634
def measure():
37-
print("Start timing...")
38-
start = time.time()
39-
4035
ll = tuple(range(1000))
4136
length = call_len(1000000000, ll) # 1000000
4237

4338
print("Final length ", length)
4439

45-
duration = "%.3f\n" % (time.time() - start)
46-
print("builtin-len-tuple: " + duration)
47-
48-
49-
# warm up
50-
print('warming up ...')
51-
for run in range(10000):
52-
call_len(50000, (1, 2, 3, 4, 5))
5340

54-
measure()
41+
def __benchmark__(*args):
42+
measure()

0 commit comments

Comments
 (0)