Changes have been pushed for the project "Fawkes Robotics Software Framework".
Gitweb: http://git.fawkesrobotics.org/fawkes.git Trac: http://trac.fawkesrobotics.org The branch, thofmann/syncpoint has been updated to fae64cec3380775baddf8c6877c2bb24efa7c39f (commit) via 13857c9b1f62c09a1bbd68a05f246dc0063541c6 (commit) from 02a4bc618e2d7a7f00773db39d332e3eafe4c784 (commit) http://git.fawkesrobotics.org/fawkes.git/thofmann/syncpoint Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - *Log* --------------------------------------------------------------- commit 13857c9b1f62c09a1bbd68a05f246dc0063541c6 Author: Till Hofmann <hofm...@kbsg.rwth-aachen.de> AuthorDate: Fri Aug 15 19:49:05 2014 +0200 Commit: Till Hofmann <hofm...@kbsg.rwth-aachen.de> CommitDate: Fri Aug 15 19:49:05 2014 +0200 syncpoint: add support for visualization Add all necessary data structures to the syncpoint library to be able to visualize call sequences. We now store all recent calls in a CircularBuffer and keep track of calling statistics (first call, last call, frequency, wait time). Furthermore, we use that data to generate a DOT graph. This could for example be used to show the call graph in webview. http://git.fawkesrobotics.org/fawkes.git/commit/13857c9 http://trac.fawkesrobotics.org/changeset/13857c9 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - commit fae64cec3380775baddf8c6877c2bb24efa7c39f Author: Till Hofmann <hofm...@kbsg.rwth-aachen.de> AuthorDate: Fri Aug 15 20:01:14 2014 +0200 Commit: Till Hofmann <hofm...@kbsg.rwth-aachen.de> CommitDate: Fri Aug 15 20:04:33 2014 +0200 webview: add SyncPoint visualization Visualize SyncPoints with a graph. This shows all currently used SyncPoints and visualizes emit and wait calls to those SyncPoints. Furthermore, some basic information such as last wait()/emit() call, average waiting time and emit frequency are shown. http://git.fawkesrobotics.org/fawkes.git/commit/fae64ce http://trac.fawkesrobotics.org/changeset/fae64ce - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *Summary* ----------------------------------------------------------- cfg/conf.d/webview.yaml | 5 +- src/libs/syncpoint/Makefile | 2 +- src/libs/syncpoint/syncpoint.cpp | 44 ++++++++ src/libs/syncpoint/syncpoint.h | 18 +++- src/libs/syncpoint/syncpoint_call.cpp | 74 +++++++++++++ .../syncpoint_call.h} | 31 +++--- src/libs/syncpoint/syncpoint_call_stats.cpp | 110 ++++++++++++++++++++ .../syncpoint_call_stats.h} | 35 ++++--- src/libs/syncpoint/syncpoint_manager.cpp | 71 +++++++++++++ src/libs/syncpoint/syncpoint_manager.h | 3 + src/plugins/webview/Makefile | 12 ++- .../{tf_processor.cpp => syncpoint_processor.cpp} | 55 +++++----- .../{tf_processor.h => syncpoint_processor.h} | 26 ++--- src/plugins/webview/webview_thread.cpp | 14 +++ src/plugins/webview/webview_thread.h | 6 + 15 files changed, 433 insertions(+), 73 deletions(-) create mode 100644 src/libs/syncpoint/syncpoint_call.cpp copy src/libs/{aspect/inifins/syncpoint_manager.h => syncpoint/syncpoint_call.h} (62%) create mode 100644 src/libs/syncpoint/syncpoint_call_stats.cpp copy src/libs/{aspect/inifins/syncpoint_manager.h => syncpoint/syncpoint_call_stats.h} (56%) copy src/plugins/webview/{tf_processor.cpp => syncpoint_processor.cpp} (56%) copy src/plugins/webview/{tf_processor.h => syncpoint_processor.h} (63%) - *Diffs* ------------------------------------------------------------- - *commit* 13857c9b1f62c09a1bbd68a05f246dc0063541c6 - - - - - - - - - - Author: Till Hofmann <hofm...@kbsg.rwth-aachen.de> Date: Fri Aug 15 19:49:05 2014 +0200 Subject: syncpoint: add support for visualization src/libs/syncpoint/Makefile | 2 +- src/libs/syncpoint/syncpoint.cpp | 44 ++++++++ src/libs/syncpoint/syncpoint.h | 18 +++- src/libs/syncpoint/syncpoint_call.cpp | 74 +++++++++++++ .../syncpoint_call.h} | 31 +++--- src/libs/syncpoint/syncpoint_call_stats.cpp | 110 ++++++++++++++++++++ .../syncpoint_call_stats.h} | 35 ++++--- src/libs/syncpoint/syncpoint_manager.cpp | 71 +++++++++++++ src/libs/syncpoint/syncpoint_manager.h | 3 + 9 files changed, 357 insertions(+), 31 deletions(-) _Diff for modified files_: diff --git a/src/libs/syncpoint/Makefile b/src/libs/syncpoint/Makefile index 494a926..154a448 100644 --- a/src/libs/syncpoint/Makefile +++ b/src/libs/syncpoint/Makefile @@ -17,7 +17,7 @@ BASEDIR = ../../.. include $(BASEDIR)/etc/buildsys/config.mk -LIBS_libfawkessyncpoint = fawkescore +LIBS_libfawkessyncpoint = fawkescore fawkesutils OBJS_libfawkessyncpoint = $(patsubst %.cpp,%.o,$(patsubst qa/%,,$(subst $(SRCDIR)/,,$(realpath $(wildcard $(SRCDIR)/*.cpp))))) HDRS_libfawkessyncpoint = $(subst $(SRCDIR)/,,$(wildcard $(SRCDIR)/*.h)) diff --git a/src/libs/syncpoint/syncpoint.cpp b/src/libs/syncpoint/syncpoint.cpp index 927ec66..ba7b35f 100644 --- a/src/libs/syncpoint/syncpoint.cpp +++ b/src/libs/syncpoint/syncpoint.cpp @@ -22,6 +22,8 @@ #include <syncpoint/syncpoint.h> #include <syncpoint/exceptions.h> +#include <utils/time/time.h> + #include <string.h> namespace fawkes { @@ -29,6 +31,7 @@ namespace fawkes { } #endif + /** @class SyncPoint <syncpoint/syncpoint.h> * The SyncPoint class. * This class is used for dynamic synchronization of threads which depend @@ -49,6 +52,9 @@ namespace fawkes { */ SyncPoint::SyncPoint(const char * identifier) : identifier_(identifier), + emit_calls_(CircularBuffer<SyncPointCall>(1000)), + wait_calls_(CircularBuffer<SyncPointCall>(1000)), + creation_time_(Time()), mutex(new Mutex()), wait_condition(new WaitCondition(mutex)) { @@ -112,6 +118,7 @@ SyncPoint::emit(const char * component) throw SyncPointNonWatcherCalledEmitException(component, get_identifier()); } waiting_watchers.clear(); + emit_calls_.push_back(SyncPointCall(component)); wait_condition->wake_all(); mutex->unlock(); } @@ -133,8 +140,45 @@ SyncPoint::wait(const char * component) { throw SyncPointMultipleWaitCallsException(component, get_identifier()); } waiting_watchers.insert(component); + Time start; wait_condition->wait(); + Time wait_time = Time() - start; + wait_calls_.push_back(SyncPointCall(component, start, wait_time)); + mutex->unlock(); +} + +/** + * @return all watchers of the SyncPoint + */ +std::set<const char *> +SyncPoint::get_watchers() const { + mutex->lock(); + std::set<const char *> ret = watchers; + mutex->unlock(); + return ret; +} + +/** + * @return a copy of the wait call buffer + */ +CircularBuffer<SyncPointCall> +SyncPoint::get_wait_calls() const { + mutex->lock(); + CircularBuffer<SyncPointCall> ret(wait_calls_); + mutex->unlock(); + return ret; +} + + +/** + * @return a copy of the emit call buffer + */ +CircularBuffer<SyncPointCall> +SyncPoint::get_emit_calls() const { + mutex->lock(); + CircularBuffer<SyncPointCall> ret(emit_calls_); mutex->unlock(); + return ret; } } // namespace fawkes diff --git a/src/libs/syncpoint/syncpoint.h b/src/libs/syncpoint/syncpoint.h index 8fe3707..4222435 100644 --- a/src/libs/syncpoint/syncpoint.h +++ b/src/libs/syncpoint/syncpoint.h @@ -24,10 +24,15 @@ #include <interface/interface.h> #include <syncpoint/syncpoint_manager.h> +#include <syncpoint/syncpoint_call.h> #include <core/threading/mutex.h> #include <core/threading/wait_condition.h> +#include <utils/time/time.h> + +#include <core/utils/circular_buffer.h> #include <set> +#include <map> namespace fawkes { #if 0 /* just to make Emacs auto-indent happy */ @@ -35,6 +40,8 @@ namespace fawkes { #endif class SyncPointManager; +class SyncPointCall; + class SyncPoint { @@ -52,16 +59,25 @@ class SyncPoint bool operator==(const SyncPoint & other) const; bool operator<(const SyncPoint & other) const; + std::set<const char *> get_watchers() const; + CircularBuffer<SyncPointCall> get_wait_calls() const; + CircularBuffer<SyncPointCall> get_emit_calls() const; + + /** * allow Syncpoint Manager to edit */ friend SyncPointManager; private: - const char * identifier_; + const char * const identifier_; std::set<const char *> watchers; std::set<const char *> waiting_watchers; + CircularBuffer<SyncPointCall> emit_calls_; + CircularBuffer<SyncPointCall> wait_calls_; + const Time creation_time_; + Mutex *mutex; WaitCondition *wait_condition; }; diff --git a/src/libs/syncpoint/syncpoint_manager.cpp b/src/libs/syncpoint/syncpoint_manager.cpp index 6ba24a9..e9e4861 100644 --- a/src/libs/syncpoint/syncpoint_manager.cpp +++ b/src/libs/syncpoint/syncpoint_manager.cpp @@ -22,7 +22,10 @@ #include <syncpoint/syncpoint_manager.h> #include <syncpoint/exceptions.h> +#include "syncpoint_call_stats.h" + #include <string.h> +#include <sstream> namespace fawkes { #if 0 /* just to make Emacs auto-indent happy */ @@ -147,4 +150,72 @@ SyncPointManager::get_syncpoints() { return syncpoints_; } +/** + * Get DOT graph for all SyncPoints + * @param max_age Show only SyncPoint calls which are younger than max_age + * @return string representation of DOT graph + */ +std::string +SyncPointManager::all_syncpoints_as_dot(float max_age) +{ + std::stringstream graph; + graph << std::fixed; //fixed point notation + graph.precision(3); //3 decimal places + graph << "digraph { graph [fontsize=14]; " + << "node [fontsize=12]; edge [fontsize=12]; "; + graph.setf(std::ios::fixed, std::ios::floatfield); + + for (std::set<RefPtr<SyncPoint>, SyncPointSetLessThan>::const_iterator sp_it = syncpoints_.begin(); + sp_it != syncpoints_.end(); sp_it++) { + Time lifetime = Time() - (*sp_it)->creation_time_; + graph << "\"" << (*sp_it)->get_identifier() << "\";"; + + // EMIT CALLS + CircularBuffer<SyncPointCall> emit_calls = (*sp_it)->get_emit_calls(); + // generate call stats + std::map<const char *, SyncPointCallStats> emit_call_stats; + for (CircularBuffer<SyncPointCall>::iterator emitcalls_it = emit_calls.begin(); + emitcalls_it != emit_calls.end(); emitcalls_it++) { + emit_call_stats[emitcalls_it->get_caller()].update_calls(emitcalls_it->get_call_time()); + } + + for (std::map<const char *, SyncPointCallStats>::iterator emit_call_stats_it = emit_call_stats.begin(); + emit_call_stats_it != emit_call_stats.end(); emit_call_stats_it++) { + float age = (Time() - emit_call_stats_it->second.get_last_call()).in_sec(); + if (age < max_age) { + graph << "\"" << emit_call_stats_it->first << "\" -> \"" + << (*sp_it)->get_identifier() + << "\"" << " [label=\"" + << " freq=" << emit_call_stats_it->second.get_call_frequency() << "Hz" + << " age=" << age << "s" + << "\"" << "];"; + } + } + + // WAIT CALLS + CircularBuffer<SyncPointCall> wait_calls = (*sp_it)->get_wait_calls(); + // generate call stats + std::map<const char *, SyncPointCallStats> wait_call_stats; + for (CircularBuffer<SyncPointCall>::iterator waitcalls_it = wait_calls.begin(); + waitcalls_it != wait_calls.end(); waitcalls_it++) { + wait_call_stats[waitcalls_it->get_caller()].update_calls(*waitcalls_it); + } + + for (std::map<const char *, SyncPointCallStats>::iterator wait_call_stats_it = wait_call_stats.begin(); + wait_call_stats_it != wait_call_stats.end(); wait_call_stats_it++) { + float age = (Time() - wait_call_stats_it->second.get_last_call()).in_sec(); + if (age < max_age) { + graph << "\"" << (*sp_it)->get_identifier() << "\"" << " -> " + << "\"" << wait_call_stats_it->first << "\"" << " [label=" << "\"" + << " avg=" << wait_call_stats_it->second.get_waittime_average() << "s" + << " age=" << age << "s" + //<< " max=" << max_wait_time << "s" + << "\"" << "];"; + } + } + } + graph << "}"; + return graph.str(); +} + } // namespace fawkes diff --git a/src/libs/syncpoint/syncpoint_manager.h b/src/libs/syncpoint/syncpoint_manager.h index 602d7a0..23f61ea 100644 --- a/src/libs/syncpoint/syncpoint_manager.h +++ b/src/libs/syncpoint/syncpoint_manager.h @@ -23,6 +23,7 @@ #define __SYNCPOINT_SYNCPOINT_MANAGER_H_ #include <set> +#include <string> #include <syncpoint/syncpoint.h> #include <core/utils/refptr.h> @@ -51,6 +52,8 @@ class SyncPointManager std::set<RefPtr<SyncPoint>, SyncPointSetLessThan > get_syncpoints(); + std::string all_syncpoints_as_dot(float max_age); + protected: /** * Set of all existing SyncPoints - *commit* fae64cec3380775baddf8c6877c2bb24efa7c39f - - - - - - - - - - Author: Till Hofmann <hofm...@kbsg.rwth-aachen.de> Date: Fri Aug 15 20:01:14 2014 +0200 Subject: webview: add SyncPoint visualization cfg/conf.d/webview.yaml | 5 ++- src/plugins/webview/Makefile | 12 ++++- .../{tf_processor.cpp => syncpoint_processor.cpp} | 55 ++++++++++--------- .../{tf_processor.h => syncpoint_processor.h} | 26 ++++----- src/plugins/webview/webview_thread.cpp | 14 +++++ src/plugins/webview/webview_thread.h | 6 ++ 6 files changed, 76 insertions(+), 42 deletions(-) _Diff for modified files_: diff --git a/cfg/conf.d/webview.yaml b/cfg/conf.d/webview.yaml index 9926e7c..2d0bccd 100644 --- a/cfg/conf.d/webview.yaml +++ b/cfg/conf.d/webview.yaml @@ -57,4 +57,7 @@ webview: jpeg-vflip: false # directories with static files - static-dirs: ["@BASEDIR@/res/webview"] \ No newline at end of file + static-dirs: ["@BASEDIR@/res/webview"] + + syncpoints: + max_age: 3.0 diff --git a/src/plugins/webview/Makefile b/src/plugins/webview/Makefile index 64d4699..851a4b3 100644 --- a/src/plugins/webview/Makefile +++ b/src/plugins/webview/Makefile @@ -91,6 +91,16 @@ ifeq ($(HAVE_LIBMICROHTTPD),1) LIBS_webview += crypt WARN_TARGETS += warning_apr_util endif + + ifeq ($(HAVE_GRAPHVIZ),1) + OBJS_webview += syncpoint_processor.o + LIBS_webview += fawkessyncpoint + CFLAGS += $(CFLAGS_GRAPHVIZ) + LDFLAGS += $(LDFLAGS_GRAPHVIZ) + else + WARN_TARGETS += warning_graphviz + endif + else WARN_TARGETS += warning_libmicrohttpd endif @@ -107,7 +117,7 @@ warning_libmicrohttpd: warning_tf: $(SILENT)echo -e "$(INDENT_PRINT)--> $(TRED)Omitting transforms support$(TNORMAL) (TF not available)" warning_graphviz: - $(SILENT)echo -e "$(INDENT_PRINT)--> $(TRED)Omitting transforms support$(TNORMAL) (graphviz not found)" + $(SILENT)echo -e "$(INDENT_PRINT)--> $(TRED)Omitting transforms and syncpoint support$(TNORMAL) (graphviz not found)" warning_jpeg: $(SILENT)echo -e "$(INDENT_PRINT)--> $(TRED)Omitting image viewing support$(TNORMAL) (JPEG not available)" warning_cpp11: diff --git a/src/plugins/webview/webview_thread.cpp b/src/plugins/webview/webview_thread.cpp index ddeea3c..26d01cc 100644 --- a/src/plugins/webview/webview_thread.cpp +++ b/src/plugins/webview/webview_thread.cpp @@ -24,6 +24,7 @@ #include "blackboard_processor.h" #include "startpage_processor.h" #include "plugins_processor.h" +#include "syncpoint_processor.h" #ifdef HAVE_TF # include "tf_processor.h" #endif @@ -61,6 +62,8 @@ const char *WebviewThread::PLUGINS_URL_PREFIX = "/plugins"; const char *WebviewThread::TF_URL_PREFIX = "/tf"; /** Prefix for the WebMJPEGRequestProcessor. */ const char *WebviewThread::IMAGE_URL_PREFIX = "/images"; +/** Prefix for the SyncPointRequestProcessor. */ +const char *WebviewThread::SYNCPOINT_URL_PREFIX = "/syncpoints"; /** @class WebviewThread "webview_thread.h" * Webview Thread. @@ -148,6 +151,11 @@ WebviewThread::init() __cfg_access_log = config->get_string("/webview/access_log"); } catch (Exception &e) {} + __cfg_syncpoint_max_age = 20.f; + try { + __cfg_syncpoint_max_age = config->get_float("/webview/syncpoints/max_age"); + } catch (Exception &e) {} + __cache_logger.clear(); @@ -206,6 +214,7 @@ WebviewThread::init() __static_processor = new WebviewStaticRequestProcessor(STATIC_URL_PREFIX, static_dirs_cstr, logger); __blackboard_processor = new WebviewBlackBoardRequestProcessor(BLACKBOARD_URL_PREFIX, blackboard); __plugins_processor = new WebviewPluginsRequestProcessor(PLUGINS_URL_PREFIX, plugin_manager); + __syncpoint_processor = new WebviewSyncPointRequestProcessor(SYNCPOINT_URL_PREFIX, syncpoint_manager, __cfg_syncpoint_max_age); #ifdef HAVE_TF __tf_processor = new WebviewTfRequestProcessor(TF_URL_PREFIX, tf_listener); #endif @@ -217,6 +226,7 @@ WebviewThread::init() webview_url_manager->register_baseurl(STATIC_URL_PREFIX, __static_processor); webview_url_manager->register_baseurl(BLACKBOARD_URL_PREFIX, __blackboard_processor); webview_url_manager->register_baseurl(PLUGINS_URL_PREFIX, __plugins_processor); + webview_url_manager->register_baseurl(SYNCPOINT_URL_PREFIX, __syncpoint_processor); #ifdef HAVE_TF webview_url_manager->register_baseurl(TF_URL_PREFIX, __tf_processor); #endif @@ -229,6 +239,7 @@ WebviewThread::init() webview_nav_manager->add_nav_entry(TF_URL_PREFIX, "TF"); #endif webview_nav_manager->add_nav_entry(PLUGINS_URL_PREFIX, "Plugins"); + webview_nav_manager->add_nav_entry(SYNCPOINT_URL_PREFIX, "SyncPoints"); #ifdef HAVE_JPEG webview_nav_manager->add_nav_entry(IMAGE_URL_PREFIX, "Images"); #endif @@ -256,6 +267,7 @@ WebviewThread::finalize() webview_url_manager->unregister_baseurl(BLACKBOARD_URL_PREFIX); webview_url_manager->unregister_baseurl(PLUGINS_URL_PREFIX); webview_url_manager->unregister_baseurl(IMAGE_URL_PREFIX); + webview_url_manager->unregister_baseurl(SYNCPOINT_URL_PREFIX); #ifdef HAVE_TF webview_url_manager->unregister_baseurl(TF_URL_PREFIX); @@ -263,6 +275,7 @@ WebviewThread::finalize() webview_nav_manager->remove_nav_entry(BLACKBOARD_URL_PREFIX); webview_nav_manager->remove_nav_entry(PLUGINS_URL_PREFIX); + webview_nav_manager->remove_nav_entry(SYNCPOINT_URL_PREFIX); #ifdef HAVE_TF webview_nav_manager->remove_nav_entry(TF_URL_PREFIX); #endif @@ -277,6 +290,7 @@ WebviewThread::finalize() delete __blackboard_processor; delete __startpage_processor; delete __plugins_processor; + delete __syncpoint_processor; #ifdef HAVE_TF delete __tf_processor; #endif diff --git a/src/plugins/webview/webview_thread.h b/src/plugins/webview/webview_thread.h index 531105b..3b2b451 100644 --- a/src/plugins/webview/webview_thread.h +++ b/src/plugins/webview/webview_thread.h @@ -36,6 +36,7 @@ #ifdef HAVE_TF # include <aspect/tf.h> #endif +#include <aspect/syncpoint_manager.h> #include <logging/cache.h> @@ -59,6 +60,7 @@ class WebviewTfRequestProcessor; #ifdef HAVE_JPEG class WebviewImageRequestProcessor; #endif +class WebviewSyncPointRequestProcessor; class WebviewThread : public fawkes::Thread, @@ -74,6 +76,7 @@ class WebviewThread #ifdef HAVE_TF public fawkes::TransformAspect, #endif + public fawkes::SyncPointManagerAspect, public fawkes::WebviewAspect { public: @@ -89,6 +92,7 @@ class WebviewThread static const char *PLUGINS_URL_PREFIX; static const char *TF_URL_PREFIX; static const char *IMAGE_URL_PREFIX; + static const char *SYNCPOINT_URL_PREFIX; private: void ssl_create(const char *ssl_key_file, const char *ssl_cert_file); @@ -115,6 +119,7 @@ class WebviewThread WebviewHeaderGenerator *__header_gen; WebviewFooterGenerator *__footer_gen; WebviewUserVerifier *__user_verifier; + WebviewSyncPointRequestProcessor *__syncpoint_processor; unsigned int __cfg_port; bool __cfg_use_ssl; @@ -124,6 +129,7 @@ class WebviewThread bool __cfg_use_basic_auth; std::string __cfg_basic_auth_realm; std::string __cfg_access_log; + float __cfg_syncpoint_max_age; fawkes::CacheLogger __cache_logger; fawkes::NetworkService *__webview_service; -- Fawkes Robotics Framework http://www.fawkesrobotics.org _______________________________________________ fawkes-commits mailing list fawkes-commits@lists.kbsg.rwth-aachen.de https://lists.kbsg.rwth-aachen.de/listinfo/fawkes-commits