@@ -65,25 +65,86 @@ get_ts()
6565#endif
6666}
6767
68+ static inline long
69+ get_buffered_entry_count (TracerObject * self )
70+ {
71+ if (self -> buffer_tail_idx >= self -> buffer_head_idx ) {
72+ return self -> buffer_tail_idx - self -> buffer_head_idx ;
73+ }
74+ return self -> buffer_size - self -> buffer_head_idx + self -> buffer_tail_idx ;
75+ }
76+
77+ static int
78+ grow_buffer (TracerObject * self )
79+ {
80+ long curr_entries = self -> buffer_size - 1 ;
81+ long new_entries = curr_entries * 2 ;
82+ long buffered_entries = get_buffered_entry_count (self );
83+ struct EventNode * new_buffer = NULL ;
84+
85+ if (self -> max_buffer_entries > 0 && new_entries > self -> max_buffer_entries ) {
86+ new_entries = self -> max_buffer_entries ;
87+ }
88+
89+ if (new_entries <= curr_entries ) {
90+ return -1 ;
91+ }
92+
93+ new_buffer = (struct EventNode * ) PyMem_Calloc (new_entries + 1 , sizeof (struct EventNode ));
94+ if (!new_buffer ) {
95+ return -1 ;
96+ }
97+
98+ for (long i = 0 ; i < buffered_entries ; i ++ ) {
99+ long src_idx = self -> buffer_head_idx + i ;
100+ if (src_idx >= self -> buffer_size ) {
101+ src_idx -= self -> buffer_size ;
102+ }
103+ new_buffer [i ] = self -> buffer [src_idx ];
104+ }
105+
106+ PyMem_FREE (self -> buffer );
107+ self -> buffer = new_buffer ;
108+ self -> buffer_size = new_entries + 1 ;
109+ self -> buffer_head_idx = 0 ;
110+ self -> buffer_tail_idx = buffered_entries ;
111+ self -> total_entries = buffered_entries ;
112+
113+ return 0 ;
114+ }
115+
68116static inline struct EventNode *
69117get_next_node (TracerObject * self )
70118{
71119 struct EventNode * node = NULL ;
120+ long next_tail_idx = 0 ;
121+ int overwrote = 0 ;
72122
73123 SNAPTRACE_THREAD_PROTECT_START (self );
74- node = self -> buffer + self -> buffer_tail_idx ;
75124 // This is actually faster than modulo
76- self -> buffer_tail_idx = self -> buffer_tail_idx + 1 ;
77- if (self -> buffer_tail_idx >= self -> buffer_size ) {
78- self -> buffer_tail_idx = 0 ;
79- }
80- if (self -> buffer_tail_idx == self -> buffer_head_idx ) {
81- self -> buffer_head_idx = self -> buffer_head_idx + 1 ;
82- if (self -> buffer_head_idx >= self -> buffer_size ) {
83- self -> buffer_head_idx = 0 ;
125+ next_tail_idx = self -> buffer_tail_idx + 1 ;
126+ if (next_tail_idx >= self -> buffer_size ) {
127+ next_tail_idx = 0 ;
128+ }
129+ if (next_tail_idx == self -> buffer_head_idx ) {
130+ if (!(self -> grow_on_full && grow_buffer (self ) == 0 )) {
131+ overwrote = 1 ;
132+ self -> overflowed = 1 ;
133+ clear_node (self -> buffer + next_tail_idx );
134+ self -> buffer_head_idx = next_tail_idx + 1 ;
135+ if (self -> buffer_head_idx >= self -> buffer_size ) {
136+ self -> buffer_head_idx = 0 ;
137+ }
138+ } else {
139+ next_tail_idx = self -> buffer_tail_idx + 1 ;
140+ if (next_tail_idx >= self -> buffer_size ) {
141+ next_tail_idx = 0 ;
142+ }
84143 }
85- clear_node (self -> buffer + self -> buffer_tail_idx );
86- } else {
144+ }
145+ node = self -> buffer + self -> buffer_tail_idx ;
146+ self -> buffer_tail_idx = next_tail_idx ;
147+ if (!overwrote ) {
87148 self -> total_entries += 1 ;
88149 }
89150 SNAPTRACE_THREAD_PROTECT_END (self );
@@ -1072,6 +1133,11 @@ tracer_start(TracerObject* self, PyObject* Py_UNUSED(unused))
10721133 curr_tracer = self ;
10731134 }
10741135
1136+ if (self -> buffer_head_idx == self -> buffer_tail_idx ) {
1137+ self -> total_entries = 0 ;
1138+ self -> overflowed = 0 ;
1139+ }
1140+
10751141 self -> collecting = 1 ;
10761142#if PY_VERSION_HEX >= 0x030C0000
10771143 if (enable_monitoring (self ) != 0 ) {
@@ -1493,7 +1559,6 @@ tracer_dump(TracerObject* self, PyObject* args, PyObject* kw)
14931559 SNAPTRACE_THREAD_PROTECT_START (self );
14941560 struct EventNode * curr = self -> buffer + self -> buffer_head_idx ;
14951561 unsigned long pid = 0 ;
1496- uint8_t overflowed = ((self -> buffer_tail_idx + 1 ) % self -> buffer_size ) == self -> buffer_head_idx ;
14971562 struct MetadataNode * metadata_node = NULL ;
14981563 PyObject * task_dict = NULL ;
14991564
@@ -1681,7 +1746,7 @@ tracer_dump(TracerObject* self, PyObject* args, PyObject* kw)
16811746
16821747 self -> buffer_tail_idx = self -> buffer_head_idx ;
16831748 fseek (fptr , -1 , SEEK_CUR );
1684- fprintf (fptr , "], \"viztracer_metadata\": {\"overflow\":%s" , overflowed ? "true" : "false" );
1749+ fprintf (fptr , "], \"viztracer_metadata\": {\"overflow\":%s" , self -> overflowed ? "true" : "false" );
16851750
16861751 if (self -> sync_marker > 0 )
16871752 {
@@ -1708,6 +1773,8 @@ tracer_clear(TracerObject* self, PyObject* Py_UNUSED(unused))
17081773 }
17091774 }
17101775 self -> buffer_tail_idx = self -> buffer_head_idx ;
1776+ self -> total_entries = 0 ;
1777+ self -> overflowed = 0 ;
17111778
17121779 Py_RETURN_NONE ;
17131780}
@@ -2062,10 +2129,13 @@ Tracer_New(PyTypeObject* type, PyObject* args, PyObject* kwargs)
20622129 self -> collecting = 0 ;
20632130 self -> fix_pid = 0 ;
20642131 self -> total_entries = 0 ;
2132+ self -> overflowed = 0 ;
2133+ self -> grow_on_full = 0 ;
20652134 self -> check_flags = 0 ;
20662135 self -> verbose = 0 ;
20672136 self -> lib_file_path = NULL ;
20682137 self -> max_stack_depth = 0 ;
2138+ self -> max_buffer_entries = 0 ;
20692139 self -> include_files = NULL ;
20702140 self -> exclude_files = NULL ;
20712141 self -> min_duration = 0 ;
0 commit comments