11"""JSONL collector."""
22
3+ from collections import Counter
34import json
45import uuid
56from itertools import batched
@@ -38,8 +39,8 @@ def __init__(self, sample_interval_usec, *, skip_idle=False, mode=None):
3839 self ._frame_to_id = {}
3940 self ._frames = []
4041
41- self ._frame_self = {}
42- self ._frame_cumulative = {}
42+ self ._frame_self = Counter ()
43+ self ._frame_cumulative = Counter ()
4344 self ._samples_total = 0
4445
4546 self ._mode = mode
@@ -56,21 +57,39 @@ def process_frames(self, frames, _thread_id, weight=1):
5657 ]
5758 leaf_frame_id = frame_ids [0 ]
5859
59- self ._frame_self [leaf_frame_id ] = (
60- self ._frame_self .get (leaf_frame_id , 0 ) + weight
61- )
60+ self ._frame_self [leaf_frame_id ] += weight
6261
6362 for frame_id in set (frame_ids ):
64- self ._frame_cumulative [frame_id ] = (
65- self ._frame_cumulative .get (frame_id , 0 ) + weight
66- )
63+ self ._frame_cumulative [frame_id ] += weight
6764
6865 def export (self , filename ):
6966 with open (filename , "w" , encoding = "utf-8" ) as output :
7067 self ._write_message (output , self ._build_meta_record ())
71- self ._write_chunked_defs (output , "str_def" , self ._strings )
72- self ._write_chunked_defs (output , "frame_def" , self ._frames )
73- self ._write_chunked_agg (output , self ._iter_agg_entries ())
68+ self ._write_chunked_records (
69+ output ,
70+ {"type" : "str_def" , "v" : 1 , "run_id" : self .run_id },
71+ "defs" ,
72+ self ._strings ,
73+ )
74+ self ._write_chunked_records (
75+ output ,
76+ {"type" : "frame_def" , "v" : 1 , "run_id" : self .run_id },
77+ "defs" ,
78+ self ._frames ,
79+ )
80+ self ._write_chunked_records (
81+ output ,
82+ {
83+ "type" : "agg" ,
84+ "v" : 1 ,
85+ "run_id" : self .run_id ,
86+ "kind" : "frame" ,
87+ "scope" : "final" ,
88+ "samples_total" : self ._samples_total ,
89+ },
90+ "entries" ,
91+ self ._iter_agg_entries (),
92+ )
7493 self ._write_message (output , self ._build_end_record ())
7594
7695 def _build_meta_record (self ):
@@ -171,44 +190,18 @@ def _normalize_export_location(location):
171190 return normalized
172191
173192 def _iter_agg_entries (self ):
174- entries = []
175- for frame_record in self ._frames :
176- frame_id = frame_record ["frame_id" ]
177- entries .append (
178- {
179- "frame_id" : frame_id ,
180- "self" : self ._frame_self .get (frame_id , 0 ),
181- "cumulative" : self ._frame_cumulative .get (frame_id , 0 ),
182- }
183- )
184- return entries
185-
186- def _write_chunked_defs (self , output , record_type , entries ):
187- for chunk in batched (entries , _CHUNK_SIZE ):
188- self ._write_message (
189- output ,
190- {
191- "type" : record_type ,
192- "v" : 1 ,
193- "run_id" : self .run_id ,
194- "defs" : chunk ,
195- },
196- )
193+ return [
194+ {
195+ "frame_id" : frame_record ["frame_id" ],
196+ "self" : self ._frame_self [frame_record ["frame_id" ]],
197+ "cumulative" : self ._frame_cumulative [frame_record ["frame_id" ]],
198+ }
199+ for frame_record in self ._frames
200+ ]
197201
198- def _write_chunked_agg (self , output , entries ):
202+ def _write_chunked_records (self , output , base_record , chunk_field , entries ):
199203 for chunk in batched (entries , _CHUNK_SIZE ):
200- self ._write_message (
201- output ,
202- {
203- "type" : "agg" ,
204- "v" : 1 ,
205- "run_id" : self .run_id ,
206- "kind" : "frame" ,
207- "scope" : "final" ,
208- "samples_total" : self ._samples_total ,
209- "entries" : chunk ,
210- },
211- )
204+ self ._write_message (output , {** base_record , chunk_field : chunk })
212205
213206 @staticmethod
214207 def _write_message (output , record ):
0 commit comments