• 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 <list>
24 #include <memory>
25 #include <string>
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   // adb setprop options.
154   enum SetPropFlag {
155     kDisable = 0,
156     kPrintBit = 1 << 0,
157     kDumpBit = 1 << 1,
158     kStopWatch = 1 << 2,
159     // Print FPS per interval time based on the value of SetFpsPrintInterval()
160     kPrintFpsPerIntervalBit = 1 << 3,
161     // Calculate FPS on process end function instead of process start function
162     kCalculateFpsOnEndBit = 1 << 4,
163     // Dynamic start profiling.
164     kDynamicStartBit = 1 << 5,
165     // Dumps result using proto format.
166     kProto = 1 << 6,
167     // Customized profiler derived from Profiler
168     kCustomProfiler = 1 << 7,
169   };
170 
171   // Setup the name of use case the profiler is running.
172   // Argument:
173   //  usecase: the name use case of the profiler is running.
174   virtual void SetUseCase(std::string usecase) = 0;
175 
176   // Set the file prefix name for dumpping the profiling file.
177   // Argument:
178   //  dump_file_prefix: file prefix name. In the current setting,
179   //    "/data/vendor/camera/" is a valid folder for camera to dump file.
180   //    A valid prefix can be "/data/vendor/camera/test_prefix_".
181   virtual void SetDumpFilePrefix(const std::string& dump_file_prefix) = 0;
182 
183   // Start to profile.
184   // We use start and end to choose which code snippet to be profile.
185   // The user specifies the name, and the profiler will print the name and its
186   // timing.
187   // Arguments:
188   //   name: the name of the node to be profiled.
189   //   request_id: frame requesd id.
190   virtual void Start(const std::string& name, int request_id) = 0;
191 
192   // End the profileing.
193   // Arguments:
194   //   name: the name of the node to be profiled. Should be the same in Start().
195   //   request_id: frame requesd id.
196   virtual void End(const std::string& name, int request_id) = 0;
197 
198   // Print out the profiling result in the standard output (ANDROID_LOG_ERROR).
199   virtual void PrintResult() = 0;
200 
201   // Profile the frame rate
202   // If only call this function without start() and End(),
203   // creating profiler needs to set option with kPrintFpsPerIntervalBit bit.
204   // It can print FPS every second.
205   virtual void ProfileFrameRate(const std::string& name) = 0;
206 
207   // Set the interval of FPS print
208   // The interval unit is second and interval_seconds must >= 1
209   virtual void SetFpsPrintInterval(int32_t interval_seconds) = 0;
210 
211   virtual std::list<std::pair<std::string, float>> GetLatencyData() = 0;
212 
213   virtual std::string GetUseCase() const = 0;
214 
215  protected:
216   Profiler() = default;
217 };
218 
219 // A scoped utility class to facilitate profiling.
220 class ScopedProfiler {
221  public:
222   // Constructor.
223   // Arguments:
224   //   profiler: profiler object.
225   //   target: the name of the target to be profiled.
226   //   request_id: frame requesd id.
ScopedProfiler(std::shared_ptr<Profiler> profiler,const std::string target,int request_id)227   ScopedProfiler(std::shared_ptr<Profiler> profiler, const std::string target,
228                  int request_id)
229       : profiler_(profiler),
230         target_(std::move(target)),
231         request_id_(request_id) {
232     profiler_->Start(target_, request_id_);
233   }
234 
ScopedProfiler(std::shared_ptr<Profiler> profiler,const std::string target)235   ScopedProfiler(std::shared_ptr<Profiler> profiler, const std::string target)
236       : profiler_(profiler), target_(std::move(target)) {
237     request_id_ = Profiler::kInvalidRequestId;
238     profiler_->Start(target_, request_id_);
239   }
240 
ScopedProfiler(const std::string target,int option)241   ScopedProfiler(const std::string target, int option)
242       : target_(std::move(target)) {
243     profiler_ = Profiler::Create(option);
244     request_id_ = Profiler::kInvalidRequestId;
245     profiler_->Start(target_, request_id_);
246   }
247 
~ScopedProfiler()248   ~ScopedProfiler() {
249     profiler_->End(target_, request_id_);
250   }
251 
252  private:
253   std::shared_ptr<Profiler> profiler_;
254   const std::string target_;
255   int request_id_;
256 };
257 
258 }  // namespace camera_common
259 }  // namespace google
260 
261 #endif  // HARDWARE_GOOGLE_CAMERA_COMMON_PROFILER_H
262