| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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. |
| */ |
| |
| #pragma once |
| |
| #include <thread> |
| #include <mutex> |
| #include <vector> |
| #include <string> |
| #include <chrono> |
| #include <sys/types.h> |
| #include <unistd.h> |
| |
| namespace ats_plugin |
| { |
| // A single profile, stores data of a taken profile |
| class Profile |
| { |
| public: |
| // Computes the start time and sets the thread id |
| // The duration of the profiles is in microseconds |
| void |
| ComputeStartTime() |
| { |
| this->start_time_ = |
| std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); |
| this->thread_id_ = std::hash<std::thread::id>()(std::this_thread::get_id()); |
| this->process_id_ = getpid(); |
| } |
| |
| // Computes the end time |
| void |
| ComputeEndTime() |
| { |
| this->end_time_ = |
| std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); |
| } |
| |
| // Gettors |
| std::size_t |
| start_time() const |
| { |
| return this->start_time_; |
| } |
| std::size_t |
| end_time() const |
| { |
| return this->end_time_; |
| } |
| std::size_t |
| thread_id() const |
| { |
| return this->thread_id_; |
| } |
| |
| std::size_t |
| process_id() const |
| { |
| return this->process_id_; |
| } |
| std::size_t |
| object_id() const |
| { |
| return this->object_id_; |
| } |
| void |
| set_object_id(std::size_t objId) |
| { |
| object_id_ = objId; |
| } |
| const std::string & |
| task_name() const |
| { |
| return this->task_name_; |
| } |
| |
| // Settors |
| void |
| set_task_name(const std::string &task_name) |
| { |
| this->task_name_ = task_name; |
| } |
| |
| const std::string & |
| obj_stage() const |
| { |
| return this->obj_stage_; |
| } |
| void |
| set_obj_stage(const std::string &obj_stage) |
| { |
| this->obj_stage_ = obj_stage; |
| } |
| |
| private: |
| // The time the profile started |
| std::chrono::high_resolution_clock::rep start_time_; |
| |
| // The time the profile ended |
| std::chrono::high_resolution_clock::rep end_time_; |
| |
| // The id of the thread |
| std::size_t thread_id_; |
| std::size_t process_id_; |
| |
| std::size_t object_id_; |
| // The name of the task of the profile |
| std::string task_name_; |
| std::string obj_stage_; |
| }; |
| |
| // Keeps tracks of the taken profiles and saves the data to a JSON. |
| // In order to take profiles use the embedded class profile taker |
| // The duration is in microseconds |
| class Profiler |
| { |
| public: |
| // The storage of profiles |
| typedef std::vector<Profile> ProfileContainer; |
| |
| // Empty constructor |
| Profiler() : record_enabled_(false) {} |
| // Submits a new profile |
| void |
| SubmitProfile(const Profile &profile) |
| { |
| // Ignore if not enabled |
| if (!this->record_enabled_) |
| return; |
| std::unique_lock<std::mutex> lock(this->profiles_mutex_); |
| this->profiles_.push_back(profile); |
| } |
| |
| // Removes all the profiles |
| void |
| Clear() |
| { |
| std::unique_lock<std::mutex> lock(this->profiles_mutex_); |
| this->profiles_.clear(); |
| } |
| |
| // Gettors |
| bool |
| record_enabled() const |
| { |
| return this->record_enabled_; |
| } |
| const ProfileContainer & |
| profiles() const |
| { |
| return this->profiles_; |
| } |
| |
| void |
| printProfileLength() |
| { |
| std::cout << "Profile Length: " << this->profiles_.size() << std::endl; |
| } |
| // Settors |
| void |
| set_record_enabled(bool enabled) |
| { |
| this->record_enabled_ = enabled; |
| if (!this->record_enabled_) |
| this->Clear(); |
| } |
| |
| private: |
| // The profiles |
| ProfileContainer profiles_; |
| |
| // If true, enabled |
| bool record_enabled_; |
| |
| // The mutex for safe access |
| mutable std::mutex profiles_mutex_; |
| }; |
| |
| // Takes a profile during its life time |
| class ProfileTaker |
| { |
| public: |
| // Initializes a profile |
| ProfileTaker(Profiler *owner, const std::string &task_name, std::size_t objId, const std::string &phase) : owner_(owner) |
| { |
| profile_.ComputeStartTime(); |
| profile_.set_task_name(task_name); |
| profile_.set_obj_stage(phase); |
| profile_.set_object_id(objId); |
| } |
| |
| // Releases a profile and submits it |
| ~ProfileTaker() |
| { |
| // profile_.ComputeEndTime(); |
| owner_->SubmitProfile(this->profile_); |
| // profile_.set_task_name(this->profile_.task_name()); |
| // profile_.set_obj_stage("E"); |
| Profile endProf; |
| endProf.ComputeStartTime(); |
| endProf.set_obj_stage("E"); |
| endProf.set_task_name(this->profile_.task_name()); |
| endProf.set_object_id(this->profile_.object_id()); |
| owner_->SubmitProfile(endProf); |
| } |
| |
| private: |
| // The profile to take care of |
| Profile profile_; |
| |
| // The owner profiler |
| Profiler *owner_; |
| }; |
| } // namespace ats_plugin |