Skip to content

Commit 7d0184c

Browse files
s-noghabiThe tunix Authors
authored andcommitted
Add perfetto visualization
PiperOrigin-RevId: 874830609
1 parent 7e57b8f commit 7d0184c

File tree

16 files changed

+1639
-12
lines changed

16 files changed

+1639
-12
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Tests for perfetto."""
16+
17+
import os
18+
import tempfile
19+
import time
20+
21+
from absl.testing import absltest
22+
from tunix.perf.experimental import perfetto
23+
from tunix.perf.experimental import tracer
24+
25+
26+
class PerfettoTest(absltest.TestCase):
27+
28+
# TODO(noghabi): Add more tests for PerfettoTraceWriter.
29+
def test_perfetto_trace_writer(self):
30+
with tempfile.TemporaryDirectory() as tmp_dir:
31+
writer = perfetto.PerfettoTraceWriter(export_dir=tmp_dir)
32+
33+
# Create some dummy timelines
34+
t = tracer.Timeline("test_timeline", time.perf_counter())
35+
s = t.start_span("test_span", time.perf_counter())
36+
time.sleep(0.001)
37+
t.stop_span(time.perf_counter())
38+
39+
timelines = {"test_timeline": t}
40+
41+
writer.write_timelines(timelines)
42+
43+
# Check if file was created
44+
files = os.listdir(tmp_dir)
45+
self.assertLen(files, 1)
46+
self.assertTrue(files[0].startswith("perfetto_trace_v2_"))
47+
self.assertTrue(files[0].endswith(".pb"))
48+
49+
# We could parse the proto back to verify content, but just existence is good for now.
50+
51+
52+
if __name__ == "__main__":
53+
absltest.main()
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from absl.testing import absltest
16+
from tunix.perf.experimental import constants
17+
from tunix.perf.experimental import span
18+
19+
20+
class TimelineTest(absltest.TestCase):
21+
22+
def test_span(self):
23+
s = span.Span(name="test", begin=1.0, id=0)
24+
self.assertEqual(s.name, "test")
25+
self.assertEqual(s.begin, 1.0)
26+
self.assertEqual(s.end, float("inf"))
27+
self.assertEqual(s.ended, False)
28+
self.assertEqual(s.duration, float("inf"))
29+
30+
def test_span_with_tags(self):
31+
tags_dict = {constants.GLOBAL_STEP: 1, "custom_tag": "value"}
32+
s = span.Span(name="test_tags", begin=1.0, id=0, tags=tags_dict)
33+
self.assertEqual(s.tags, tags_dict)
34+
self.assertIn("tags=", repr(s))
35+
self.assertIn("global_step", repr(s))
36+
37+
def test_add_tag(self):
38+
s = span.Span(name="test_add_tag", begin=1.0, id=0)
39+
s.add_tag("foo", "bar")
40+
self.assertEqual(s.tags, {"foo": "bar"})
41+
s.add_tag(constants.GLOBAL_STEP, 100)
42+
self.assertEqual(s.tags, {"foo": "bar", "global_step": 100})
43+
44+
def test_add_tag_overwrite_warning(self):
45+
s = span.Span(name="test_add_tag_overwrite", begin=1.0, id=0)
46+
s.add_tag("foo", "bar")
47+
with self.assertLogs(level="WARNING") as cm:
48+
s.add_tag("foo", "baz")
49+
self.assertEqual(s.tags, {"foo": "baz"})
50+
self.assertTrue(
51+
any(
52+
"Tag 'foo' already exists with value 'bar'. Overwriting with 'baz'."
53+
in o
54+
for o in cm.output
55+
)
56+
)
57+
58+
def test_repr_with_born_at(self):
59+
born_at = 100.0
60+
s = span.Span(name="test_born_at", begin=101.0, id=0)
61+
s.end = 105.0
62+
63+
# Check default repr (born_at=0.0)
64+
expected_default = "[0] test_born_at: 101.000000, 105.000000"
65+
self.assertEqual(repr(s), expected_default)
66+
67+
# Check repr with explicit born_at
68+
expected_adjusted = "[0] test_born_at: 1.000000, 5.000000"
69+
self.assertEqual(s.__repr__(born_at=born_at), expected_adjusted)
70+
71+
72+
if __name__ == "__main__":
73+
absltest.main()

0 commit comments

Comments
 (0)