From a2e89784cbc2efdf8944704a2fde21641053e30e Mon Sep 17 00:00:00 2001
From: KyleKlenk <kyle.c.klenk@gmail.com>
Date: Fri, 8 Jul 2022 13:10:23 -0600
Subject: [PATCH] Tested new Timing Class on HRU

---
 build/includes/global/timing_info.hpp       | 12 +++--
 build/includes/hru_actor/hru_actor.hpp      |  3 ++
 build/source/actors/global/global.cpp       | 30 -----------
 build/source/actors/global/timing_info.cpp  | 56 +++++++++++++++++++++
 build/source/actors/hru_actor/hru_actor.cpp | 52 ++++++++++++++++++-
 5 files changed, 117 insertions(+), 36 deletions(-)

diff --git a/build/includes/global/timing_info.hpp b/build/includes/global/timing_info.hpp
index 2b0c9fa..145ee06 100644
--- a/build/includes/global/timing_info.hpp
+++ b/build/includes/global/timing_info.hpp
@@ -3,21 +3,25 @@
 #include <optional>
 #include <vector>
 
-
-
 using chrono_time = std::chrono::time_point<std::chrono::system_clock>;
 
 class TimingInfo {
     private:
         std::vector<std::optional<chrono_time>> start;
         std::vector<std::optional<chrono_time>> end;
-        std::vector<std::optional<std::string>> name_of_time_point; // the name you want for the time point (ie. reading, writing, duration)
+        std::vector<double> duration;
+        std::vector<std::string> name_of_time_point; // the name you want for the time point (ie. reading, writing, duration)
         int num_time_points;
 
+        std::optional<double> calculateDuration(int index);
+        std::optional<int>  getIndex(std::string time_point_name);
+
     public:
         TimingInfo();
         ~TimingInfo();
         void addTimePoint(std::string time_point_name);
-        void updateTimePoint(std::string time_point_name);
+        void updateStartPoint(std::string time_point_name);
+        void updateEndPoint(std::string time_point_name);
+        std::optional<double> getDuration(std::string time_point_name); // returns duration in seconds
 
 };
\ No newline at end of file
diff --git a/build/includes/hru_actor/hru_actor.hpp b/build/includes/hru_actor/hru_actor.hpp
index 2bac162..3943046 100644
--- a/build/includes/hru_actor/hru_actor.hpp
+++ b/build/includes/hru_actor/hru_actor.hpp
@@ -2,6 +2,7 @@
 
 #include "caf/all.hpp"
 #include "fortran_data_types.hpp"
+#include "timing_info.hpp"
 
 #include <chrono>
 #include <string>
