Skip to content

Commit ef8fbb0

Browse files
committed
working on pypy verion, relocations and other changes
1 parent 5807efe commit ef8fbb0

18 files changed

+268
-154
lines changed

README.md

+8-5
Original file line numberDiff line numberDiff line change
@@ -31,28 +31,31 @@ Setting up development can be done using the following commands:
3131
$ python setup.py develop
3232

3333
Now it is time to write a test and implement your feature. If you want
34-
your changes to affect vmprof.com, please head over to
34+
your changes to affect vmprof.com, head over to
3535
https://github.com/vmprof/vmprof-server and follow the setup instructions.
3636

37-
Please also consult our section for development at https://vmprof.readthedocs.org.
37+
Consult our section for development at https://vmprof.readthedocs.org for more
38+
information.
3839

3940
## vmprofshow
4041

41-
`vmprofshow` is a command line tool that comes with **VMprof** which can read profile files generated by **VMprof** and produce a nicely formatted output.
42+
`vmprofshow` is a command line tool that comes with **VMProf** which can read profile files
43+
and produce a formatted output.
4244

43-
Here is an example of how to use:
45+
Here is an example of how to use `vmprofshow`:
4446

4547
Clone the vmprof repo first to use a minimalistic cpuburn.py:
4648

4749
```console
4850
git clone https://github.com/vmprof/vmprof-python
4951
cd vmprof-python
52+
pip install .
5053
```
5154

5255
Run that smallish program which burns CPU cycles (with vmprof enabled):
5356

5457
```console
55-
python vmprof/test/cpuburn.py
58+
pypy vmprof/test/cpuburn.py
5659
```
5760

