Skip to content

Commit 8de4f13

Browse files
committed
Expose the record writer for validating arbitrary files
Adds TestRecordWriter class to enable testing and validation of memray record files by allowing direct writing of test records. This provides a way to create controlled test files with known contents for validating the file format and reader functionality. The implementation supports writing all record types including memory snapshots, allocations, frames, and thread information, making it possible to test edge cases and complex scenarios that would be difficult to trigger in normal operation.
1 parent b6fd496 commit 8de4f13

File tree

5 files changed

+514
-67
lines changed

5 files changed

+514
-67
lines changed

setup.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,12 +267,19 @@ def build_js_files(self):
267267
name="memray._test_utils",
268268
sources=[
269269
"src/memray/_memray_test_utils.pyx",
270+
"src/memray/_memray/sink.cpp",
271+
"src/memray/_memray/records.cpp",
272+
"src/memray/_memray/snapshot.cpp",
273+
"src/memray/_memray/record_writer.cpp",
274+
"src/memray/_memray/hooks.cpp",
275+
"src/memray/_memray/logging.cpp",
270276
],
271277
language="c++",
272278
extra_compile_args=["-std=c++17", "-Wall", *EXTRA_COMPILE_ARGS],
273279
extra_link_args=["-std=c++17", *EXTRA_LINK_ARGS],
274280
define_macros=DEFINE_MACROS,
275281
undef_macros=UNDEF_MACROS,
282+
**library_flags,
276283
)
277284