@@ -97,6 +98,8 @@ struct hru_state {
     std::chrono::time_point<std::chrono::system_clock> writeOutputEnd;
     double writeOutputDuration = 0.0;
 
+    TimingInfo hru_timing;
+
 };
 
 behavior hru_actor(stateful_actor<hru_state>* self, int refGRU, int indxGRU,
diff --git a/build/source/actors/global/global.cpp b/build/source/actors/global/global.cpp
index fff197e..dff7bf4 100644
--- a/build/source/actors/global/global.cpp
+++ b/build/source/actors/global/global.cpp
@@ -7,33 +7,3 @@ double calculateTime(std::chrono::time_point<std::chrono::system_clock> start,
     
     return std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
 }
-
-// template <typename T>
-// std::optional<T> getSettings(std::string settings_file_path, std::string key_1, std::string key_2, 
-//     T return_value) {
-//     json settings;
-//     std::string summa_actors_settings = "/Summa_Actors_Settings.json";
-//     std::ifstream settings_file(settings_file_path + summa_actors_settings);
-//     settings_file >> settings;
-//     settings_file.close();
-    
-//     // find first key
-//     try {
-//         if (settings.find(key_1) != settings.end()) {
-//             json key_1_settings = settings[key_1];
-
-//             // find value behind second key
-//             if (key_1_settings.find(key_2) != key_1_settings.end()) {
-//                 return key_1_settings[key_2];
-//             } else 
-//                 return {};
-
-//         } else {
-//             return {}; // return none in the optional (error value)
-//         }
-//     } catch (json::exception& e) {
-//         std::cout << e.what() << "\n";
-//         return {};
-//     }
-   
-// }
\ No newline at end of file
diff --git a/build/source/actors/global/timing_info.cpp b/build/source/actors/global/timing_info.cpp
index 034d2a3..5c83987 100644
--- a/build/source/actors/global/timing_info.cpp
+++ b/build/source/actors/global/timing_info.cpp
@@ -1,4 +1,6 @@
 #include "timing_info.hpp"
+#include <chrono>
+#include <algorithm>
 
 TimingInfo::TimingInfo() {
     this->num_time_points = 0;
@@ -6,9 +8,63 @@ TimingInfo::TimingInfo() {
 
 TimingInfo::~TimingInfo(){}
 
+std::optional<double> TimingInfo::calculateDuration(int index) {
+    if (!this->start[index].has_value() || !this->end[index].has_value()) {
+        return {};
+    } else {
+        auto start = this->start[index].value();
+        auto end = this->end[index].value();
+        return std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
+
+    }
+}
+
+std::optional<int> TimingInfo::getIndex(std::string time_point_name) {
+
+    auto itr = std::find(this->name_of_time_point.begin(), 
+        this->name_of_time_point.end(),
+        time_point_name);
+    if (itr != this->name_of_time_point.end()) {
+        return std::distance(this->name_of_time_point.begin(), itr);
+    } else {
+        return {};
+    }
+}
+
 void TimingInfo::addTimePoint(std::string time_point_name) {
     this->name_of_time_point.push_back(time_point_name);
     this->start.push_back({});
     this->end.push_back({});
+    this->duration.push_back(0.0);
     this->num_time_points++;
+}
+
+void TimingInfo::updateStartPoint(std::string time_point_name) {
+    std::optional<int> index = getIndex(time_point_name);
+
+    if (index.has_value()) {
+        this->start[index.value()] = std::chrono::high_resolution_clock::now();
+    }
+}
+
+void TimingInfo::updateEndPoint(std::string time_point_name) {
+    std::optional<int> index = getIndex(time_point_name);
+    if (index.has_value()) {
+        this->end[index.value()] = std::chrono::high_resolution_clock::now();
+        std::optional<double> duration = calculateDuration(index.value());
+        if (duration.has_value())
+            this->duration[index.value()] += duration.value();
+    }
+}
+
+std::optional<double> TimingInfo::getDuration(std::string time_point_name) {
+    std::optional<int> index = getIndex(time_point_name);
+    if (index.has_value()) {
+        double duration = this->duration[index.value()];
+        duration = duration / 1000; // convert to miliseconds
+        duration = duration / 1000; // convert to seconds
+        return duration;
+    } else {
+        return {};
+    }
 }
\ No newline at end of file
diff --git a/build/source/actors/hru_actor/hru_actor.cpp b/build/source/actors/hru_actor/hru_actor.cpp
index 641f2b8..da50ed0 100644
--- a/build/source/actors/hru_actor/hru_actor.cpp
+++ b/build/source/actors/hru_actor/hru_actor.cpp
@@ -8,9 +8,20 @@
 namespace caf {
 
 behavior hru_actor(stateful_actor<hru_state>* self, int refGRU, int indxGRU,
-    std::string configPath,
-    caf::actor file_access_actor, int outputStrucSize, caf::actor parent) {
+    std::string configPath, caf::actor file_access_actor, int outputStrucSize, caf::actor parent) {
+    
     // Timing Information
+    self->state.hru_timing = TimingInfo();
+    self->state.hru_timing.addTimePoint("total_duration");
+    self->state.hru_timing.updateStartPoint("total_duration");
+    // Add the rest of the timing
+    self->state.hru_timing.addTimePoint("init_duration");
+    self->state.hru_timing.addTimePoint("forcing_duration");
+    self->state.hru_timing.addTimePoint("run_physics_duration");
+    self->state.hru_timing.addTimePoint("write_output_duration");
+
+
+
     self->state.start = std::chrono::high_resolution_clock::now();
     self->state.duration            = 0.0;
     self->state.initDuration        = 0.0;
@@ -54,12 +65,16 @@ behavior hru_actor(stateful_actor<hru_state>* self, int refGRU, int indxGRU,
     self->state.end = std::chrono::high_resolution_clock::now();
     self->state.duration += calculateTime(self->state.start, self->state.end);
 
+    self->state.hru_timing.updateEndPoint("total_duration");
+
     self->send(self->state.parent, done_init_hru_v);
 
     return {
         // Starts the HRU and tells it to ask for data from the file_access_actor
         [=](start_hru) {
             self->state.start = std::chrono::high_resolution_clock::now();
+            self->state.hru_timing.updateStartPoint("total_duration");
+
             
             int err;
             
@@ -76,17 +91,22 @@ behavior hru_actor(stateful_actor<hru_state>* self, int refGRU, int indxGRU,
             
             self->send(self->state.file_access_actor, access_forcing_v, self->state.iFile, self);
             self->state.end = std::chrono::high_resolution_clock::now();
+            self->state.hru_timing.updateEndPoint("total_duration");
+
             self->state.duration += calculateTime(self->state.start, self->state.end);
         },
 
         [=](done_write) {
             self->state.start = std::chrono::high_resolution_clock::now();
+            self->state.hru_timing.updateStartPoint("total_duration");
 
             // We receive a done_write message so we ensure that
             // stepsInCurrentFFile remains unchanged
             if (self->state.timestep >= self->state.num_steps) {
                 
                 self->state.end = std::chrono::high_resolution_clock::now();
+                self->state.hru_timing.updateEndPoint("total_duration");
+
                 self->state.duration += calculateTime(self->state.start, self->state.end);
                 // Tell our parent we are done, convert all timings to seconds
 
@@ -95,6 +115,13 @@ behavior hru_actor(stateful_actor<hru_state>* self, int refGRU, int indxGRU,
                 self->state.forcingDuration = self->state.forcingDuration / 1000; // Convert to milliseconds
                 self->state.runPhysicsDuration = self->state.runPhysicsDuration / 1000; // Convert to milliseconds
                 self->state.writeOutputDuration = self->state.writeOutputDuration / 1000; // Convert to milliseconds
+                aout(self) << "\n________________PRINTING HRU TIMING INFO RESULTS________________\n";
+                aout(self) << "Total Duration = " << self->state.hru_timing.getDuration("total_duration").value_or(-1.0) << "\n";
+                aout(self) << "Init Duration = " << self->state.hru_timing.getDuration("init_duration").value_or(-1.0) << "\n";
+                aout(self) << "Forcing Duration = " << self->state.hru_timing.getDuration("forcing_duration").value_or(-1.0) << "\n";
+                aout(self) << "Run Physics Duration = " << self->state.hru_timing.getDuration("run_physics_duration").value_or(-1.0) << "\n";
+                aout(self) << "Write Output Duration = " << self->state.hru_timing.getDuration("write_output_duration").value_or(-1.0) << "\n";
+
 
                 self->send(self->state.parent, 
                     done_hru_v,
@@ -112,6 +139,8 @@ behavior hru_actor(stateful_actor<hru_state>* self, int refGRU, int indxGRU,
             }
 
             self->state.end = std::chrono::high_resolution_clock::now();
+            self->state.hru_timing.updateEndPoint("total_duration");
+            
             self->state.duration += calculateTime(self->state.start, self->state.end);
             
             self->send(self, run_hru_v, self->state.stepsInCurrentFFile);
@@ -119,6 +148,8 @@ behavior hru_actor(stateful_actor<hru_state>* self, int refGRU, int indxGRU,
 
         [=](run_hru, int stepsInCurrentFFile) {
             self->state.start = std::chrono::high_resolution_clock::now();
+            self->state.hru_timing.updateStartPoint("total_duration");
+
             bool keepRunning = true;
             int err = 0;
             self->state.stepsInCurrentFFile = stepsInCurrentFFile;
@@ -141,6 +172,8 @@ behavior hru_actor(stateful_actor<hru_state>* self, int refGRU, int indxGRU,
             }
      
             self->state.end = std::chrono::high_resolution_clock::now();
+            self->state.hru_timing.updateEndPoint("total_duration");
+
             self->state.duration += calculateTime(self->state.start, self->state.end);
 
         },
@@ -157,6 +190,8 @@ behavior hru_actor(stateful_actor<hru_state>* self, int refGRU, int indxGRU,
 
 void Initialize_HRU(stateful_actor<hru_state>* self) {
     self->state.initStart = std::chrono::high_resolution_clock::now();
+    self->state.hru_timing.updateStartPoint("init_duration");
+    
     // aout(self) << "Initalizing HRU" << std::endl;
     // aout(self) << "Entering Initalize \n"; 
     summaActors_initialize(&self->state.indxGRU,
@@ -233,6 +268,8 @@ void Initialize_HRU(stateful_actor<hru_state>* self) {
             
     // aout(self) << self->state.refGRU << " - Done Init" << std::endl;
     self->state.initEnd = std::chrono::high_resolution_clock::now();
+    self->state.hru_timing.updateEndPoint("init_duration");
+
     self->state.initDuration = calculateTime(self->state.initStart, self->state.initEnd);
 }
 
@@ -241,6 +278,8 @@ int Run_HRU(stateful_actor<hru_state>* self) {
     ** READ FORCING
     **********************************************************************/    
     self->state.forcingStart = std::chrono::high_resolution_clock::now();
+    self->state.hru_timing.updateStartPoint("forcing_duration");
+
     Forcing(&self->state.indxGRU,
         &self->state.timestep,
         self->state.handle_timeStruct,
@@ -259,6 +298,8 @@ int Run_HRU(stateful_actor<hru_state>* self) {
 
     }
     self->state.forcingEnd = std::chrono::high_resolution_clock::now();
+    self->state.hru_timing.updateEndPoint("forcing_duration");
+
     self->state.forcingDuration += calculateTime(self->state.forcingStart, self->state.forcingEnd);
 
 
@@ -272,6 +313,8 @@ int Run_HRU(stateful_actor<hru_state>* self) {
     ** RUN_PHYSICS    
     **********************************************************************/    
     self->state.runPhysicsStart = std::chrono::high_resolution_clock::now();
+    self->state.hru_timing.updateStartPoint("run_physics_duration");
+
     self->state.err = 0;
     RunPhysics(&self->state.indxHRU,
         &self->state.timestep,
@@ -299,12 +342,14 @@ int Run_HRU(stateful_actor<hru_state>* self) {
         return 20;
     }
     self->state.runPhysicsEnd = std::chrono::high_resolution_clock::now();
+    self->state.hru_timing.updateEndPoint("run_physics_duration");
     self->state.runPhysicsDuration += calculateTime(self->state.runPhysicsStart, self->state.runPhysicsEnd);
 
     /**********************************************************************
     ** WRITE_OUTPUT  
     **********************************************************************/
     self->state.writeOutputStart = std::chrono::high_resolution_clock::now();
+    self->state.hru_timing.updateStartPoint("write_output_duration");
     WriteOutput(&self->state.indxHRU,
             &self->state.indxGRU,
             &self->state.timestep,
@@ -340,6 +385,7 @@ int Run_HRU(stateful_actor<hru_state>* self) {
         return 30;
     }
     self->state.writeOutputEnd = std::chrono::high_resolution_clock::now();
+    self->state.hru_timing.updateEndPoint("write_output_duration");
     self->state.writeOutputDuration += calculateTime(self->state.writeOutputStart, self->state.writeOutputEnd);
 
     return 0;      
@@ -369,6 +415,8 @@ bool check_HRU(stateful_actor<hru_state>* self, int err) {
             self->state.indxGRU, self->state.indxHRU, self->state.outputStep, self);
 
         self->state.end = std::chrono::high_resolution_clock::now();
+        self->state.hru_timing.updateEndPoint("total_duration");
+
         self->state.duration += calculateTime(self->state.start, self->state.end);
 
         return false;
-- 
GitLab