1+ # Copyright (c) 2026, 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+ # Utilities for benchmarking GraalPy startup. Creates a C benchmark runner that spawns
41+ # the subprocesses to avoid counting subprocess module overhead into the benchmark
42+ import os
43+ import subprocess
44+ import sys
45+ import tempfile
46+ from pathlib import Path
47+
48+ RUNNER_CODE = '''
49+ #include <stdio.h>
50+ #include <stdlib.h>
51+ #include <unistd.h>
52+ #include <sys/wait.h>
53+
54+ int main(int argc, char *argv[]) {
55+ if (argc < 3) {
56+ return 1;
57+ }
58+ int n = atoi(argv[1]);
59+ if (n <= 0) {
60+ return 1;
61+ }
62+ char **cmd_argv = &argv[2];
63+ for (int i = 0; i < n; ++i) {
64+ pid_t pid = fork();
65+ if (pid < 0) {
66+ perror("fork");
67+ return 1;
68+ } else if (pid == 0) {
69+ execvp(cmd_argv[0], cmd_argv);
70+ perror("execvp");
71+ exit(127); // If exec fails
72+ } else {
73+ int status;
74+ if (waitpid(pid, &status, 0) < 0) {
75+ perror("waitpid");
76+ return 1;
77+ }
78+ }
79+ }
80+ return 0;
81+ }
82+ '''
83+
84+ TMPDIR = tempfile .TemporaryDirectory ()
85+ RUNNER_EXE = None
86+ ORIG_ARGV = None
87+
88+
89+ def setup ():
90+ global RUNNER_EXE
91+ tmpdir = Path (TMPDIR .name )
92+ runner_c = tmpdir / 'runner.c'
93+ runner_c .write_text (RUNNER_CODE )
94+ RUNNER_EXE = tmpdir / 'runner'
95+ subprocess .check_call ([os .environ .get ('CC' , 'gcc' ), runner_c , '-O2' , '-o' , RUNNER_EXE ])
96+
97+ global ORIG_ARGV
98+ ORIG_ARGV = sys .orig_argv
99+ for i , arg in enumerate (ORIG_ARGV ):
100+ if arg .endswith ('.py' ):
101+ ORIG_ARGV = ORIG_ARGV [:i ]
102+ break
103+ try :
104+ ORIG_ARGV .remove ('-snapshot-startup' )
105+ except ValueError :
106+ pass
107+
108+
109+ def teardown ():
110+ TMPDIR .cleanup ()
111+
112+
113+ def run (num , code ):
114+ subprocess .check_call ([
115+ str (RUNNER_EXE ),
116+ str (num ),
117+ * ORIG_ARGV ,
118+ "-I" , # isolate from environment
119+ "-S" , # do not import site
120+ "-B" , # do not attempt to write pyc files
121+ "-u" , # do not add buffering wrappers around output streams
122+ "-c" ,
123+ code
124+ ])
0 commit comments