1
- use cpython:: Python ;
2
1
use criterion:: measurement:: WallTime ;
3
2
use criterion:: {
4
3
criterion_group, criterion_main, BatchSize , BenchmarkGroup , BenchmarkId , Criterion , Throughput ,
@@ -19,31 +18,32 @@ pub struct MicroBenchmark {
19
18
20
19
fn bench_cpython_code ( group : & mut BenchmarkGroup < WallTime > , bench : & MicroBenchmark ) {
21
20
let gil = cpython:: Python :: acquire_gil ( ) ;
22
- let python = gil. python ( ) ;
21
+ let py = gil. python ( ) ;
23
22
24
- let bench_func = |( python , code ) : ( Python , String ) | {
25
- let res: cpython :: PyResult < ( ) > = python . run ( & code, None , None ) ;
23
+ let bench_func = |( code , globals , locals ) | {
24
+ let res = cpy_run_code ( py , & code, & globals , & locals ) ;
26
25
if let Err ( e) = res {
27
- e. print ( python ) ;
26
+ e. print ( py ) ;
28
27
panic ! ( "Error running microbenchmark" )
29
28
}
30
29
} ;
31
30
32
31
let bench_setup = |iterations| {
33
- let code = if let Some ( idx) = iterations {
34
- // We can't easily modify the locals when running cPython. So we just add the
35
- // loop iterations at the top of the code...
36
- format ! ( "ITERATIONS = {}\n {}" , idx, bench. code)
37
- } else {
38
- ( & bench. code ) . to_string ( )
39
- } ;
32
+ let globals = cpython:: PyDict :: new ( py) ;
33
+ let locals = cpython:: PyDict :: new ( py) ;
34
+ if let Some ( idx) = iterations {
35
+ globals. set_item ( py, "ITERATIONS" , idx) . unwrap ( ) ;
36
+ }
40
37
41
- let res: cpython :: PyResult < ( ) > = python . run ( & bench. setup , None , None ) ;
38
+ let res = py . run ( & bench. setup , Some ( & globals ) , Some ( & locals ) ) ;
42
39
if let Err ( e) = res {
43
- e. print ( python ) ;
40
+ e. print ( py ) ;
44
41
panic ! ( "Error running microbenchmark setup code" )
45
42
}
46
- ( python, code)
43
+ let code = std:: ffi:: CString :: new ( & * bench. code ) . unwrap ( ) ;
44
+ let name = std:: ffi:: CString :: new ( & * bench. name ) . unwrap ( ) ;
45
+ let code = cpy_compile_code ( py, & code, & name) . unwrap ( ) ;
46
+ ( code, globals, locals)
47
47
} ;
48
48
49
49
if bench. iterate {
@@ -64,6 +64,42 @@ fn bench_cpython_code(group: &mut BenchmarkGroup<WallTime>, bench: &MicroBenchma
64
64
}
65
65
}
66
66
67
+ unsafe fn cpy_res (
68
+ py : cpython:: Python < ' _ > ,
69
+ x : * mut python3_sys:: PyObject ,
70
+ ) -> cpython:: PyResult < cpython:: PyObject > {
71
+ cpython:: PyObject :: from_owned_ptr_opt ( py, x) . ok_or_else ( || cpython:: PyErr :: fetch ( py) )
72
+ }
73
+
74
+ fn cpy_compile_code (
75
+ py : cpython:: Python < ' _ > ,
76
+ s : & std:: ffi:: CStr ,
77
+ fname : & std:: ffi:: CStr ,
78
+ ) -> cpython:: PyResult < cpython:: PyObject > {
79
+ unsafe {
80
+ let res =
81
+ python3_sys:: Py_CompileString ( s. as_ptr ( ) , fname. as_ptr ( ) , python3_sys:: Py_file_input ) ;
82
+ cpy_res ( py, res)
83
+ }
84
+ }
85
+
86
+ fn cpy_run_code (
87
+ py : cpython:: Python < ' _ > ,
88
+ code : & cpython:: PyObject ,
89
+ locals : & cpython:: PyDict ,
90
+ globals : & cpython:: PyDict ,
91
+ ) -> cpython:: PyResult < cpython:: PyObject > {
92
+ use cpython:: PythonObject ;
93
+ unsafe {
94
+ let res = python3_sys:: PyEval_EvalCode (
95
+ code. as_ptr ( ) ,
96
+ locals. as_object ( ) . as_ptr ( ) ,
97
+ globals. as_object ( ) . as_ptr ( ) ,
98
+ ) ;
99
+ cpy_res ( py, res)
100
+ }
101
+ }
102
+
67
103
fn bench_rustpy_code ( group : & mut BenchmarkGroup < WallTime > , bench : & MicroBenchmark ) {
68
104
let mut settings = PySettings :: default ( ) ;
69
105
settings. path_list . push ( "Lib/" . to_string ( ) ) ;
0 commit comments