Skip to content

Commit 5dde5d9

Browse files
committed
[GR-11498] Improve performance when calling magic methods of native objects.
PullRequest: graalpython/180
2 parents 20014e8 + 64a4ed3 commit 5dde5d9

File tree

21 files changed

+1369
-134
lines changed

21 files changed

+1369
-134
lines changed
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
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+
code = """
41+
#include "Python.h"
42+
43+
typedef struct {
44+
PyObject_HEAD;
45+
int bState;
46+
uint64_t cnt;
47+
} NativeMagicMethodsObject;
48+
49+
50+
PyObject* nmm_index(PyObject* self) {
51+
return PyLong_FromLong((((NativeMagicMethodsObject*)self)->cnt)++);
52+
}
53+
54+
int nmm_bool(PyObject* self) {
55+
int curState = ((NativeMagicMethodsObject*)self)->bState;
56+
((NativeMagicMethodsObject*)self)->bState = !curState;
57+
return curState;
58+
}
59+
60+
PyObject* nmm_iter(PyObject* self) {
61+
return NULL;
62+
}
63+
64+
65+
static PyNumberMethods NativeMagicMethods_number_methods = {
66+
0,
67+
0,
68+
0,
69+
0,
70+
0,
71+
0,
72+
0,
73+
0,
74+
0,
75+
nmm_bool,
76+
0,
77+
0,
78+
0,
79+
0,
80+
0,
81+
0,
82+
nmm_index,
83+
0,
84+
0,
85+
0,
86+
0,
87+
0,
88+
0,
89+
0,
90+
0,
91+
0,
92+
0,
93+
0,
94+
0,
95+
0,
96+
0,
97+
0,
98+
0,
99+
nmm_index,
100+
101+
0,
102+
0,
103+
104+
};
105+
106+
static struct PyMethodDef NativeMagicMethods_methods[] = {
107+
{NULL, NULL, 0, NULL},
108+
{NULL, NULL, 0, NULL}
109+
};
110+
111+
static PyTypeObject NativeMagicMethodsType = {
112+
PyVarObject_HEAD_INIT(NULL, 0)
113+
"NativeMagicMethods.NativeMagicMethods",
114+
sizeof(NativeMagicMethodsObject), /* tp_basicsize */
115+
0, /* tp_itemsize */
116+
0, /* tp_dealloc */
117+
0,
118+
0,
119+
0,
120+
0, /* tp_reserved */
121+
0,
122+
&NativeMagicMethods_number_methods,
123+
0,
124+
0,
125+
0,
126+
0,
127+
0,
128+
0,
129+
0,
130+
0,
131+
Py_TPFLAGS_DEFAULT,
132+
"",
133+
0, /* tp_traverse */
134+
0, /* tp_clear */
135+
0, /* tp_richcompare */
136+
0, /* tp_weaklistoffset */
137+
nmm_iter, /* tp_iter */
138+
0, /* tp_iternext */
139+
NativeMagicMethods_methods, /* tp_methods */
140+
NULL, /* tp_members */
141+
0, /* tp_getset */
142+
0, /* tp_base */
143+
0, /* tp_dict */
144+
0, /* tp_descr_get */
145+
0, /* tp_descr_set */
146+
0, /* tp_dictoffset */
147+
0, /* tp_init */
148+
PyType_GenericAlloc, /* tp_alloc */
149+
PyType_GenericNew, /* tp_new */
150+
PyObject_Del, /* tp_free */
151+
};
152+
153+
static PyModuleDef NativeMagicMethodsmodule = {
154+
PyModuleDef_HEAD_INIT,
155+
"c_list_iterating_obj_module",
156+
"",
157+
-1,
158+
NULL, NULL, NULL, NULL, NULL
159+
};
160+
161+
PyMODINIT_FUNC
162+
PyInit_c_list_iterating_obj_module(void)
163+
{
164+
PyObject* m;
165+
166+
167+
if (PyType_Ready(&NativeMagicMethodsType) < 0)
168+
return NULL;
169+
170+
171+
m = PyModule_Create(&NativeMagicMethodsmodule);
172+
if (m == NULL)
173+
return NULL;
174+
175+
Py_INCREF(&NativeMagicMethodsType);
176+
PyModule_AddObject(m, "NativeMagicMethods", (PyObject *)&NativeMagicMethodsType);
177+
return m;
178+
}
179+
180+
"""
181+
182+
183+
ccompile("c_list_iterating_obj_module", code)
184+
import c_list_iterating_obj_module
185+
186+
def iterate_list(ll, num):
187+
idxObj = c_list_iterating_obj_module.NativeMagicMethods()
188+
for t in range(num):
189+
item = ll[idxObj]
190+
return item
191+
192+
193+
def measure(num):
194+
last_item = iterate_list(list(range(num)), num)
195+
print("Last item ", last_item)
196+
197+
198+
def __benchmark__(num=1000000):
199+
measure(num)
200+

0 commit comments

Comments
 (0)