• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef HARDWARE_GOOGLE_CAMERA_COMMON_PROFILER_H
18 #define HARDWARE_GOOGLE_CAMERA_COMMON_PROFILER_H
19 
20 #include <cutils/properties.h>
21 
22 #include <limits>
23 #include <memory>
24 #include <string>
25 #include <vector>
26 
27 namespace google {
28 namespace camera_common {
29 
30 // The goal of the Profiler is to profile the performance of camemra pipeline.
31 // However you can use it profile any procedure.
32 // The profiler prints out the result when the Profiler obejct is deconstructed.
33 //
34 // Setprops:
35 //  - To disable the profiler:
36 //    $ adb shell setprop persist.vendor.camera.profiler 0
37 //  - To print the profiling result in standard output:
38 //    $ adb shell setprop persist.vendor.camera.profiler 1
39 //  - To dump the profiling result to "/data/vendor/camera/profiler":
40 //    $ adb shell setprop persist.vendor.camera.profiler 2
41 //  - To print and dump the profiling result to "/data/vendor/camera/profiler":
42 //    $ adb shell setprop persist.vendor.camera.profiler 3
43 //  After add FPS option, here are the combination results.
44 //  Option 0 (kDisable): Disable Profiler
45 //  Option 1 (kPrintBit):
46 //    When close, Print the result
47 //    - Processing time
48 //    - FPS with total frames on process start function
49 //  Option 2 (kDumpBit):
50 //    When close, dump the result to file(dump_file_prefix)
51 //    - Processing time
52 //    - FPS with total frames on process start function
53 //  Option 3 (kPrintBit|kDumpBit):
54 //    When close, print and dump the result
55 //    - Processing time
56 //    - FPS with total frames on process start function
57 //  Option 8 (kPrintFpsPerIntervalBit):
58 //    Print FPS per interval on ProfileFrameRate function
59 //    The frequency is based on the value of SetFpsPrintInterval()
60 //  Option 9 (kPrintFpsPerIntervalBit|kPrintBit):
61 //    Print FPS per interval on process start and ProfileFrameRate function
62 //    When close, print the result
63 //    - Processing time
64 //    - FPS with total frames on process start function
65 //  Option 10 (kPrintFpsPerIntervalBit|kDumpBit):
66 //    Print FPS per interval on process start and ProfileFrameRate function
67 //    When close, dump the result
68 //    - Processing time
69 //    - FPS with total frames on process start function
70 //  Option 11 (kPrintFpsPerIntervalBit|kPrintBit|kDumpBit):
71 //    Print FPS per interval on process start and ProfileFrameRate function
72 //    When close, print and dump the result
73 //    - Processing time
74 //    - FPS with total frames on process start function
75 //  Option 16 (kCalculateFpsOnEndBit):
76 //    Calculate FPS on process end function instead of process start function
77 //  Option 17 (kCalculateFpsOnEndBit|kPrintBit):
78 //    When close, print the result
79 //    - Processing time
80 //    - FPS with total frames on process "end" function
81 //  Option 18 (kCalculateFpsOnEndBit|kDumpBit):
82 //    When close, dump the result
83 //    - Processing time
84 //    - FPS with total frames on process "end" function
85 //  Option 19 (kCalculateFpsOnEndBit|kPrintBitk|DumpBit):
86 //    When close, print and dump the result
87 //    - Processing time
88 //    - FPS with total frames on process "end" function
89 //  Option 25 (kCalculateFpsOnEndBit|kPrintFpsPerIntervalBit|kPrintBit):
90 //    Print FPS per interval on process start and ProfileFrameRate function
91 //    When close, print the result
92 //    - Processing time
93 //    - FPS with total frames on process "end" function
94 //  Option 26 (kCalculateFpsOnEndBit|kPrintFpsPerIntervalBit|DumpBit):
95 //    Print FPS per interval on process start and ProfileFrameRate function
96 //    When close, dump the result
97 //    - Processing time
98 //    - FPS with total frames on process "end" function
99 //  Option 27 (kCalculateFpsOnEndBit|kPrintFpsPerIntervalBit|kPrintBitk|DumpBit):
100 //    Print FPS per interval on process start and ProfileFrameRate function
101 //    When close, print and dump the result
102 //    - Processing time
103 //    - FPS with total frames on process "end" function
104 //
105 //  By default the profiler is disabled.
106 //
107 // Usage:
108 //  1. To Create a profiler, please call Profiler::Create(...).
109 //  2. Use Start() and End() to profile the enclosed code snippet.
110 //  3. Use SetUseCase to specify the name of the profiling target (purpose).
111 //  4  If you want to dump the profiling data to the disk, call
112 //     SetDumpFilePrefix(), which is default to "/vendor/camera/profiler/".
113 //     The dumped file name is the prefix name + usecase name.
114 //
115 // Example Code:
116 //  In the following example, we use a for loop to profile two fucntions Foo()
117 //  and Bar; Foo() run once, and Bar() run twice.
118 //
119 //   std::unique_ptr<Profiler> profiler = Profiler::Create(Profiler::kPrintBit);
120 //   profiler->SetUseCase("Profiling Example");
121 //
122 //   for (int i = 0; i < 100; i++) {
123 //     profiler->Start("Foo function", i);
124 //     Foo()
125 //     profiler->End("Foo function", i);
126 //
127 //     profiler->Start("Bar function", i);
128 //     Bar()
129 //     profiler->End("Bar function", i);
130 //
131 //     profiler->Start("Bar function", i);
132 //     Bar()
133 //     profiler->End("Bar function", i);
134 //   }
135 //
136 // Example Print Out:
137 //
138 // UseCase: Profiling Example. Profiled Frames: 100.
139 //      Foo function           Max:  0.012 ms.   Avg:  0.020 ms x 1 =  0.040 ms
140 //      Bar function           Max:  0.008 ms.   Avg:  0.019 ms x 2 =  0.039 ms
141 //                      SUM OF MAX:  0.020 ms,           SUM OF AVG =  0.079 ms
142 //
143 class Profiler {
144  public:
145   // Invalid request id.
146   static constexpr int kInvalidRequestId = std::numeric_limits<int>::max();
147 
148   // Create profiler.
149   static std::shared_ptr<Profiler> Create(int option);
150 
151   virtual ~Profiler() = default;
152 
153   struct LatencyEvent {
154     std::string name;
155     float duration;
156   };
157 
158   // adb setprop options.
159   enum SetPropFlag {
160     kDisable = 0,
161     kPrintBit = 1 << 0,
162     kDumpBit = 1 << 1,
163     kStopWatch = 1 << 2,
164     // Print FPS per interval time based on the value of SetFpsPrintInterval()
165     kPrintFpsPerIntervalBit = 1 << 3,
166     // Calculate FPS on process end function instead of process start function
167     kCalculateFpsOnEndBit = 1 << 4,
168     // Dynamic start profiling.
169     kDynamicStartBit = 1 << 5,
170     // Dumps result using proto format.
171     kProto = 1 << 6,
172     // Customized profiler derived from Profiler
173     kCustomProfiler = 1 << 7,
174   };
175 
176   // Setup the name of use case the profiler is running.
177   // Argument:
178   //  usecase: the name use case of the profiler is running.
179   virtual void SetUseCase(std::string usecase) = 0;
180 
181   // Set the file prefix name for dumpping the profiling file.
182   // Argument:
183   //  dump_file_prefix: file prefix name. In the current setting,
184   //    "/data/vendor/camera/" is a valid folder for camera to dump file.
185   //    A valid prefix can be "/data/vendor/camera/test_prefix_".
186   virtual void SetDumpFilePrefix(const std::string& dump_file_prefix) = 0;
187 
188   // Start to profile.
189   // We use start and end to choose which code snippet to be profile.
190   // The user specifies the name, and the profiler will print the name and its
191   // timing.
192   // Arguments:
193   //   name: the name of the node to be profiled.
194   //   request_id: frame requesd id.
195   virtual void Start(const std::string& name, int request_id) = 0;
196 
197   // End the profileing.
198   // Arguments:
199   //   name: the name of the node to be profiled. Should be the same in Start().
200   //   request_id: frame requesd id.
201   virtual void End(const std::string& name, int request_id) = 0;
202 
203   // Print out the profiling result in the standard output (ANDROID_LOG_ERROR).
204   virtual void PrintResult() = 0;
205 
206   // Profile the frame rate
207   // If only call this function without start() and End(),
208   // creating profiler needs to set option with kPrintFpsPerIntervalBit bit.
209   // It can print FPS every second.
210   virtual void ProfileFrameRate(const std::string& name) = 0;
211 
212   // Set the interval of FPS print
213   // The interval unit is second and interval_seconds must >= 1
214   virtual void SetFpsPrintInterval(int32_t interval_seconds) = 0;
215 
216   virtual std::vector<LatencyEvent> GetLatencyData() = 0;
217 
218   virtual std::string GetUseCase() const = 0;
219 
220  protected:
221   Profiler() = default;
222 };
223 
224 // A scoped utility class to facilitate profiling.
225 class ScopedProfiler {
226  public:
227   // Constructor.
228   // Arguments:
229   //   profiler: profiler object.
230   //   target: the name of the target to be profiled.
231   //   request_id: frame requesd id.
ScopedProfiler(std::shared_ptr<Profiler> profiler,const std::string target,int request_id)232   ScopedProfiler(std::shared_ptr<Profiler> profiler, const std::string target,
233                  int request_id)
234       : profiler_(profiler),
235         target_(std::move(target)),
236         request_id_(request_id) {
237     profiler_->Start(target_, request_id_);
238   }
239 
ScopedProfiler(std::shared_ptr<Profiler> profiler,const std::string target)240   ScopedProfiler(std::shared_ptr<Profiler> profiler, const std::string target)
241       : profiler_(profiler), target_(std::move(target)) {
242     request_id_ = Profiler::kInvalidRequestId;
243     profiler_->Start(target_, request_id_);
244   }
245 
ScopedProfiler(const std::string target,int option)246   ScopedProfiler(const std::string target, int option)
247       : target_(std::move(target)) {
248     profiler_ = Profiler::Create(option);
249     request_id_ = Profiler::kInvalidRequestId;
250     profiler_->Start(target_, request_id_);
251   }
252 
~ScopedProfiler()253   ~ScopedProfiler() {
254     profiler_->End(target_, request_id_);
255   }
256 
257  private:
258   std::shared_ptr<Profiler> profiler_;
259   const std::string target_;
260   int request_id_;
261 };
262 
263 }  // namespace camera_common
264 }  // namespace google
265 
266 #endif  // HARDWARE_GOOGLE_CAMERA_COMMON_PROFILER_H
267