| /* |
| * Copyright (C) 2019 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef HARDWARE_GOOGLE_CAMERA_COMMON_PROFILER_H |
| #define HARDWARE_GOOGLE_CAMERA_COMMON_PROFILER_H |
| |
| #include <cutils/properties.h> |
| |
| #include <limits> |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| namespace google { |
| namespace camera_common { |
| |
| // The goal of the Profiler is to profile the performance of camemra pipeline. |
| // However you can use it profile any procedure. |
| // The profiler prints out the result when the Profiler obejct is deconstructed. |
| // |
| // Setprops: |
| // - To disable the profiler: |
| // $ adb shell setprop persist.vendor.camera.profiler 0 |
| // - To print the profiling result in standard output: |
| // $ adb shell setprop persist.vendor.camera.profiler 1 |
| // - To dump the profiling result to "/data/vendor/camera/profiler": |
| // $ adb shell setprop persist.vendor.camera.profiler 2 |
| // - To print and dump the profiling result to "/data/vendor/camera/profiler": |
| // $ adb shell setprop persist.vendor.camera.profiler 3 |
| // After add FPS option, here are the combination results. |
| // Option 0 (kDisable): Disable Profiler |
| // Option 1 (kPrintBit): |
| // When close, Print the result |
| // - Processing time |
| // - FPS with total frames on process start function |
| // Option 2 (kDumpBit): |
| // When close, dump the result to file(dump_file_prefix) |
| // - Processing time |
| // - FPS with total frames on process start function |
| // Option 3 (kPrintBit|kDumpBit): |
| // When close, print and dump the result |
| // - Processing time |
| // - FPS with total frames on process start function |
| // Option 8 (kPrintFpsPerIntervalBit): |
| // Print FPS per interval on ProfileFrameRate function |
| // The frequency is based on the value of SetFpsPrintInterval() |
| // Option 9 (kPrintFpsPerIntervalBit|kPrintBit): |
| // Print FPS per interval on process start and ProfileFrameRate function |
| // When close, print the result |
| // - Processing time |
| // - FPS with total frames on process start function |
| // Option 10 (kPrintFpsPerIntervalBit|kDumpBit): |
| // Print FPS per interval on process start and ProfileFrameRate function |
| // When close, dump the result |
| // - Processing time |
| // - FPS with total frames on process start function |
| // Option 11 (kPrintFpsPerIntervalBit|kPrintBit|kDumpBit): |
| // Print FPS per interval on process start and ProfileFrameRate function |
| // When close, print and dump the result |
| // - Processing time |
| // - FPS with total frames on process start function |
| // Option 16 (kCalculateFpsOnEndBit): |
| // Calculate FPS on process end function instead of process start function |
| // Option 17 (kCalculateFpsOnEndBit|kPrintBit): |
| // When close, print the result |
| // - Processing time |
| // - FPS with total frames on process "end" function |
| // Option 18 (kCalculateFpsOnEndBit|kDumpBit): |
| // When close, dump the result |
| // - Processing time |
| // - FPS with total frames on process "end" function |
| // Option 19 (kCalculateFpsOnEndBit|kPrintBitk|DumpBit): |
| // When close, print and dump the result |
| // - Processing time |
| // - FPS with total frames on process "end" function |
| // Option 25 (kCalculateFpsOnEndBit|kPrintFpsPerIntervalBit|kPrintBit): |
| // Print FPS per interval on process start and ProfileFrameRate function |
| // When close, print the result |
| // - Processing time |
| // - FPS with total frames on process "end" function |
| // Option 26 (kCalculateFpsOnEndBit|kPrintFpsPerIntervalBit|DumpBit): |
| // Print FPS per interval on process start and ProfileFrameRate function |
| // When close, dump the result |
| // - Processing time |
| // - FPS with total frames on process "end" function |
| // Option 27 (kCalculateFpsOnEndBit|kPrintFpsPerIntervalBit|kPrintBitk|DumpBit): |
| // Print FPS per interval on process start and ProfileFrameRate function |
| // When close, print and dump the result |
| // - Processing time |
| // - FPS with total frames on process "end" function |
| // |
| // By default the profiler is disabled. |
| // |
| // Usage: |
| // 1. To Create a profiler, please call Profiler::Create(...). |
| // 2. Use Start() and End() to profile the enclosed code snippet. |
| // 3. Use SetUseCase to specify the name of the profiling target (purpose). |
| // 4 If you want to dump the profiling data to the disk, call |
| // SetDumpFilePrefix(), which is default to "/vendor/camera/profiler/". |
| // The dumped file name is the prefix name + usecase name. |
| // |
| // Example Code: |
| // In the following example, we use a for loop to profile two fucntions Foo() |
| // and Bar; Foo() run once, and Bar() run twice. |
| // |
| // std::unique_ptr<Profiler> profiler = Profiler::Create(Profiler::kPrintBit); |
| // profiler->SetUseCase("Profiling Example"); |
| // |
| // for (int i = 0; i < 100; i++) { |
| // profiler->Start("Foo function", i); |
| // Foo() |
| // profiler->End("Foo function", i); |
| // |
| // profiler->Start("Bar function", i); |
| // Bar() |
| // profiler->End("Bar function", i); |
| // |
| // profiler->Start("Bar function", i); |
| // Bar() |
| // profiler->End("Bar function", i); |
| // } |
| // |
| // Example Print Out: |
| // |
| // UseCase: Profiling Example. Profiled Frames: 100. |
| // Foo function Max: 0.012 ms. Avg: 0.020 ms x 1 = 0.040 ms |
| // Bar function Max: 0.008 ms. Avg: 0.019 ms x 2 = 0.039 ms |
| // SUM OF MAX: 0.020 ms, SUM OF AVG = 0.079 ms |
| // |
| class Profiler { |
| public: |
| // Invalid request id. |
| static constexpr int kInvalidRequestId = std::numeric_limits<int>::max(); |
| |
| // Create profiler. |
| static std::shared_ptr<Profiler> Create(int option); |
| |
| virtual ~Profiler() = default; |
| |
| struct LatencyEvent { |
| std::string name; |
| float duration; |
| }; |
| |
| // adb setprop options. |
| enum SetPropFlag { |
| kDisable = 0, |
| kPrintBit = 1 << 0, |
| kDumpBit = 1 << 1, |
| kStopWatch = 1 << 2, |
| // Print FPS per interval time based on the value of SetFpsPrintInterval() |
| kPrintFpsPerIntervalBit = 1 << 3, |
| // Calculate FPS on process end function instead of process start function |
| kCalculateFpsOnEndBit = 1 << 4, |
| // Dynamic start profiling. |
| kDynamicStartBit = 1 << 5, |
| // Dumps result using proto format. |
| kProto = 1 << 6, |
| // Customized profiler derived from Profiler |
| kCustomProfiler = 1 << 7, |
| }; |
| |
| // Setup the name of use case the profiler is running. |
| // Argument: |
| // usecase: the name use case of the profiler is running. |
| virtual void SetUseCase(std::string usecase) = 0; |
| |
| // Set the file prefix name for dumpping the profiling file. |
| // Argument: |
| // dump_file_prefix: file prefix name. In the current setting, |
| // "/data/vendor/camera/" is a valid folder for camera to dump file. |
| // A valid prefix can be "/data/vendor/camera/test_prefix_". |
| virtual void SetDumpFilePrefix(const std::string& dump_file_prefix) = 0; |
| |
| // Start to profile. |
| // We use start and end to choose which code snippet to be profile. |
| // The user specifies the name, and the profiler will print the name and its |
| // timing. |
| // Arguments: |
| // name: the name of the node to be profiled. |
| // request_id: frame requesd id. |
| virtual void Start(const std::string& name, int request_id) = 0; |
| |
| // End the profileing. |
| // Arguments: |
| // name: the name of the node to be profiled. Should be the same in Start(). |
| // request_id: frame requesd id. |
| virtual void End(const std::string& name, int request_id) = 0; |
| |
| // Print out the profiling result in the standard output (ANDROID_LOG_ERROR). |
| virtual void PrintResult() = 0; |
| |
| // Profile the frame rate |
| // If only call this function without start() and End(), |
| // creating profiler needs to set option with kPrintFpsPerIntervalBit bit. |
| // It can print FPS every second. |
| virtual void ProfileFrameRate(const std::string& name) = 0; |
| |
| // Set the interval of FPS print |
| // The interval unit is second and interval_seconds must >= 1 |
| virtual void SetFpsPrintInterval(int32_t interval_seconds) = 0; |
| |
| virtual std::vector<LatencyEvent> GetLatencyData() = 0; |
| |
| virtual std::string GetUseCase() const = 0; |
| |
| protected: |
| Profiler() = default; |
| }; |
| |
| // A scoped utility class to facilitate profiling. |
| class ScopedProfiler { |
| public: |
| // Constructor. |
| // Arguments: |
| // profiler: profiler object. |
| // target: the name of the target to be profiled. |
| // request_id: frame requesd id. |
| ScopedProfiler(std::shared_ptr<Profiler> profiler, const std::string target, |
| int request_id) |
| : profiler_(profiler), |
| target_(std::move(target)), |
| request_id_(request_id) { |
| profiler_->Start(target_, request_id_); |
| } |
| |
| ScopedProfiler(std::shared_ptr<Profiler> profiler, const std::string target) |
| : profiler_(profiler), target_(std::move(target)) { |
| request_id_ = Profiler::kInvalidRequestId; |
| profiler_->Start(target_, request_id_); |
| } |
| |
| ScopedProfiler(const std::string target, int option) |
| : target_(std::move(target)) { |
| profiler_ = Profiler::Create(option); |
| request_id_ = Profiler::kInvalidRequestId; |
| profiler_->Start(target_, request_id_); |
| } |
| |
| ~ScopedProfiler() { |
| profiler_->End(target_, request_id_); |
| } |
| |
| private: |
| std::shared_ptr<Profiler> profiler_; |
| const std::string target_; |
| int request_id_; |
| }; |
| |
| } // namespace camera_common |
| } // namespace google |
| |
| #endif // HARDWARE_GOOGLE_CAMERA_COMMON_PROFILER_H |