From 7f15ef65f420179b606f136ed805fae9d320b321 Mon Sep 17 00:00:00 2001 From: Romain Forlot Date: Sun, 22 Jul 2018 01:13:17 +0200 Subject: Improved performance Before value was translated to a C type variable two times, at the reception then at the emission. Now it just receives and sends the signal value without translation nor interpretation except if you ask for an average, minimum or maximum value. Then in those cases it interprets the json to return you a value or an error if there is no numeric values to compute. Remove unneeded log message at event reception. Improved signal search engine, will search in source's signals map by the signal ID not the event name which lead to a more direct map match. Bugs-AGL: SPEC-1612 Depends-On: I43e79ed73a507ac2ca7ed4cdc3f16ec009392194 Change-Id: Ie253c3fe1e8cde42dabe8832da74e9f9bf442c14 Signed-off-by: Romain Forlot --- .../signal-composer-binding.cpp | 4 +- signal-composer-binding/signal-composer.cpp | 62 ++------- signal-composer-binding/signal.cpp | 139 ++++++++++++--------- signal-composer-binding/signal.hpp | 45 ++----- signal-composer-binding/source.cpp | 2 +- 5 files changed, 102 insertions(+), 150 deletions(-) (limited to 'signal-composer-binding') diff --git a/signal-composer-binding/signal-composer-binding.cpp b/signal-composer-binding/signal-composer-binding.cpp index 0d9c8e3..f7c8c73 100644 --- a/signal-composer-binding/signal-composer-binding.cpp +++ b/signal-composer-binding/signal-composer-binding.cpp @@ -32,10 +32,8 @@ /// @param[in] object - eventual data that comes with the event void onEvent(const char *event, json_object *object) { - Composer& composer = Composer::instance(); - AFB_NOTICE("event: %s", json_object_to_json_string(object)); + std::vector> signals { Composer::instance().searchSignals(event) }; - std::vector> signals = composer.searchSignals(event); if(!signals.empty()) { // If there is more than 1 element then maybe we can find a more diff --git a/signal-composer-binding/signal-composer.cpp b/signal-composer-binding/signal-composer.cpp index 99129b4..f7c1971 100644 --- a/signal-composer-binding/signal-composer.cpp +++ b/signal-composer-binding/signal-composer.cpp @@ -21,7 +21,7 @@ #include "clientApp.hpp" -extern "C" void searchNsetSignalValueHandle(const char* aName, uint64_t timestamp, struct signalValue value) +extern "C" void searchNsetSignalValueHandle(const char* aName, uint64_t timestamp, json_object* value) { std::vector> signals = Composer::instance().searchSignals(aName); if(!signals.empty()) @@ -31,7 +31,7 @@ extern "C" void searchNsetSignalValueHandle(const char* aName, uint64_t timestam } } -extern "C" void setSignalValueHandle(void* aSignal, uint64_t timestamp, struct signalValue value) +extern "C" void setSignalValueHandle(void* aSignal, uint64_t timestamp, json_object* value) { Signal* sig = static_cast(aSignal); sig->set(timestamp, value); @@ -380,47 +380,25 @@ void Composer::processOptions(const std::map& opts, std::share { avg = true; double value = sig->average(o.second); - json_object_object_add(response, "value", - json_object_new_double(value)); + json_object_object_add(response, "value", json_object_new_double(value)); } else if (o.first.compare("minimum") && !min) { min = true; double value = sig->minimum(); - json_object_object_add(response, "value", - json_object_new_double(value)); + json_object_object_add(response, "value", json_object_new_double(value)); } else if (o.first.compare("maximum") && !max) { max = true; double value = sig->maximum(); - json_object_object_add(response, "value", - json_object_new_double(value)); + json_object_object_add(response, "value", json_object_new_double(value)); } else if (o.first.compare("last") && !last) { last = true; - struct signalValue value = sig->last_value(); - if(value.hasBool) - { - json_object_object_add(response, "value", - json_object_new_boolean(value.boolVal)); - } - else if(value.hasNum) - { - json_object_object_add(response, "value", - json_object_new_double(value.numVal)); - } - else if(value.hasStr) - { - json_object_object_add(response, "value", - json_object_new_string(value.strVal.c_str())); - } - else - { - json_object_object_add(response, "value", - json_object_new_string("No recorded value so far.")); - } + json_object* value = sig->last_value(); + json_object_object_add(response, "value", value); } else { @@ -568,8 +546,9 @@ std::vector> Composer::searchSignals(const std::string& if(sep != std::string::npos) { api = aName.substr(0, sep); + std::string signal_id = aName.substr(sep + 1, std::string::npos); std::shared_ptr source = getSourceAPI(api); - return source->searchSignals(aName); + return source->searchSignals(signal_id); } else { @@ -603,27 +582,8 @@ json_object* Composer::getsignalValue(const std::string& sig, json_object* optio "signal", sig->id().c_str()); if (opts.empty()) { - struct signalValue value = sig->last_value(); - if(value.hasBool) - { - json_object_object_add(response, "value", - json_object_new_boolean(value.boolVal)); - } - else if(value.hasNum) - { - json_object_object_add(response, "value", - json_object_new_double(value.numVal)); - } - else if(value.hasStr) - { - json_object_object_add(response, "value", - json_object_new_string(value.strVal.c_str())); - } - else - { - json_object_object_add(response, "value", - json_object_new_string("No recorded value so far.")); - } + json_object* value = sig->last_value(); + json_object_object_add(response, "value", value); } else {processOptions(opts, sig, response);} diff --git a/signal-composer-binding/signal.cpp b/signal-composer-binding/signal.cpp index 2f1aa57..14e85ba 100644 --- a/signal-composer-binding/signal.cpp +++ b/signal-composer-binding/signal.cpp @@ -148,9 +148,8 @@ json_object* Signal::toJSON() const if(timestamp_) json_object_object_add(sigJ, "timestamp", json_object_new_int64(timestamp_)); - if (value_.hasBool) {json_object_object_add(sigJ, "value", json_object_new_boolean(value_.boolVal));} - else if (value_.hasNum) {json_object_object_add(sigJ, "value", json_object_new_double(value_.numVal));} - else if (value_.hasStr) {json_object_object_add(sigJ, "value", json_object_new_string(value_.strVal.c_str()));} + if(value_) + json_object_object_add(sigJ, "value", value_); return sigJ; } @@ -198,19 +197,21 @@ json_object *Signal::getSignalsArgs() /// /// @param[in] timestamp - timestamp of occured signal /// @param[in] value - value of change -void Signal::set(uint64_t timestamp, struct signalValue& value) +void Signal::set(uint64_t timestamp, json_object*& value) { uint64_t diff = retention_+1; value_ = value; timestamp_ = timestamp; - history_[timestamp_] = value_; + history_[timestamp_] = json_object_get(value_); while(diff > retention_) { uint64_t first = history_.begin()->first; diff = (timestamp_ - first)/NANO; - if(diff > retention_) - {history_.erase(history_.cbegin());} + if(diff > retention_) { + json_object_put(history_.cbegin()->second); + history_.erase(history_.cbegin()); + } } notify(); @@ -253,37 +254,22 @@ void Signal::update(Signal* sig) /// @param[in] eventJ - json_object containing event data to process /// /// @return 0 if ok, -1 or others if not -void Signal::defaultReceivedCB(json_object *eventJ) +void Signal::defaultReceivedCB(Signal *signal, json_object *eventJ) { uint64_t ts = 0; - struct signalValue sv; + json_object* sv = nullptr; json_object_iterator iter = json_object_iter_begin(eventJ); json_object_iterator iterEnd = json_object_iter_end(eventJ); + while(!json_object_iter_equal(&iter, &iterEnd)) { std::string key = json_object_iter_peek_name(&iter); std::transform(key.begin(), key.end(), key.begin(), ::tolower); json_object *value = json_object_iter_peek_value(&iter); if (key.find("value") != std::string::npos || - key.find(id_) != std::string::npos) + key.find(signal->id()) != std::string::npos) { - switch (json_object_get_type(value)) { - case json_type_double: - sv = json_object_get_double(value); - break; - case json_type_int: - sv = json_object_get_int(value); - break; - case json_type_boolean: - sv = json_object_get_int(value); - break; - case json_type_string: - sv = json_object_get_string(value); - break; - default: - sv = signalValue(); - break; - } + sv = json_object_get(value); } else if (key.find("timestamp") != std::string::npos) { @@ -292,9 +278,9 @@ void Signal::defaultReceivedCB(json_object *eventJ) json_object_iter_next(&iter); } - if(!sv.hasBool && !sv.hasNum && !sv.hasStr) + if(!sv) { - AFB_ERROR("No data found to set signal %s in %s", id_.c_str(), json_object_to_json_string(eventJ)); + AFB_ERROR("No data found to set signal %s in %s", signal->id().c_str(), json_object_to_json_string(eventJ)); return; } else if(ts == 0) @@ -305,7 +291,7 @@ void Signal::defaultReceivedCB(json_object *eventJ) ts = (uint64_t)(t.tv_sec) * (uint64_t)NANO + (uint64_t)(t.tv_nsec); } - set(ts, sv); + signal->set(ts, sv); } /// @brief Notify observers that there is a change and execute callback defined @@ -343,7 +329,7 @@ void Signal::onReceivedCB(json_object *eventJ) if (onReceived_) ActionExecOne(&source, onReceived_, json_object_get(eventJ)); else - defaultReceivedCB(eventJ); + defaultReceivedCB(this, eventJ); } /// @brief Make a Signal observer observes Signals observables @@ -382,22 +368,31 @@ double Signal::average(int seconds) const double total = 0.0; int nbElt = 0; - for (const auto& val: history_) + for(const auto& val: history_) { - if(val.first >= end) - {break;} - if(val.second.hasNum) + if(val.first >= end) { + break; + } + if(val.second) { - total += val.second.numVal; + switch(json_object_get_type(val.second)) { + case json_type_int: + total += static_cast(json_object_get_int64(val.second)); + break; + case json_type_double: + total += json_object_get_double(val.second); + break; + default: + AFB_ERROR("The stored value '%s' for the signal '%s' isn't numeric, it is not possible to compute an average value.", json_object_get_string(val.second), id_.c_str()); + break; + } nbElt++; } else { - AFB_ERROR("There isn't numerical value to compare with in that signal '%s'. Stored value : bool %d, num %lf, str: %s", + AFB_ERROR("There isn't numerical value to compare with in that signal '%s'. Stored value: %s", id_.c_str(), - val.second.boolVal, - val.second.numVal, - val.second.strVal.c_str()); + json_object_get_string(val.second)); break; } } @@ -416,21 +411,34 @@ double Signal::minimum(int seconds) const uint64_t end = seconds ? begin+(seconds*NANO) : history_.rbegin()->first; + double current = 0.0; double min = DBL_MAX; - for (auto& v : history_) + for(const auto& val : history_) { - if(v.first >= end) - {break;} - else if(v.second.hasNum && v.second.numVal < min) - {min = v.second.numVal;} + if(val.first >= end) { + break; + } + else if(val.second) { + switch(json_object_get_type(val.second)) { + case json_type_int: + current = static_cast(json_object_get_int64(val.second)); + min = current < min ? current : min; + break; + case json_type_double: + current = json_object_get_double(val.second); + min = current < min ? current : min; + break; + default: + AFB_ERROR("The stored value '%s' for signal '%s' isn't numeric, it is not possible to find a minimum value.", json_object_get_string(val.second), id_.c_str()); + break; + } + } else { - AFB_ERROR("There isn't numerical value to compare with in that signal '%s'. Stored value : bool %d, num %lf, str: %s", + AFB_ERROR("There isn't numerical value to compare with in that signal '%s'. Stored value: %s", id_.c_str(), - v.second.boolVal, - v.second.numVal, - v.second.strVal.c_str()); + json_object_get_string(val.second)); break; } } @@ -448,21 +456,34 @@ double Signal::maximum(int seconds) const uint64_t end = seconds ? begin+(seconds*NANO) : history_.rbegin()->first; + double current = 0.0; double max = 0.0; - for (auto& v : history_) + for(const auto& val : history_) { - if(v.first >= end) - {break;} - else if(v.second.hasNum && v.second.hasNum > max) - {max = v.second.numVal;} + if(val.first >= end) { + break; + } + else if(val.second) { + switch(json_object_get_type(val.second)) { + case json_type_int: + current = static_cast(json_object_get_int64(val.second)); + max = current > max ? current : max; + break; + case json_type_double: + current = json_object_get_double(val.second); + max = current > max ? current : max; + break; + default: + AFB_ERROR("The stored value '%s' for signal '%s' isn't numeric, it is not possible to find a maximum value.", json_object_get_string(val.second), id_.c_str()); + break; + } + } else { - AFB_ERROR("There isn't numerical value to compare with in that signal '%s'. Stored value : bool %d, num %lf, str: %s", + AFB_ERROR("There isn't numerical value to compare with in that signal '%s'. Stored value: %s", id_.c_str(), - v.second.boolVal, - v.second.numVal, - v.second.strVal.c_str()); + json_object_get_string(val.second)); break; } } @@ -472,7 +493,7 @@ double Signal::maximum(int seconds) const /// @brief Return last value recorded /// /// @return Last value -struct signalValue Signal::last_value() const +json_object* Signal::last_value() const { return value_; } diff --git a/signal-composer-binding/signal.hpp b/signal-composer-binding/signal.hpp index 0a12b16..6c7f43f 100644 --- a/signal-composer-binding/signal.hpp +++ b/signal-composer-binding/signal.hpp @@ -28,40 +28,14 @@ class Composer; -/// @brief Structure holding a possible value of a Signal -/// as it could be different type of value, we declare all -/// possibility. -/// Not very efficient or optimized, maybe use of Variant in -/// C++17 but this is a bit too new to uses it for now -struct signalValue { - bool undefined; - bool hasBool; - bool boolVal; - bool hasNum; - double numVal; - bool hasStr; - std::string strVal; - - signalValue(): - undefined(true), hasBool(false), boolVal(false), hasNum(false), numVal(0), hasStr(false), strVal("") {}; - signalValue(bool b): - undefined(false), hasBool(true), boolVal(b), hasNum(false), numVal(0), hasStr(false), strVal("") {}; - signalValue(int i): - undefined(false), hasBool(false), boolVal(false), hasNum(true), numVal(i), hasStr(false), strVal("") {}; - signalValue(double d): - undefined(false), hasBool(false), boolVal(false), hasNum(true), numVal(d), hasStr(false), strVal("") {}; - signalValue(const std::string& s): - undefined(false), hasBool(false), boolVal(false), hasNum(false), numVal(0), hasStr(true), strVal(s) {}; -}; - -extern "C" void searchNsetSignalValueHandle(const char* aName, uint64_t timestamp, struct signalValue value); -extern "C" void setSignalValueHandle(void* aSignal, uint64_t timestamp, struct signalValue value); +extern "C" void searchNsetSignalValueHandle(const char* aName, uint64_t timestamp, json_object* value); +extern "C" void setSignalValueHandle(void* aSignal, uint64_t timestamp, json_object* value); /// @brief Holds composer callbacks and obj to manipulate struct signalCBT { - void (*searchNsetSignalValue)(const char* aName, uint64_t timestamp, struct signalValue value); - void (*setSignalValue)(void* aSignal, uint64_t timestamp, struct signalValue value); + void (*searchNsetSignalValue)(const char* aName, uint64_t timestamp, json_object* value); + void (*setSignalValue)(void* aSignal, uint64_t timestamp, json_object* value); void* aSignal; void* pluginCtx; }; @@ -80,8 +54,8 @@ private: std::string event_; std::vector dependsSigV_; uint64_t timestamp_; - struct signalValue value_; - std::map history_; ///< history_ - Hold signal value history in map with + json_object* value_; + std::map history_; ///< history_ - Hold signal value history in map with int retention_; double frequency_; std::string unit_; @@ -107,17 +81,16 @@ public: struct signalCBT* get_context(); json_object *getSignalsArgs(); - void set(uint64_t timestamp, struct signalValue& value); + void set(uint64_t timestamp, json_object*& value); void update(Signal* sig); - static int defaultOnReceivedCB(CtlSourceT* source, json_object* argsJ, json_object *queryJ); - void defaultReceivedCB(json_object *eventJ); + static void defaultReceivedCB(Signal *signal, json_object *eventJ); void onReceivedCB(json_object *eventJ); void attachToSourceSignals(Composer& composer); double average(int seconds = 0) const; double minimum(int seconds = 0) const; double maximum(int seconds = 0) const; - struct signalValue last_value() const; + json_object* last_value() const; uint64_t last_timestamp() const; int initialRecursionCheck(); diff --git a/signal-composer-binding/source.cpp b/signal-composer-binding/source.cpp index a46e766..bd988c9 100644 --- a/signal-composer-binding/source.cpp +++ b/signal-composer-binding/source.cpp @@ -122,7 +122,7 @@ std::vector> SourceAPI::searchSignals(const std::string& if(signalsM_.count(name)) {signals.emplace_back(signalsM_[name]);} - if(newSignalsM_.count(name)) + else if(newSignalsM_.count(name)) {signals.emplace_back(signalsM_[name]);} else { -- cgit 1.2.3-korg