278285
MEMRAY_INJECT_EXTENSION = Extension(

src/memray/_memray/record_writer.pxd

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,36 @@
1+
from _memray.records cimport AllocationRecord
12
from _memray.records cimport FileFormat
3+
from _memray.records cimport FramePop
4+
from _memray.records cimport FramePush
5+
from _memray.records cimport HeaderRecord
6+
from _memray.records cimport ImageSegments
7+
from _memray.records cimport MemoryRecord
8+
from _memray.records cimport NativeAllocationRecord
9+
from _memray.records cimport ThreadRecord
10+
from _memray.records cimport UnresolvedNativeFrame
11+
from _memray.records cimport thread_id_t
212
from _memray.sink cimport Sink
313
from libcpp cimport bool
414
from libcpp.memory cimport unique_ptr
515
from libcpp.string cimport string
16+
from libcpp.vector cimport vector
617

718

8-
cdef extern from "record_writer.h" namespace "memray::api":
19+
cdef extern from "record_writer.h" namespace "memray::tracking_api":
920
cdef cppclass RecordWriter:
10-
pass
21+
bool writeRecord(const MemoryRecord& record) except+
22+
bool writeRecord(const UnresolvedNativeFrame& record) except+
23+
bool writeMappings(const vector[ImageSegments]& mappings) except+
24+
bool writeThreadSpecificRecord(thread_id_t tid, const FramePop& record) except+
25+
bool writeThreadSpecificRecord(thread_id_t tid, const FramePush& record) except+
26+
bool writeThreadSpecificRecord(thread_id_t tid, const AllocationRecord& record) except+
27+
bool writeThreadSpecificRecord(thread_id_t tid, const NativeAllocationRecord& record) except+
28+
bool writeThreadSpecificRecord(thread_id_t tid, const ThreadRecord& record) except+
29+
bool writeHeader(bool seek_to_start) except+
30+
bool writeTrailer() except+
31+
void setMainTidAndSkippedFrames(thread_id_t main_tid, size_t skipped_frames_on_main_tid) except+
32+
unique_ptr[RecordWriter] cloneInChildProcess() except+
33+
1134
cdef unique_ptr[RecordWriter] createRecordWriter(
1235
unique_ptr[Sink],
1336
string command_line,

src/memray/_memray/records.pxd

Lines changed: 114 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -5,73 +5,122 @@ from libcpp.string cimport string
55
from libcpp.vector cimport vector
66

77

8+
cdef extern from "hooks.h" namespace "memray::hooks":
9+
cdef enum Allocator:
10+
MALLOC "memray::hooks::Allocator::MALLOC"
11+
CALLOC "memray::hooks::Allocator::CALLOC"
12+
REALLOC "memray::hooks::Allocator::REALLOC"
13+
VALLOC "memray::hooks::Allocator::VALLOC"
14+
ALIGNED_ALLOC "memray::hooks::Allocator::ALIGNED_ALLOC"
15+
POSIX_MEMALIGN "memray::hooks::Allocator::POSIX_MEMALIGN"
16+
MEMALIGN "memray::hooks::Allocator::MEMALIGN"
17+
PVALLOC "memray::hooks::Allocator::PVALLOC"
18+
FREE "memray::hooks::Allocator::FREE"
19+
PYMALLOC_MALLOC "memray::hooks::Allocator::PYMALLOC_MALLOC"
20+
PYMALLOC_CALLOC "memray::hooks::Allocator::PYMALLOC_CALLOC"
21+
PYMALLOC_REALLOC "memray::hooks::Allocator::PYMALLOC_REALLOC"
22+
PYMALLOC_FREE "memray::hooks::Allocator::PYMALLOC_FREE"
23+
824
cdef extern from "records.h" namespace "memray::tracking_api":
9-
ctypedef unsigned long thread_id_t
10-
ctypedef size_t frame_id_t
11-
12-
struct Frame:
13-
string function_name
14-
string filename
15-
int lineno
16-
17-
struct TrackerStats:
18-
size_t n_allocations
19-
size_t n_frames
20-
long long start_time
21-
long long end_time
22-
23-
cdef enum FileFormat:
24-
ALL_ALLOCATIONS 'memray::tracking_api::FileFormat::ALL_ALLOCATIONS'
25-
AGGREGATED_ALLOCATIONS 'memray::tracking_api::FileFormat::AGGREGATED_ALLOCATIONS'
26-
27-
struct HeaderRecord:
28-
int version
29-
bool native_traces
30-
FileFormat file_format
31-
TrackerStats stats
32-
string command_line
33-
int pid
34-
size_t main_tid
35-
size_t skipped_frames_on_main_tid
36-
int python_allocator
37-
bool trace_python_allocators
38-
39-
cdef cppclass Allocation:
40-
thread_id_t tid
41-
uintptr_t address
42-
size_t size
43-
Allocator allocator
44-
frame_id_t native_frame_id
45-
size_t frame_index
46-
size_t native_segment_generation
47-
size_t n_allocations
48-
49-
object toPythonObject()
50-
51-
cdef cppclass AggregatedAllocation:
52-
thread_id_t tid
53-
Allocator allocator
54-
frame_id_t native_frame_id
55-
size_t frame_index
56-
size_t native_segment_generation
57-
58-
size_t n_allocations_in_high_water_mark
59-
size_t n_allocations_leaked
60-
size_t bytes_in_high_water_mark
61-
size_t bytes_leaked
62-
63-
Allocation contributionToHighWaterMark()
64-
Allocation contributionToLeaks()
65-
66-
struct MemoryRecord:
67-
unsigned long int ms_since_epoch
68-
size_t rss
69-
70-
struct MemorySnapshot:
71-
unsigned long int ms_since_epoch
72-
size_t rss
73-
size_t heap
25+
ctypedef unsigned long thread_id_t
26+
ctypedef size_t frame_id_t
27+
ctypedef long long millis_t
28+
29+
cdef enum FileFormat:
30+
ALL_ALLOCATIONS
31+
AGGREGATED_ALLOCATIONS
32+
33+
cdef struct MemoryRecord:
34+
unsigned long int ms_since_epoch
35+
size_t rss
36+
37+
cdef struct AllocationRecord:
38+
uintptr_t address
39+
size_t size
40+
Allocator allocator
41+
42+
cdef struct NativeAllocationRecord:
43+
uintptr_t address
44+
size_t size
45+
Allocator allocator
46+
frame_id_t native_frame_id
47+
48+
cdef struct FramePush:
49+
frame_id_t frame_id
50+
51+
cdef struct FramePop:
52+
size_t count
53+
54+
cdef struct ThreadRecord:
55+
const char* name
56+
57+
cdef struct Segment:
58+
uintptr_t vaddr
59+
size_t memsz
60+
61+
cdef struct ImageSegments:
62+
string filename
63+
uintptr_t addr
64+
vector[Segment] segments
65+
66+
cdef struct UnresolvedNativeFrame:
67+
uintptr_t ip
68+
frame_id_t index
69+
70+
struct Frame:
71+
string function_name
72+
string filename
73+
int lineno
74+
75+
struct TrackerStats:
76+
size_t n_allocations
77+
size_t n_frames
78+
long long start_time
79+
long long end_time
80+
81+
struct HeaderRecord:
82+
int version
83+
bool native_traces
84+
FileFormat file_format
85+
TrackerStats stats
86+
string command_line
87+
int pid
88+
size_t main_tid
89+
size_t skipped_frames_on_main_tid
90+
int python_allocator
91+
bool trace_python_allocators
92+
93+
cdef cppclass Allocation:
94+
thread_id_t tid
95+
uintptr_t address
96+
size_t size
97+
Allocator allocator
98+
frame_id_t native_frame_id
99+
size_t frame_index
100+
size_t native_segment_generation
101+
size_t n_allocations
102+
103+
object toPythonObject()
104+
105+
cdef cppclass AggregatedAllocation:
106+
thread_id_t tid
107+
Allocator allocator
108+
frame_id_t native_frame_id
109+
size_t frame_index
110+
size_t native_segment_generation
111+
112+
size_t n_allocations_in_high_water_mark
113+
size_t n_allocations_leaked
114+
size_t bytes_in_high_water_mark
115+
size_t bytes_leaked
116+
117+
Allocation contributionToHighWaterMark()
118+
Allocation contributionToLeaks()
74119

120+
struct MemorySnapshot:
121+
unsigned long int ms_since_epoch
122+
size_t rss
123+
size_t heap
75124

76125
cdef extern from "<optional>":
77126
# Cython doesn't have libcpp.optional yet, so just declare this opaquely.

0 commit comments

Comments
 (0)