Skip to content

Commit a50c767

Browse files
timfelfangerer
authored andcommitted
add simple member access benchmark
1 parent 0fe6726 commit a50c767

File tree

2 files changed

+132
-0
lines changed

2 files changed

+132
-0
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from importlib import invalidate_caches
2+
from distutils.core import setup, Extension
3+
__dir__ = __file__.rpartition("/")[0]
4+
5+
6+
def ccompile(name, code):
7+
source_file = '%s/%s.c' % (__dir__, name)
8+
with open(source_file, "w") as f:
9+
f.write(code)
10+
module = Extension(name, sources=[source_file])
11+
args = ['--quiet', 'build', 'install_lib', '-f', '--install-dir=%s' % __dir__]
12+
setup(
13+
script_name='setup',
14+
script_args=args,
15+
name=name,
16+
version='1.0',
17+
description='',
18+
ext_modules=[module]
19+
)
20+
# IMPORTANT:
21+
# Invalidate caches after creating the native module.
22+
# FileFinder caches directory contents, and the check for directory
23+
# changes has whole-second precision, so it can miss quick updates.
24+
invalidate_caches()
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
from . import ccompile
2+
3+
4+
code = """
5+
#include <Python.h>
6+
#include "structmember.h"
7+
8+
typedef struct {
9+
PyObject_HEAD
10+
int number;
11+
} ObjectWithMember;
12+
13+
PyObject* ObjectWithMember_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
14+
ObjectWithMember* self = (ObjectWithMember *)type->tp_alloc(type, 0);
15+
if (self != NULL) {
16+
self->number = 0;
17+
}
18+
return (PyObject *)self;
19+
}
20+
21+
int ObjectWithMember_init(ObjectWithMember* self, PyObject* args, PyObject* kwds) {
22+
if (!PyArg_ParseTuple(args, "i", &self->number)) {
23+
return -1;
24+
}
25+
return 0;
26+
}
27+
28+
static PyMemberDef ObjectWithMember_members[] = {
29+
{"number", T_INT, offsetof(ObjectWithMember, number), 0, ""},
30+
{NULL}
31+
};
32+
33+
static PyTypeObject ObjectWithMemberType = {
34+
PyVarObject_HEAD_INIT(NULL, 0)
35+
"module.ObjectWithMember", /* tp_name */
36+
sizeof(ObjectWithMember), /* tp_basicsize */
37+
0, /* tp_itemsize */
38+
0, /* tp_dealloc */
39+
0, /* tp_print */
40+
0, /* tp_getattr */
41+
0, /* tp_setattr */
42+
0, /* tp_reserved */
43+
0, /* tp_repr */
44+
0, /* tp_as_number */
45+
0, /* tp_as_sequence */
46+
0, /* tp_as_mapping */
47+
0, /* tp_hash */
48+
0, /* tp_call */
49+
0, /* tp_str */
50+
0, /* tp_getattro */
51+
0, /* tp_setattro */
52+
0, /* tp_as_buffer */
53+
Py_TPFLAGS_DEFAULT |
54+
Py_TPFLAGS_BASETYPE, /* tp_flags */
55+
"", /* tp_doc */
56+
0, /* tp_traverse */
57+
0, /* tp_clear */
58+
0, /* tp_richcompare */
59+
0, /* tp_weaklistoffset */
60+
0, /* tp_iter */
61+
0, /* tp_iternext */
62+
0, /* tp_methods */
63+
ObjectWithMember_members, /* tp_members */
64+
0, /* tp_getset */
65+
0, /* tp_base */
66+
0, /* tp_dict */
67+
0, /* tp_descr_get */
68+
0, /* tp_descr_set */
69+
0, /* tp_dictoffset */
70+
(initproc)ObjectWithMember_init, /* tp_init */
71+
0, /* tp_alloc */
72+
ObjectWithMember_new, /* tp_new */
73+
};
74+
75+
static PyModuleDef module = {
76+
PyModuleDef_HEAD_INIT,
77+
"module",
78+
"",
79+
-1,
80+
NULL, NULL, NULL, NULL, NULL
81+
};
82+
83+
PyMODINIT_FUNC
84+
PyInit_c_member_access_module(void) {
85+
if (PyType_Ready(&ObjectWithMemberType) < 0) {
86+
return NULL;
87+
}
88+
89+
PyObject* m = PyModule_Create(&module);
90+
if (m == NULL) {
91+
return NULL;
92+
}
93+
94+
Py_INCREF(&ObjectWithMemberType);
95+
PyModule_AddObject(m, "ObjectWithMember", (PyObject *)&ObjectWithMemberType);
96+
return m;
97+
}
98+
"""
99+
100+
101+
ccompile("c_member_access_module", code)
102+
from . import c_member_access_module
103+
104+
105+
def __benchmark__(num=5):
106+
co = c_member_access_module.ObjectWithMember(42)
107+
for i in range(300000):
108+
co.number

0 commit comments

Comments
 (0)