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