xref: /aosp_15_r20/external/tensorflow/tensorflow/lite/profiling/profiler_test.cc (revision b6fb3261f9314811a0f4371741dbb8839866f948)
1 /* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
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 #include "tensorflow/lite/profiling/profiler.h"
16 
17 #include <unistd.h>
18 
19 #include <chrono>  // NOLINT(build/c++11)
20 #include <cmath>
21 #include <thread>  // NOLINT(build/c++11)
22 
23 #include <gmock/gmock.h>
24 #include <gtest/gtest.h>
25 
26 namespace tflite {
27 namespace profiling {
28 namespace {
29 
GetDurationOfEventMs(const ProfileEvent * event)30 double GetDurationOfEventMs(const ProfileEvent* event) {
31   return (event->elapsed_time) / 1e3;
32 }
33 
SleepForQuarterSecond(tflite::Profiler * profiler)34 void SleepForQuarterSecond(tflite::Profiler* profiler) {
35   ScopedProfile profile(profiler, "SleepForQuarter");
36   std::this_thread::sleep_for(std::chrono::milliseconds(250));
37 }
38 
ChildFunction(tflite::Profiler * profiler)39 void ChildFunction(tflite::Profiler* profiler) {
40   ScopedProfile profile(profiler, "Child");
41   SleepForQuarterSecond(profiler);
42 }
43 
ParentFunction(tflite::Profiler * profiler)44 void ParentFunction(tflite::Profiler* profiler) {
45   ScopedProfile profile(profiler, "Parent");
46   for (int i = 0; i < 2; i++) {
47     ChildFunction(profiler);
48   }
49 }
50 
TEST(ProfilerTest,NoProfilesAreCollectedWhenDisabled)51 TEST(ProfilerTest, NoProfilesAreCollectedWhenDisabled) {
52   BufferedProfiler profiler(1024);
53   ParentFunction(&profiler);
54   auto profile_events = profiler.GetProfileEvents();
55   EXPECT_EQ(0, profile_events.size());
56 }
57 
TEST(ProfilerTest,NoProfilesAreCollectedWhenEventTypeUnsupported)58 TEST(ProfilerTest, NoProfilesAreCollectedWhenEventTypeUnsupported) {
59   BufferedProfiler profiler(1024);
60   tflite::Profiler* p = &profiler;
61   p->AddEvent("Hello",
62               Profiler::EventType::GENERAL_RUNTIME_INSTRUMENTATION_EVENT,
63               /*elaped_time*/ 1,
64               /*event_metadata*/ 2);
65   auto handler = p->BeginEvent(
66       "begin", Profiler::EventType::GENERAL_RUNTIME_INSTRUMENTATION_EVENT, 0);
67   p->EndEvent(handler);
68   auto profile_events = profiler.GetProfileEvents();
69   EXPECT_EQ(0, profile_events.size());
70 }
71 
TEST(ProfilingTest,ProfilesAreCollected)72 TEST(ProfilingTest, ProfilesAreCollected) {
73   BufferedProfiler profiler(1024);
74   profiler.StartProfiling();
75   ParentFunction(&profiler);
76   profiler.StopProfiling();
77   auto profile_events = profiler.GetProfileEvents();
78   // ParentFunction calls the ChildFunction 2 times.
79   // Each ChildFunction calls SleepForQuarterSecond once.
80   // We expect 1 entry for ParentFunction, 2 for ChildFunction and 2 for
81   // SleepForQuarterSecond: Total: 1+ 2 + 2 = 5
82   //  Profiles should look like:
83   //  Parent ~ 500 ms (due to 2 Child calls)
84   //   - Child ~ 250 ms (due to SleepForQuarter calls)
85   //       - SleepForQuarter ~ 250ms
86   //   - Child ~ 250 ms (due to SleepForQuarter calls)
87   //      - SleepForQuarter ~ 250ms
88   //
89   ASSERT_EQ(5, profile_events.size());
90   EXPECT_EQ("Parent", profile_events[0]->tag);
91   EXPECT_EQ("Child", profile_events[1]->tag);
92   EXPECT_EQ("SleepForQuarter", profile_events[2]->tag);
93   EXPECT_EQ("Child", profile_events[3]->tag);
94   EXPECT_EQ("SleepForQuarter", profile_events[4]->tag);
95 
96 #ifndef ADDRESS_SANITIZER
97   // ASAN build is sometimes very slow. Set a large epsilon to avoid flakiness.
98   // Due to flakiness, just verify relative values match.
99   const int eps_ms = 50;
100   auto parent_ms = GetDurationOfEventMs(profile_events[0]);
101   double child_ms[2], sleep_for_quarter_ms[2];
102   child_ms[0] = GetDurationOfEventMs(profile_events[1]);
103   child_ms[1] = GetDurationOfEventMs(profile_events[3]);
104   sleep_for_quarter_ms[0] = GetDurationOfEventMs(profile_events[2]);
105   sleep_for_quarter_ms[1] = GetDurationOfEventMs(profile_events[4]);
106   EXPECT_NEAR(parent_ms, child_ms[0] + child_ms[1], eps_ms);
107   EXPECT_NEAR(child_ms[0], sleep_for_quarter_ms[0], eps_ms);
108   EXPECT_NEAR(child_ms[1], sleep_for_quarter_ms[1], eps_ms);
109 #endif
110 }
111 
TEST(ProfilingTest,NullProfiler)112 TEST(ProfilingTest, NullProfiler) {
113   Profiler* profiler = nullptr;
114   { SCOPED_TAGGED_OPERATOR_PROFILE(profiler, "noop", 1); }
115 }
116 
TEST(ProfilingTest,ScopedProfile)117 TEST(ProfilingTest, ScopedProfile) {
118   BufferedProfiler profiler(1024);
119   profiler.StartProfiling();
120   { SCOPED_TAGGED_OPERATOR_PROFILE(&profiler, "noop", 1); }
121   profiler.StopProfiling();
122   auto profile_events = profiler.GetProfileEvents();
123   EXPECT_EQ(1, profile_events.size());
124 }
125 
TEST(ProfilingTest,NoopProfiler)126 TEST(ProfilingTest, NoopProfiler) {
127   NoopProfiler profiler;
128   profiler.StartProfiling();
129   { SCOPED_TAGGED_OPERATOR_PROFILE(&profiler, "noop", 1); }
130   profiler.StopProfiling();
131   auto profile_events = profiler.GetProfileEvents();
132   EXPECT_EQ(0, profile_events.size());
133 }
134 
135 }  // namespace
136 }  // namespace profiling
137 }  // namespace tflite
138