5861
This will produce a profile file `vmprof_cpuburn.dat`.

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
'src/_vmprof.c',
5959
'src/machine.c',
6060
'src/compat.c',
61-
'src/stack.c',
61+
'src/vmp_stack.c',
6262
] + extra_source_files,
6363
depends=[
6464
'src/vmprof_main.h',

src/_vmprof.c

+6-53
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ static volatile int is_enabled = 0;
2121
#else
2222
#include "vmprof_main_win32.h"
2323
#endif
24-
#include "stack.h"
24+
#include "vmp_stack.h"
2525

2626
static destructor Original_code_dealloc = 0;
2727
PyObject* (*_default_eval_loop)(PyFrameObject *, int) = 0;
@@ -32,12 +32,12 @@ __attribute__((disable_tail_calls))
3232
#elif defined(__GNUC__)
3333
__attribute__((optimize("O1")))
3434
#endif
35-
PyObject* vmprof_eval(PyFrameObject *f, int throwflag)
35+
PY_EVAL_RETURN_T * vmprof_eval(PY_STACK_FRAME_T *f, int throwflag)
3636
{
3737
#ifdef X86_64
38-
register PyFrameObject * callee_saved asm("rbx");
38+
register PY_STACK_FRAME_T * callee_saved asm("rbx");
3939
#elif defined(X86_32)
40-
register PyFrameObject * callee_saved asm("edi");
40+
register PY_STACK_FRAME_T * callee_saved asm("edi");
4141
#else
4242
# error "platform not supported"
4343
#endif
@@ -150,30 +150,6 @@ static void cpyprof_code_dealloc(PyObject *co)
150150
Original_code_dealloc(co);
151151
}
152152

153-
#ifdef VMP_SUPPORTS_NATIVE_PROFILING
154-
static void init_cpyprof(int native)
155-
{
156-
// skip this if native should not be enabled
157-
if (!native) {
158-
vmp_native_disable();
159-
return;
160-
}
161-
#if CPYTHON_HAS_FRAME_EVALUATION
162-
PyThreadState *tstate = PyThreadState_GET();
163-
tstate->interp->eval_frame = vmprof_eval;
164-
_default_eval_loop = _PyEval_EvalFrameDefault;
165-
#else
166-
if (vmp_patch_callee_trampoline(PyEval_EvalFrameEx,
167-
vmprof_eval, (void*)&_default_eval_loop) == 0) {
168-
} else {
169-
fprintf(stderr, "FATAL: could not insert trampline, try with --no-native\n");
170-
// TODO dump the first few bytes and tell them to create an issue!
171-
exit(-1);
172-
}
173-
#endif
174-
vmp_native_enable();
175-
}
176-
#endif
177153

178154
void dump_native_symbols(int fileno)
179155
{
@@ -189,22 +165,6 @@ void dump_native_symbols(int fileno)
189165
Py_XDECREF(mod);
190166
}
191167

192-
#ifdef VMP_SUPPORTS_NATIVE_PROFILING
193-
static void disable_cpyprof(void)
194-
{
195-
vmp_native_disable();
196-
#if CPYTHON_HAS_FRAME_EVALUATION
197-
PyThreadState *tstate = PyThreadState_GET();
198-
tstate->interp->eval_frame = _PyEval_EvalFrameDefault;
199-
#else
200-
if (vmp_unpatch_callee_trampoline(PyEval_EvalFrameEx) > 0) {
201-
fprintf(stderr, "FATAL: could not remove trampoline\n");
202-
exit(-1);
203-
}
204-
#endif
205-
dump_native_symbols(vmp_profile_fileno());
206-
}
207-
#endif
208168

209169

210170
static PyObject *enable_vmprof(PyObject* self, PyObject *args)
@@ -229,10 +189,6 @@ static PyObject *enable_vmprof(PyObject* self, PyObject *args)
229189

230190
vmp_profile_lines(lines);
231191

232-
#ifdef VMP_SUPPORTS_NATIVE_PROFILING
233-
init_cpyprof(native);
234-
#endif
235-
236192
if (!Original_code_dealloc) {
237193
Original_code_dealloc = PyCode_Type.tp_dealloc;
238194
PyCode_Type.tp_dealloc = &cpyprof_code_dealloc;
@@ -244,7 +200,7 @@ static PyObject *enable_vmprof(PyObject* self, PyObject *args)
244200
return NULL;
245201
}
246202

247-
if (vmprof_enable(memory) < 0) {
203+
if (vmprof_enable(memory, native) < 0) {
248204
PyErr_SetFromErrno(PyExc_OSError);
249205
return NULL;
250206
}
@@ -265,9 +221,6 @@ disable_vmprof(PyObject *module, PyObject *noarg)
265221
is_enabled = 0;
266222
vmprof_ignore_signals(1);
267223
emit_all_code_objects();
268-
#ifdef VMP_SUPPORTS_NATIVE_PROFILING
269-
disable_cpyprof();
270-
#endif
271224

272225
if (vmprof_disable() < 0) {
273226
PyErr_SetFromErrno(PyExc_OSError);
@@ -319,7 +272,7 @@ sample_stack_now(PyObject *module, PyObject *args)
319272
vmprof_ignore_signals(0);
320273
return NULL;
321274
}
322-
entry_count = vmp_walk_and_record_stack(tstate->frame, m, MAX_STACK_DEPTH-1, 0);
275+
entry_count = vmp_walk_and_record_stack(tstate->frame, m, MAX_STACK_DEPTH-1, 0, 0);
323276

324277
for (i = 0; i < entry_count; i++) {
325278
routine_ip = m[i];

src/_vmprof.h

+2-35
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
#pragma once
22

3-
#include <Python.h>
4-
#include <frameobject.h>
3+
#include "vmprof.h"
54

65
#ifdef VMPROF_WINDOWS
76
#include "msiinttypes/inttypes.h"
87
#include "msiinttypes/stdint.h"
98
#else
109
#include <inttypes.h>
1110
#include <stdint.h>
11+
#include <stddef.h>
1212
#endif
1313

1414
/**
@@ -43,37 +43,4 @@
4343

4444
#define CPYTHON_HAS_FRAME_EVALUATION PY_VERSION_HEX >= 0x30600B0
4545

46-
PyObject* vmprof_eval(PyFrameObject *f, int throwflag);
47-
48-
#ifdef VMPROF_UNIX
49-
#define VMP_SUPPORTS_NATIVE_PROFILING
50-
#endif
51-
52-
#ifdef __x86_64__
53-
#define X86_64
54-
#elif defined(__i386__)
55-
#define X86_32
56-
#endif
57-
58-
#define MARKER_STACKTRACE '\x01'
59-
#define MARKER_VIRTUAL_IP '\x02'
60-
#define MARKER_TRAILER '\x03'
61-
#define MARKER_INTERP_NAME '\x04' /* deprecated */
62-
#define MARKER_HEADER '\x05'
63-
#define MARKER_TIME_N_ZONE '\x06'
64-
#define MARKER_META '\x07'
65-
#define MARKER_NATIVE_SYMBOLS '\x08'
66-
67-
#define VERSION_BASE '\x00'
68-
#define VERSION_THREAD_ID '\x01'
69-
#define VERSION_TAG '\x02'
70-
#define VERSION_MEMORY '\x03'
71-
#define VERSION_MODE_AWARE '\x04'
72-
#define VERSION_DURATION '\x05'
73-
#define VERSION_TIMESTAMP '\x06'
74-
75-
#define PROFILE_MEMORY '\x01'
76-
#define PROFILE_LINES '\x02'
77-
#define PROFILE_NATIVE '\x04'
78-
7946
int vmp_write_all(const char *buf, size_t bufsize);

src/compat.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
#include "compat.h"
22

3-
#include "_vmprof.h"
4-
3+
#include <string.h>
4+
#include <assert.h>
55
#if VMPROF_WINDOWS
66
#define WIN32_LEAN_AND_MEAN
77
#include <Windows.h>
8+
#else
9+
#include <time.h>
10+
#include <sys/time.h>
811
#endif
912

1013
static int _vmp_profile_fileno = -1;

src/compat.h

+13-11
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
#pragma once
22

3-
INCLUDE_MODULE_HEADER
3+
#include "vmprof.h"
44

5-
#if PY_MAJOR_VERSION >= 3
6-
#define PyStr_AS_STRING PyBytes_AS_STRING
7-
#define PyStr_GET_SIZE PyBytes_GET_SIZE
8-
#define PyStr_NEW PyUnicode_FromString
9-
#define PyLong_NEW PyLong_FromLong
10-
#else
11-
#define PyStr_AS_STRING PyString_AS_STRING
12-
#define PyStr_GET_SIZE PyString_GET_SIZE
13-
#define PyStr_NEW PyString_FromString
14-
#define PyLong_NEW PyInt_FromLong
5+
#ifndef RPYTHON_VMPROF
6+
# if PY_MAJOR_VERSION >= 3
7+
#define PyStr_AS_STRING PyBytes_AS_STRING
8+
#define PyStr_GET_SIZE PyBytes_GET_SIZE
9+
#define PyStr_NEW PyUnicode_FromString
10+
#define PyLong_NEW PyLong_FromLong
11+
# else
12+
#define PyStr_AS_STRING PyString_AS_STRING
13+
#define PyStr_GET_SIZE PyString_GET_SIZE
14+
#define PyStr_NEW PyString_FromString
15+
#define PyLong_NEW PyInt_FromLong
16+
# endif
1517
#endif
1618

1719
int vmp_write_all(const char *buf, size_t bufsize);

src/machine.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include "machine.h"
22

3-
#include "_vmprof.h"
3+
#include "vmprof.h"
44
#include <stdio.h>
55

66
int vmp_machine_bits(void)

src/rss_unix.h

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#include <stdlib.h>
2+
13
/* On normal Unices we can get RSS from '/proc/<pid>/status'. */
24
static int proc_file = -1;
35

src/symboltable.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
#include "symboltable.h"
22

3-
#include "_vmprof.h"
3+
#include "vmprof.h"
44
#include "machine.h"
55

6+
#include <string.h>
67
#include <stdio.h>
78
#include <stdlib.h>
89

10+
#include <dlfcn.h>
911
#ifdef VMPROF_LINUX
10-
#define _GNU_SOURCE 1
1112
#include <link.h>
1213
#endif
13-
#include <dlfcn.h>
1414

1515
#ifdef _PY_TEST
1616
#define LOG(...) printf(__VA_ARGS__)
@@ -220,7 +220,7 @@ int vmp_resolve_addr(void * addr, char * name, int name_len, int * lineno, char
220220
name[name_len-1] = 0;
221221
}
222222
lookup_vmprof_debug_info(name, info.dli_fbase, srcfile, srcfile_len, lineno);
223-
#elif defined(__unix__)
223+
#elif defined(VMPROF_LINUX)
224224
if (bstate == NULL) {
225225
bstate = backtrace_create_state (NULL, 1, backtrace_error_cb, NULL);
226226
}

src/symboltable.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
#pragma once
22

3+
#define _GNU_SOURCE 1
4+
35
/**
46
* Extract all the known symbols from the current process and
57
* log them to the file descriptor. To read them see binary.py funcs:
68
*
79
* # encoded as a mapping
810
* addr = read_word(fd); name = read_string(fd)
911
*
10-
* A) It is not allowed to have two addresses (virtual ones only valid
12+
* A) It is not allowed to have two addresses (virtual ones are only valid
1113
* in the curent process) in this mapping to point to several symbols.
1214
* B) No duplicates are logged
15+
*
16+
* Deprecated, do not use
1317
*/
1418
void dump_all_known_symbols(int fd);
1519

0 commit comments

Comments
 (0)