Skip to content

Commit 9520599

Browse files
Jack-Khuufacebook-github-bot
authored andcommitted
Adding support for a scale factor when parsing ETDump results
Summary: By default, event profiling time is treated as ms (1/1000), but users should have the ability to define the scale Note that the default is set to 1000 only in the constructor. Private functions default to no-op (scale = 1) Differential Revision: D49762707
1 parent 4b2f0b7 commit 9520599

File tree

2 files changed

+40
-11
lines changed

2 files changed

+40
-11
lines changed

sdk/etdb/inspector.py

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,16 @@ class Event:
153153

154154
@staticmethod
155155
def _gen_from_profile_events(
156-
signature: ProfileEventSignature, events: List[ProfileEvent]
156+
signature: ProfileEventSignature,
157+
events: List[ProfileEvent],
158+
scale_factor: int = 1,
157159
) -> "Event":
158160
"""
159161
Given a ProfileEventSignature and a list of ProfileEvents with that signature,
160162
return an Event object matching the ProfileEventSignature, with perf_data
161163
populated from the list of ProfileEvents
164+
165+
An optional inverse scale factor can be provided to adjust the event timestamps
162166
"""
163167
if signature.delegate_id is not None: # 0 is a valid value
164168
delegate_debug_identifier = signature.delegate_id
@@ -170,7 +174,10 @@ def _gen_from_profile_events(
170174
name = signature.name if not is_delegated_op else str(delegate_debug_identifier)
171175

172176
perf_data = PerfData(
173-
[float(event.end_time - event.start_time) / 1000 for event in events]
177+
[
178+
float(event.end_time - event.start_time) / scale_factor
179+
for event in events
180+
]
174181
)
175182

176183
return Event(
@@ -247,10 +254,15 @@ def to_dataframe(self) -> pd.DataFrame:
247254
return df
248255

249256
@staticmethod
250-
def _gen_from_etdump(etdump: ETDumpFlatCC) -> List["EventBlock"]:
257+
def _gen_from_etdump(
258+
etdump: ETDumpFlatCC, scale_factor: int = 1
259+
) -> List["EventBlock"]:
251260
"""
252261
Given an etdump, generate a list of EventBlocks corresponding to the
253-
contents
262+
contents.
263+
264+
An optional (inverse) scale factor can be provided to adjust the
265+
etdump timestamps associated with each EventBlocks
254266
"""
255267

256268
# Group all the RunData by the set of profile events
@@ -286,7 +298,7 @@ def _gen_from_etdump(etdump: ETDumpFlatCC) -> List["EventBlock"]:
286298
EventBlock(
287299
name=str(index),
288300
events=[
289-
Event._gen_from_profile_events(signature, event)
301+
Event._gen_from_profile_events(signature, event, scale_factor)
290302
for signature, event in profile_events.items()
291303
],
292304
)
@@ -360,16 +372,25 @@ class Inspector:
360372
"""
361373

362374
def __init__(
363-
self, etdump_path: Optional[str] = None, etrecord_path: Optional[str] = None
375+
self,
376+
etdump_path: Optional[str] = None,
377+
etrecord_path: Optional[str] = None,
378+
etdump_scale: int = 1000,
364379
) -> None:
365380
"""
366381
Create an inspector instance from the provided ETDump/ETRecord
382+
383+
Args:
384+
etdump_path: Path to the ETDump file.
385+
etrecord_path: Path to the ETRecord file.
386+
etdump_scale: Inverse Scale Factor used to cast the timestamps in ETDump
387+
defaults to milli (1000ms = 1s).
367388
"""
368389

369390
# TODO: etrecord_path can be optional, so need to support the case when it is not present
370391
self._etrecord = gen_etrecord_object(etrecord_path=etrecord_path)
371392
etdump = gen_etdump_object(etdump_path=etdump_path)
372-
self.event_blocks = EventBlock._gen_from_etdump(etdump)
393+
self.event_blocks = EventBlock._gen_from_etdump(etdump, etdump_scale)
373394

374395
self._op_graph_dict: Mapping[
375396
str, OperatorGraphWithStats

sdk/etdb/tests/event_blocks_test.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ def test_gen_from_etdump(self) -> None:
128128
- Correct number of Events and Raw Data values (iterations)
129129
"""
130130
etdump: ETDumpFlatCC = TestEventBlock._get_sample_etdump_flatcc()
131-
blocks: List[EventBlock] = EventBlock._gen_from_etdump(etdump)
131+
blocks: List[EventBlock] = EventBlock._gen_from_etdump(etdump, 1000)
132132

133133
self.assertEqual(len(blocks), 2, f"Expected 2 runs, got {len(blocks)}")
134134

@@ -152,6 +152,7 @@ def _test_profile_event_generation(
152152
instruction_id: int,
153153
delegate_debug_id_int: Optional[int] = None,
154154
delegate_debug_id_str: Optional[str] = None,
155+
scale_factor: int = 1000,
155156
) -> None:
156157
"""
157158
Helper function for testing that the provided ProfileEvent fields are
@@ -180,17 +181,19 @@ def _test_profile_event_generation(
180181
TestEventBlock._gen_sample_profile_event(
181182
name,
182183
instruction_id,
183-
(0, 10),
184+
(0, time),
184185
delegate_debug_id,
185186
)
186187
for time in durations
187188
]
188-
event = Event._gen_from_profile_events(signature, profile_events)
189+
event = Event._gen_from_profile_events(
190+
signature, profile_events, scale_factor=scale_factor
191+
)
189192

190193
is_delegated = delegate_debug_id is not None
191194
expected_event = Event(
192195
str(delegate_debug_id) if is_delegated else name,
193-
PerfData([float(duration) / 1000 for duration in durations]),
196+
PerfData([float(duration) / scale_factor for duration in durations]),
194197
instruction_id=signature.instruction_id,
195198
delegate_debug_identifier=delegate_debug_id,
196199
is_delegated_op=is_delegated,
@@ -206,6 +209,11 @@ def _test_profile_event_generation(
206209
# Delegate with String Debug ID
207210
_test_profile_event_generation("delegate", 1, None, "identifier")
208211

212+
# Manipulating the scale factor
213+
_test_profile_event_generation(
214+
"delegate", 1, None, "identifier", scale_factor=10000
215+
)
216+
209217
def test_gen_resolve_debug_handles(self) -> None:
210218
"""
211219
Test that gen_resolve_debug_handles() correctly populates the EventBlock

0 commit comments

Comments
 (0)