Skip to content

Commit ba651d9

Browse files
committed
Cleanup codeobject-interpretation benchmark
1 parent 4f5664f commit ba651d9

File tree

2 files changed

+21
-130
lines changed

2 files changed

+21
-130
lines changed

graalpython/com.oracle.graal.python.benchmarks/python/micro/codeobject-interpretation.py

Lines changed: 20 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0
@@ -37,175 +37,66 @@
3737
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3838
# SOFTWARE.
3939
import marshal
40-
import os
41-
import sys
42-
43-
44-
IS_GRAAL = sys.implementation.name == "graalpython"
45-
DIR0 = os.path.dirname(__file__)
46-
47-
48-
if IS_GRAAL:
49-
get_code = lambda n,s: __graalpython__.compile(s, n, "pyc")
50-
else:
51-
def get_code(n,s):
52-
c = compile(s,n,"exec")
53-
import dis
54-
dis.dis(c)
55-
return c
56-
40+
import pydoc_data.topics
5741

58-
CODE = get_code("bench.py", """
42+
# pollute the profile of the bytecode loop
43+
exec("""
5944
import sys
60-
def foo():
61-
pass
45+
def foo(): pass
6246
len(sys.__name__)
6347
print(sys, flush=False)
6448
pass
6549
""")
6650

67-
# pollute the profile of the bytecode loop
68-
exec(CODE)
69-
70-
71-
# We're making sure that each code object is a separate call target. This is to
72-
# simulate we are loading SIMULATED_FILECOUNT modules, because each module is
73-
# potentially a lot of code but only gets executed once
74-
RETURN_NONE = [100, 0, 83, 0]
75-
BYTECODE_COUNT = 200
76-
SIMULATED_FILECOUNT = 1000
77-
CODE = []
78-
79-
80-
def generate_code(name, code_to_repeat, **kwargs):
81-
filename = os.path.join(DIR0, name)
82-
if not IS_GRAAL and False:
83-
# generate our code files only with cpython
84-
def foo(): pass
85-
code = foo.__code__
86-
cnt = int(2 * BYTECODE_COUNT / len(code_to_repeat))
87-
newcode = code.replace(co_code=bytes(bytearray(code_to_repeat * cnt + RETURN_NONE)), **kwargs)
88-
with open(filename, "wb") as f:
89-
marshal.dump(newcode, f)
90-
# pollute the profile for the bytecode loop
91-
with open(filename, "rb") as f:
92-
exec(marshal.load(f))
93-
return filename
94-
95-
96-
BYTECODE_FILES = [
97-
generate_code("nop", [9, 0]),
98-
generate_code("pushpop", [100, 0, 1, 0]),
99-
generate_code("negative_one", [100, 1, 11, 0, 1, 0], co_consts=(None, 1,)),
100-
generate_code("load_fast", [
101-
100, 0, # load None
102-
125, 0, # store fast 0
103-
124, 0, # load fast 0
104-
1, 0, # pop top
105-
], co_varnames=('x',)),
106-
]
107-
108-
109-
110-
for _ in range(0, SIMULATED_FILECOUNT, len(BYTECODE_FILES)):
111-
for filename in BYTECODE_FILES:
112-
with open(filename, "rb") as f:
113-
CODE.append(marshal.load(f))
114-
115-
11651
CODESTR1 = "\n".join(["""
11752
# import sys
11853
def foo(): pass
11954
len(foo.__name__)
12055
"""] * 100)
56+
12157
CODESTR2 = "\n".join(["""
12258
def bar(): pass
12359
x = None
12460
len([])
12561
y = x
12662
"""] * 100)
127-
import pydoc_data.topics
63+
12864
with open(pydoc_data.topics.__file__, "r") as f:
12965
CODESTR3 = f.read()
130-
TEST_WITH_BYTECODE = False # False to test with AST
131-
if IS_GRAAL and TEST_WITH_BYTECODE:
132-
JUST_PYC_1 = __graalpython__.compile(CODESTR1, "1", "pyc-nocompile")
133-
JUST_PYC_2 = __graalpython__.compile(CODESTR1, "2", "pyc-nocompile")
134-
JUST_PYC_3 = __graalpython__.compile(CODESTR3, pydoc_data.topics.__file__, "pyc-nocompile")
135-
else:
136-
JUST_PYC_1 = marshal.dumps(compile(CODESTR1, "1", "exec"))
137-
JUST_PYC_2 = marshal.dumps(compile(CODESTR2, "2", "exec"))
138-
JUST_PYC_3 = marshal.dumps(compile(CODESTR3, pydoc_data.topics.__file__, "exec"))
13966

67+
JUST_PYC_1 = marshal.dumps(compile(CODESTR1, "1", "exec"))
68+
JUST_PYC_2 = marshal.dumps(compile(CODESTR2, "2", "exec"))
69+
JUST_PYC_3 = marshal.dumps(compile(CODESTR3, pydoc_data.topics.__file__, "exec"))
14070

141-
MORE_CODEOBJECTS = []
71+
CODEOBJECTS = []
14272

14373

14474
def __setup__(num):
14575
__cleanup__(num)
14676

14777

14878
def __cleanup__(num):
149-
import time
150-
s = time.time()
151-
MORE_CODEOBJECTS.clear()
79+
CODEOBJECTS.clear()
15280
for _ in range(0, num, 3):
153-
MORE_CODEOBJECTS.append(marshal.loads(JUST_PYC_1))
154-
MORE_CODEOBJECTS.append(marshal.loads(JUST_PYC_2))
155-
MORE_CODEOBJECTS.append(marshal.loads(JUST_PYC_3))
156-
print(f"Resetting {len(MORE_CODEOBJECTS)} took {time.time() - s} seconds")
157-
158-
159-
BYTECODE_FILE_DATA = []
160-
for filename in BYTECODE_FILES:
161-
with open(filename, "rb") as f:
162-
BYTECODE_FILE_DATA.append(f.read())
81+
CODEOBJECTS.append(marshal.loads(JUST_PYC_1))
82+
CODEOBJECTS.append(marshal.loads(JUST_PYC_2))
83+
CODEOBJECTS.append(marshal.loads(JUST_PYC_3))
16384

16485

16586
def measure(num):
16687
for i in range(num):
167-
# Enable this to benchmark GraalPython code deserialization SST vs
168-
# bytecode. Switch out the mode in the global setup above
169-
# marshal.loads(JUST_PYC_1); marshal.loads(JUST_PYC_2); marshal.loads(JUST_PYC_3)
170-
171-
# Enable this to measure executing different modules in AST vs bytecode
172-
exec(MORE_CODEOBJECTS[i])
88+
exec(CODEOBJECTS[i])
17389

174-
# Enable this to measure just unmarshalling
175-
# marshal.loads(BYTECODE_FILE_DATA[i % len(BYTECODE_FILE_DATA)])
17690

177-
# Enable this to measure just loading file data
178-
# with open(BYTECODE_FILES[i % len(BYTECODE_FILES)], "rb") as f:
179-
# f.read()
180-
181-
# Enable this to measure loading all the modules
182-
# with open(BYTECODE_FILES[i % len(BYTECODE_FILES)], "rb") as f:
183-
# marshal.loads(f.read())
184-
185-
# Enable this to measure executing different modules
186-
# exec(CODE[i % len(CODE)])
187-
188-
# Enable this to measure unmarshalling and executing code
189-
# exec(marshal.loads(BYTECODE_FILE_DATA[i % len(BYTECODE_FILE_DATA)]))
190-
191-
# Enable this to measure all three, reading file, loading data, and executing
192-
# with open(BYTECODE_FILES[i % len(BYTECODE_FILES)], "rb") as f:
193-
# exec(marshal.loads(f.read()))
194-
195-
196-
def __benchmark__(num=10_000):
91+
def __benchmark__(num=2000):
19792
measure(num)
19893

199-
200-
print("Benchmark file loaded")
201-
202-
20394
# I've written the bytecode benchmark to simulate loading thousands of modules. I
204-
# always execute 10_000 iterations, to make it somewhat like loading a big
95+
# always execute thousands of iterations, to make it somewhat like loading a big
20596
# project with many pyc files, but not so large that the compiler would have time
20697
# to compile many of the operations involved in loading code.
20798
#
208-
# If we compare unmarshaling a code object from a bytes that has bytecode vs one
99+
# If we compare unmarshalling a code object from a bytes that has bytecode vs one
209100
# that has SST, we see that unmarshalling 10_000 bytecode code objects is 2-3x
210101
# faster than unmarshalling the SST. This is for two bits of code with 300 lines
211102
# of statements (creating functions, imports, assignments, calling
@@ -227,7 +118,7 @@ def __benchmark__(num=10_000):
227118
# Opening the files *and* loading the bytecode data yields that CPython is ~14x
228119
# faster than us.
229120
#
230-
# Now, if we preload that artificial code before the benchmark and just execut
121+
# Now, if we preload that artificial code before the benchmark and just execute
231122
# those code objects 10_000 times, CPython is a whopping 20-30x faster than we
232123
# are. But the numbers are so small, it's hard to say (CPython 0.006-0.008s,
233124
# Graal 0.16-0.19s). OTOH, it's hard to argue that we would ever load more

mx.graalpython/mx_graalpython_bench_param.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@
106106
'tuple-indexing-from-constructor': ITER_10 + ['10000000'],
107107
'tuple-indexing-from-literal': ITER_10 + ['10000000'],
108108
'repeated-import': ITER_10 + ['10000000'],
109-
'codeobject-interpretation': ITER_100 + ['10000'],
109+
'codeobject-interpretation': ITER_10 + ['2000'],
110110
}
111111

112112
MICRO_BENCHMARKS_SMALL = {

0 commit comments

Comments
 (0)