diff options
Diffstat (limited to '')
-rw-r--r-- | src/debug/CMakeLists.txt | 29 | ||||
-rw-r--r-- | src/debug/demangle.cpp | 60 | ||||
-rw-r--r-- | src/debug/demangle.h | 39 | ||||
-rw-r--r-- | src/debug/event-tracker.h | 236 | ||||
-rw-r--r-- | src/debug/event.h | 81 | ||||
-rw-r--r-- | src/debug/gc-heap.h | 53 | ||||
-rw-r--r-- | src/debug/gdk-event-latency-tracker.cpp | 81 | ||||
-rw-r--r-- | src/debug/gdk-event-latency-tracker.h | 57 | ||||
-rw-r--r-- | src/debug/heap.cpp | 62 | ||||
-rw-r--r-- | src/debug/heap.h | 63 | ||||
-rw-r--r-- | src/debug/log-display-config.cpp | 79 | ||||
-rw-r--r-- | src/debug/log-display-config.h | 36 | ||||
-rw-r--r-- | src/debug/logger.cpp | 231 | ||||
-rw-r--r-- | src/debug/logger.h | 247 | ||||
-rw-r--r-- | src/debug/simple-event.h | 87 | ||||
-rw-r--r-- | src/debug/sysv-heap.cpp | 84 | ||||
-rw-r--r-- | src/debug/sysv-heap.h | 48 | ||||
-rw-r--r-- | src/debug/timestamp.cpp | 46 | ||||
-rw-r--r-- | src/debug/timestamp.h | 39 |
19 files changed, 1658 insertions, 0 deletions
diff --git a/src/debug/CMakeLists.txt b/src/debug/CMakeLists.txt new file mode 100644 index 0000000..954df1f --- /dev/null +++ b/src/debug/CMakeLists.txt @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +set(debug_SRC + demangle.cpp + heap.cpp + log-display-config.cpp + logger.cpp + sysv-heap.cpp + timestamp.cpp + gdk-event-latency-tracker.cpp + + + # ------ + # Header + demangle.h + event-tracker.h + event.h + gc-heap.h + gdk-event-latency-tracker.h + heap.h + log-display-config.h + logger.h + simple-event.h + sysv-heap.h + timestamp.h +) + +# add_inkscape_lib(debug_LIB "${debug_SRC}") +add_inkscape_source("${debug_SRC}") diff --git a/src/debug/demangle.cpp b/src/debug/demangle.cpp new file mode 100644 index 0000000..abf046b --- /dev/null +++ b/src/debug/demangle.cpp @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Debug::demangle - demangle C++ symbol names + * + * Authors: + * MenTaLguY <mental@rydia.net> + * + * Copyright (C) 2006 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include <boost/core/demangle.hpp> +#include <cstring> +#include <map> +#include <memory> +#include <string> +#include "debug/demangle.h" + +namespace Inkscape { + +namespace Debug { + +namespace { + +struct string_less_than { + bool operator()(char const *a, char const *b) const { + return ( strcmp(a, b) < 0 ); + } +}; + +typedef std::map<char const *, std::shared_ptr<std::string>, string_less_than> MangleCache; +MangleCache mangle_cache; + +} + +std::shared_ptr<std::string> demangle(char const *name) { + MangleCache::iterator found=mangle_cache.find(name); + if ( found != mangle_cache.end() ) { + return (*found).second; + } + + std::string result = boost::core::demangle(name); + return mangle_cache[name] = std::make_shared<std::string>(result); +} + +} + +} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/debug/demangle.h b/src/debug/demangle.h new file mode 100644 index 0000000..ba747cd --- /dev/null +++ b/src/debug/demangle.h @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Debug::demangle - demangle C++ symbol names + * + * Authors: + * MenTaLguY <mental@rydia.net> + * + * Copyright (C) 2006 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#ifndef SEEN_INKSCAPE_DEBUG_DEMANGLE_H +#define SEEN_INKSCAPE_DEBUG_DEMANGLE_H + +#include <memory> +#include <string> + +namespace Inkscape { + +namespace Debug { + +std::shared_ptr<std::string> demangle(char const *name); + +} + +} + +#endif +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/debug/event-tracker.h b/src/debug/event-tracker.h new file mode 100644 index 0000000..a728bac --- /dev/null +++ b/src/debug/event-tracker.h @@ -0,0 +1,236 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Debug::EventTracker - semi-automatically track event lifetimes + * + * Authors: + * MenTaLguY <mental@rydia.net> + * + * Copyright (C) 2005 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#ifndef SEEN_INKSCAPE_DEBUG_EVENT_TRACKER_H +#define SEEN_INKSCAPE_DEBUG_EVENT_TRACKER_H + +#include "debug/logger.h" + +namespace Inkscape { + +namespace Debug { + +#ifdef NDEBUG +// Make event tracking a no-op for non-debug builds +template <typename = void> struct EventTracker { + template <typename... Args> EventTracker(Args &&...) {} + template <typename, typename... Args> void set(Args &&...) {} + void clear() {} +}; +#else + +struct NoInitialEvent {}; + +template <typename Event=NoInitialEvent> class EventTracker; + +class EventTrackerBase { +public: + virtual ~EventTrackerBase() { + if (_active) { + Logger::finish(); + } + } + + template <typename EventType> + inline void set() { + if (_active) { + Logger::finish(); + } + Logger::start<EventType>(); + _active = true; + } + + template <typename EventType, typename A> + inline void set(A const &a) { + if (_active) { + Logger::finish(); + } + Logger::start<EventType>(a); + _active = true; + } + + template <typename EventType, typename A, typename B> + inline void set(A const &a, B const &b) { + if (_active) { + Logger::finish(); + } + Logger::start<EventType>(a, b); + _active = true; + } + + template <typename EventType, typename A, typename B, typename C> + inline void set(A const &a, B const &b, C const &c) { + if (_active) { + Logger::finish(); + } + Logger::start<EventType>(a, b, c); + _active = true; + } + + template <typename EventType, typename A, typename B, + typename C, typename D> + inline void set(A const &a, B const &b, C const &c, D const &d) { + if (_active) { + Logger::finish(); + } + Logger::start<EventType>(a, b, c, d); + _active = true; + } + + template <typename EventType, typename A, typename B, typename C, + typename D, typename E> + inline void set(A const &a, B const &b, C const &c, D const &d, E const &e) + { + if (_active) { + Logger::finish(); + } + Logger::start<EventType>(a, b, c, d, e); + _active = true; + } + + template <typename EventType, typename A, typename B, typename C, + typename D, typename E, typename F> + inline void set(A const &a, B const &b, C const &c, + D const &d, E const &e, F const &f) + { + if (_active) { + Logger::finish(); + } + Logger::start<EventType>(a, b, c, d, e, f); + _active = true; + } + + template <typename EventType, typename A, typename B, typename C, + typename D, typename E, typename F, + typename G> + inline void set(A const &a, B const &b, C const &c, D const &d, + E const &e, F const &f, G const &g) + { + if (_active) { + Logger::finish(); + } + Logger::start<EventType>(a, b, c, d, e, f, g); + _active = true; + } + + template <typename EventType, typename A, typename B, typename C, + typename D, typename E, typename F, + typename G, typename H> + inline void set(A const &a, B const &b, C const &c, D const &d, + E const &e, F const &f, G const &g, H const &h) + { + if (_active) { + Logger::finish(); + } + Logger::start<EventType>(a, b, c, d, e, f, g, h); + _active = true; + } + + void clear() { + if (_active) { + Logger::finish(); + _active = false; + } + } + +protected: + EventTrackerBase(bool active) : _active(active) {} + +private: + EventTrackerBase(EventTrackerBase const &) = delete; // no copy + void operator=(EventTrackerBase const &) = delete; // no assign + bool _active; +}; + +template <typename EventType> class EventTracker : public EventTrackerBase { +public: + EventTracker() : EventTrackerBase(true) { Logger::start<EventType>(); } + + template <typename A> + EventTracker(A const &a) : EventTrackerBase(true) { + Logger::start<EventType>(a); + } + + template <typename A, typename B> + EventTracker(A const &a, B const &b) : EventTrackerBase(true) { + Logger::start<EventType>(a, b); + } + + template <typename A, typename B, typename C> + EventTracker(A const &a, B const &b, C const &c) : EventTrackerBase(true) { + Logger::start<EventType>(a, b, c); + } + + template <typename A, typename B, typename C, typename D> + EventTracker(A const &a, B const &b, C const &c, D const &d) + : EventTrackerBase(true) + { + Logger::start<EventType>(a, b, c, d); + } + + template <typename A, typename B, typename C, typename D, typename E> + EventTracker(A const &a, B const &b, C const &c, D const &d, E const &e) + : EventTrackerBase(true) + { + Logger::start<EventType>(a, b, c, d, e); + } + + template <typename A, typename B, typename C, typename D, + typename E, typename F> + EventTracker(A const &a, B const &b, C const &c, D const &d, + E const &e, F const &f) + : EventTrackerBase(true) + { + Logger::start<EventType>(a, b, c, d, e, f); + } + + template <typename A, typename B, typename C, typename D, + typename E, typename F, typename G> + EventTracker(A const &a, B const &b, C const &c, D const &d, + E const &e, F const &f, G const &g) + : EventTrackerBase(true) + { + Logger::start<EventType>(a, b, c, d, e, f, g); + } + + template <typename A, typename B, typename C, typename D, + typename E, typename F, typename G, typename H> + EventTracker(A const &a, B const &b, C const &c, D const &d, + E const &e, F const &f, G const &g, H const &h) + : EventTrackerBase(true) + { + Logger::start<EventType>(a, b, c, d, e, f, g, h); + } +}; + +template <> class EventTracker<NoInitialEvent> : public EventTrackerBase { +public: + EventTracker() : EventTrackerBase(false) {} +}; + +#endif + +} + +} + +#endif +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/debug/event.h b/src/debug/event.h new file mode 100644 index 0000000..3bc6089 --- /dev/null +++ b/src/debug/event.h @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Debug::Event - event for debug tracing + * + * Authors: + * MenTaLguY <mental@rydia.net> + * + * Copyright (C) 2005 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#ifndef SEEN_INKSCAPE_DEBUG_EVENT_H +#define SEEN_INKSCAPE_DEBUG_EVENT_H + +#include <memory> +#include <string> +#include <utility> + +namespace Inkscape { + +namespace Debug { + +class Event { +public: + virtual ~Event() = default; + + enum Category { + CORE=0, + XML, + SPOBJECT, + DOCUMENT, + REFCOUNT, + EXTENSION, + FINALIZERS, + INTERACTION, + CONFIGURATION, + OTHER + }; + enum { N_CATEGORIES=OTHER+1 }; + + struct PropertyPair { + public: + PropertyPair() = default; + PropertyPair(char const *n, std::shared_ptr<std::string>&& v) + : name(n), value(std::move(v)) {} + PropertyPair(char const *n, char const *v) + : name(n), + value(std::make_shared<std::string>(v)) {} + + char const *name; + std::shared_ptr<std::string> value; + }; + + static Category category() { return OTHER; } + + // To reduce allocations, we assume the name here is always allocated statically and will never + // need to be deallocated. It would be nice to be able to assert that during the creation of + // the Event though. + virtual char const *name() const=0; + virtual unsigned propertyCount() const=0; + virtual PropertyPair property(unsigned property) const=0; + + virtual void generateChildEvents() const=0; +}; + +} + +} + +#endif +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/debug/gc-heap.h b/src/debug/gc-heap.h new file mode 100644 index 0000000..e0fd8f1 --- /dev/null +++ b/src/debug/gc-heap.h @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Debug::GCHeap - heap statistics for libgc heap + * + * Authors: + * MenTaLguY <mental@rydia.net> + * + * Copyright (C) 2004 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#ifndef SEEN_INKSCAPE_DEBUG_GC_HEAP_H +#define SEEN_INKSCAPE_DEBUG_GC_HEAP_H + +#include "inkgc/gc-core.h" +#include "debug/heap.h" + +namespace Inkscape { +namespace Debug { + +class GCHeap : public Debug::Heap { +public: + int features() const override { + return SIZE_AVAILABLE | USED_AVAILABLE | GARBAGE_COLLECTED; + } + char const *name() const override { + return "libgc"; + } + Heap::Stats stats() const override { + Stats stats; + stats.size = GC::Core::get_heap_size(); + stats.bytes_used = stats.size - GC::Core::get_free_bytes(); + return stats; + } + void force_collect() override { GC::Core::gcollect(); } +}; + +} +} + +#endif + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/debug/gdk-event-latency-tracker.cpp b/src/debug/gdk-event-latency-tracker.cpp new file mode 100644 index 0000000..db93912 --- /dev/null +++ b/src/debug/gdk-event-latency-tracker.cpp @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Debug::GdkEventLatencyTracker - tracks backlog of GDK events + * + * Authors: + * MenTaLguY <mental@rydia.net> + * + * Copyright (C) 2008 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include <gdk/gdk.h> + +#include "debug/gdk-event-latency-tracker.h" +#include "preferences.h" + +namespace Inkscape { +namespace Debug { + +GdkEventLatencyTracker::GdkEventLatencyTracker() + : start_seconds(0.0), max_latency(0.0), skew(1.0), last_elapsed(0.0), last_seconds(0.0) +{ + elapsed.stop(); + elapsed.reset(); +} + +std::optional<double> GdkEventLatencyTracker::process(GdkEvent const *event) { + guint32 const timestamp=gdk_event_get_time(const_cast<GdkEvent *>(event)); + if (timestamp == GDK_CURRENT_TIME) { + return std::optional<double>(); + } + double const timestamp_seconds = timestamp / 1000.0; + + if (start_seconds == 0.0) { + elapsed.start(); + start_seconds = timestamp_seconds; + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + skew = prefs->getDoubleLimited("/debug/latency/skew", 1.0, 0.5, 2.0); + return std::optional<double>(0.0); + } else { + last_elapsed = elapsed.elapsed(); + last_seconds = timestamp_seconds; + double const current_seconds = (last_elapsed * skew) + start_seconds; + double delta = current_seconds - timestamp_seconds; + if (delta < 0.0) { + start_seconds += -delta; + delta = 0.0; + } else if (delta > max_latency) { + max_latency = delta; + } + return std::optional<double>(delta); + } +} + +double GdkEventLatencyTracker::getSkew() { + double val = 0.0; + if ((last_elapsed > 0.0) && (last_seconds > 0.0)) { + val = (last_seconds - start_seconds) / last_elapsed; + } + return val; +} + +GdkEventLatencyTracker &GdkEventLatencyTracker::default_tracker() { + static GdkEventLatencyTracker tracker; + return tracker; +} + +} +} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/debug/gdk-event-latency-tracker.h b/src/debug/gdk-event-latency-tracker.h new file mode 100644 index 0000000..569e53a --- /dev/null +++ b/src/debug/gdk-event-latency-tracker.h @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Debug::GdkEventLatencyTracker - tracks backlog of GDK events + * + * Authors: + * MenTaLguY <mental@rydia.net> + * + * Copyright (C) 2008 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#ifndef SEEN_INKSCAPE_DEBUG_GDK_EVENT_LATENCY_TRACKER_H +#define SEEN_INKSCAPE_DEBUG_GDK_EVENT_LATENCY_TRACKER_H + +typedef union _GdkEvent GdkEvent; +#include <glibmm/timer.h> +#include <optional> + +namespace Inkscape { +namespace Debug { + +class GdkEventLatencyTracker { +public: + GdkEventLatencyTracker(); + std::optional<double> process(GdkEvent const *e); + double maxLatency() const { return max_latency; } + double getSkew(); + + static GdkEventLatencyTracker &default_tracker(); + +private: + GdkEventLatencyTracker(GdkEventLatencyTracker const &) = delete; // no copy + void operator=(GdkEventLatencyTracker const &) = delete; // no assign + + double start_seconds; + double max_latency; + double skew; + double last_elapsed; + double last_seconds; + Glib::Timer elapsed; +}; + +} +} + +#endif +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/debug/heap.cpp b/src/debug/heap.cpp new file mode 100644 index 0000000..ce9cacf --- /dev/null +++ b/src/debug/heap.cpp @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Debug::Heap - interface for gathering heap statistics + * + * Authors: + * MenTaLguY <mental@rydia.net> + * + * Copyright (C) 2005 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include "inkgc/gc-alloc.h" +#include "debug/gc-heap.h" +#include "debug/sysv-heap.h" +#include <vector> + +namespace Inkscape { +namespace Debug { + +namespace { + +typedef std::vector<Heap *, GC::Alloc<Heap *, GC::MANUAL> > HeapCollection; + +HeapCollection &heaps() { + static bool is_initialized=false; + static HeapCollection heaps; + if (!is_initialized) { + heaps.push_back(new SysVHeap()); + heaps.push_back(new GCHeap()); + is_initialized = true; + } + return heaps; +} + +} + +unsigned heap_count() { + return heaps().size(); +} + +Heap *get_heap(unsigned i) { + return heaps()[i]; +} + +void register_extra_heap(Heap &heap) { + heaps().push_back(&heap); +} + +} +} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/debug/heap.h b/src/debug/heap.h new file mode 100644 index 0000000..81e7b73 --- /dev/null +++ b/src/debug/heap.h @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Debug::Heap - interface for gathering heap statistics + * + * Authors: + * MenTaLguY <mental@rydia.net> + * + * Copyright (C) 2005 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#ifndef SEEN_INKSCAPE_DEBUG_HEAP_H +#define SEEN_INKSCAPE_DEBUG_HEAP_H + +#include <cstddef> + +namespace Inkscape { + +namespace Debug { + +class Heap { +public: + virtual ~Heap() = default; + + struct Stats { + std::size_t size; + std::size_t bytes_used; + }; + + enum { + SIZE_AVAILABLE = ( 1 << 0 ), + USED_AVAILABLE = ( 1 << 1 ), + GARBAGE_COLLECTED = ( 1 << 2 ) + }; + + virtual int features() const=0; + + virtual char const *name() const=0; + virtual Stats stats() const=0; + virtual void force_collect()=0; +}; + +unsigned heap_count(); +Heap *get_heap(unsigned i); + +void register_extra_heap(Heap &heap); + +} + +} + +#endif +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/debug/log-display-config.cpp b/src/debug/log-display-config.cpp new file mode 100644 index 0000000..7de69be --- /dev/null +++ b/src/debug/log-display-config.cpp @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Debug::log_display_config - log display configuration + * + * Authors: + * MenTaLguY <mental@rydia.net> + * + * Copyright (C) 2007 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include <iostream> +#include <gtk/gtk.h> +#include <gdk/gdk.h> +#include "debug/event-tracker.h" +#include "debug/logger.h" +#include "debug/simple-event.h" +#include "debug/log-display-config.h" + +namespace Inkscape { + +namespace Debug { + +namespace { + +typedef SimpleEvent<Event::CONFIGURATION> ConfigurationEvent; + +class Monitor : public ConfigurationEvent { +public: + Monitor(GdkMonitor *monitor) + : ConfigurationEvent("monitor") + { + GdkRectangle area; + gdk_monitor_get_geometry(monitor, &area); + + _addProperty("x", area.x); + _addProperty("y", area.y); + _addProperty("width", area.width); + _addProperty("height", area.height); + } +}; + +class Display : public ConfigurationEvent { +public: + Display() : ConfigurationEvent("display") {} + void generateChildEvents() const override { + GdkDisplay *display=gdk_display_get_default(); + + gint const n_monitors = gdk_display_get_n_monitors(display); + + // Loop through all monitors and log their details + for (gint i_monitor = 0; i_monitor < n_monitors; ++i_monitor) { + GdkMonitor *monitor = gdk_display_get_monitor(display, i_monitor); + Logger::write<Monitor>(monitor); + } + } +}; + +} + +void log_display_config() { + Logger::write<Display>(); +} + +} + +} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/debug/log-display-config.h b/src/debug/log-display-config.h new file mode 100644 index 0000000..df9be18 --- /dev/null +++ b/src/debug/log-display-config.h @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Debug::log_display_config - log display configuration + * + * Authors: + * MenTaLguY <mental@rydia.net> + * + * Copyright (C) 2007 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#ifndef SEEN_INKSCAPE_DEBUG_LOG_DISPLAY_CONFIG_H +#define SEEN_INKSCAPE_DEBUG_LOG_DISPLAY_CONFIG_H + +namespace Inkscape { + +namespace Debug { + +void log_display_config(); + +} + +} + +#endif +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/debug/logger.cpp b/src/debug/logger.cpp new file mode 100644 index 0000000..37b8221 --- /dev/null +++ b/src/debug/logger.cpp @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Debug::Logger - debug logging facility + * + * Authors: + * MenTaLguY <mental@rydia.net> + * + * Copyright (C) 2005 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include <cstring> +#include <fstream> +#include <memory> +#include <string> +#include <vector> +#include <glib.h> +#include "inkscape-version.h" +#include "debug/logger.h" +#include "debug/simple-event.h" + +namespace Inkscape { + +namespace Debug { + +bool Logger::_enabled=false; +bool Logger::_category_mask[Event::N_CATEGORIES]; + +namespace { + +static void write_escaped_value(std::ostream &os, char const *value) { + for ( char const *current=value ; *current ; ++current ) { + switch (*current) { + case '&': + os << "&"; + break; + case '"': + os << """; + break; + case '\'': + os << "'"; + break; + case '<': + os << "<"; + break; + case '>': + os << ">"; + break; + default: + os.put(*current); + } + } +} + +static void write_indent(std::ostream &os, unsigned depth) { + for ( unsigned i = 0 ; i < depth ; i++ ) { + os.write(" ", 2); + } +} + +static std::ofstream log_stream; +static bool empty_tag=false; +typedef std::vector<std::shared_ptr<std::string>> TagStack; +static TagStack &tag_stack() { + static TagStack stack; + return stack; +} + +static void do_shutdown() { + Debug::Logger::shutdown(); +} + +static bool equal_range(char const *c_string, + char const *start, char const *end) +{ + return !std::strncmp(start, c_string, end - start) && + !c_string[end - start]; +} + +static void set_category_mask(bool * const mask, char const *filter) { + if (!filter) { + for ( unsigned i = 0 ; i < Event::N_CATEGORIES ; i++ ) { + mask[i] = true; + } + return; + } else { + for ( unsigned i = 0 ; i < Event::N_CATEGORIES ; i++ ) { + mask[i] = false; + } + mask[Event::CORE] = true; + } + + char const *start; + char const *end; + start = end = filter; + while (*end) { + while ( *end && *end != ',' ) { end++; } + if ( start != end ) { + struct CategoryName { + char const *name; + Event::Category category; + }; + static const CategoryName category_names[] = { + { "CORE", Event::CORE }, + { "XML", Event::XML }, + { "SPOBJECT", Event::SPOBJECT }, + { "DOCUMENT", Event::DOCUMENT }, + { "REFCOUNT", Event::REFCOUNT }, + { "EXTENSION", Event::EXTENSION }, + { "FINALIZERS", Event::FINALIZERS }, + { "INTERACTION", Event::INTERACTION }, + { "CONFIGURATION", Event::CONFIGURATION }, + { "OTHER", Event::OTHER }, + { nullptr, Event::OTHER } + }; + CategoryName const *iter; + for ( iter = category_names ; iter->name ; iter++ ) { + if (equal_range(iter->name, start, end)) { + mask[iter->category] = true; + break; + } + } + if (!iter->name) { + g_warning("Unknown debugging category %*s", (int)(end - start), start); + } + } + if (*end) { + start = end = end + 1; + } + } +} + +typedef SimpleEvent<Event::CORE> CoreEvent; + +class SessionEvent : public CoreEvent { +public: + SessionEvent() : CoreEvent("session") { + _addProperty("inkscape-version", Inkscape::version_string); + } +}; + +} + +void Logger::init() { + if (!_enabled) { + char const *log_filename=std::getenv("INKSCAPE_DEBUG_LOG"); + if (log_filename) { + log_stream.open(log_filename); + if (log_stream.is_open()) { + char const *log_filter=std::getenv("INKSCAPE_DEBUG_FILTER"); + set_category_mask(_category_mask, log_filter); + log_stream << "<?xml version=\"1.0\"?>\n"; + log_stream.flush(); + _enabled = true; + start<SessionEvent>(); + std::atexit(&do_shutdown); + } + } + } +} + +void Logger::_start(Event const &event) { + char const *name=event.name(); + + if (empty_tag) { + log_stream << ">\n"; + } + + write_indent(log_stream, tag_stack().size()); + + log_stream << "<" << name; + + unsigned property_count=event.propertyCount(); + for ( unsigned i = 0 ; i < property_count ; i++ ) { + Event::PropertyPair property=event.property(i); + log_stream << " " << property.name << "=\""; + write_escaped_value(log_stream, property.value->c_str()); + log_stream << "\""; + } + + log_stream.flush(); + + tag_stack().push_back(std::make_shared<std::string>(name)); + empty_tag = true; + + event.generateChildEvents(); +} + +void Logger::_skip() { + tag_stack().push_back(nullptr); +} + +void Logger::_finish() { + if (tag_stack().back()) { + if (empty_tag) { + log_stream << "/>\n"; + } else { + write_indent(log_stream, tag_stack().size() - 1); + log_stream << "</" << tag_stack().back()->c_str() << ">\n"; + } + log_stream.flush(); + + empty_tag = false; + } + + tag_stack().pop_back(); +} + +void Logger::shutdown() { + if (_enabled) { + while (!tag_stack().empty()) { + finish(); + } + } +} + +} + +} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/debug/logger.h b/src/debug/logger.h new file mode 100644 index 0000000..ab6c826 --- /dev/null +++ b/src/debug/logger.h @@ -0,0 +1,247 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Debug::Logger - debug logging facility + * + * Authors: + * MenTaLguY <mental@rydia.net> + * + * Copyright (C) 2005 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#ifndef SEEN_INKSCAPE_DEBUG_LOGGER_H +#define SEEN_INKSCAPE_DEBUG_LOGGER_H + +#include "debug/event.h" + +namespace Inkscape { + +namespace Debug { + +class Logger { +public: + static void init(); + + template <typename EventType> + inline static void start() { + if (_enabled) { + if (_category_mask[EventType::category()]) { + _start(EventType()); + } else { + _skip(); + } + } + } + + template <typename EventType, typename A> + inline static void start(A const &a) { + if (_enabled) { + if (_category_mask[EventType::category()]) { + _start(EventType(a)); + } else { + _skip(); + } + } + } + + template <typename EventType, typename A, typename B> + inline static void start(A const &a, B const &b) { + if (_enabled) { + if (_category_mask[EventType::category()]) { + _start(EventType(a, b)); + } else { + _skip(); + } + } + } + + template <typename EventType, typename A, typename B, typename C> + inline static void start(A const &a, B const &b, C const &c) { + if (_enabled) { + if (_category_mask[EventType::category()]) { + _start(EventType(a, b, c)); + } else { + _skip(); + } + } + } + + template <typename EventType, typename A, typename B, + typename C, typename D> + inline static void start(A const &a, B const &b, C const &c, D const &d) { + if (_enabled) { + if (_category_mask[EventType::category()]) { + _start(EventType(a, b, c, d)); + } else { + _skip(); + } + } + } + + template <typename EventType, typename A, typename B, typename C, + typename D, typename E> + inline static void start(A const &a, B const &b, C const &c, + D const &d, E const &e) + { + if (_enabled) { + if (_category_mask[EventType::category()]) { + _start(EventType(a, b, c, d, e)); + } else { + _skip(); + } + } + } + + template <typename EventType, typename A, typename B, typename C, + typename D, typename E, typename F> + inline static void start(A const &a, B const &b, C const &c, + D const &d, E const &e, F const &f) + { + if (_enabled) { + if (_category_mask[EventType::category()]) { + _start(EventType(a, b, c, d, e, f)); + } else { + _skip(); + } + } + } + + template <typename EventType, typename A, typename B, typename C, + typename D, typename E, typename F, + typename G> + inline static void start(A const &a, B const &b, C const &c, D const &d, + E const &e, F const &f, G const &g) + { + if (_enabled) { + if (_category_mask[EventType::category()]) { + _start(EventType(a, b, c, d, e, f, g)); + } else { + _skip(); + } + } + } + + template <typename EventType, typename A, typename B, typename C, + typename D, typename E, typename F, + typename G, typename H> + inline static void start(A const &a, B const &b, C const &c, D const &d, + E const &e, F const &f, G const &g, H const &h) + { + if (_enabled) { + if (_category_mask[EventType::category()]) { + _start(EventType(a, b, c, d, e, f, g, h)); + } else { + _skip(); + } + } + } + + inline static void finish() { + if (_enabled) { + _finish(); + } + } + + template <typename EventType> + inline static void write() { + start<EventType>(); + finish(); + } + + template <typename EventType, typename A> + inline static void write(A const &a) { + start<EventType, A>(a); + finish(); + } + + template <typename EventType, typename A, typename B> + inline static void write(A const &a, B const &b) { + start<EventType, A, B>(a, b); + finish(); + } + + template <typename EventType, typename A, typename B, typename C> + inline static void write(A const &a, B const &b, C const &c) { + start<EventType, A, B, C>(a, b, c); + finish(); + } + + template <typename EventType, typename A, typename B, + typename C, typename D> + inline static void write(A const &a, B const &b, C const &c, D const &d) { + start<EventType, A, B, C, D>(a, b, c, d); + finish(); + } + + template <typename EventType, typename A, typename B, + typename C, typename D, + typename E> + inline static void write(A const &a, B const &b, C const &c, + D const &d, E const &e) + { + start<EventType, A, B, C, D, E>(a, b, c, d, e); + finish(); + } + + template <typename EventType, typename A, typename B, + typename C, typename D, + typename E, typename F> + inline static void write(A const &a, B const &b, C const &c, + D const &d, E const &e, F const &f) + { + start<EventType, A, B, C, D, E, F>(a, b, c, d, e, f); + finish(); + } + + template <typename EventType, typename A, typename B, + typename C, typename D, + typename E, typename F, + typename G> + inline static void write(A const &a, B const &b, C const &c, + D const &d, E const &e, F const &f, + G const &g) + { + start<EventType, A, B, C, D, E, F, G>(a, b, c, d, e, f, g); + finish(); + } + + template <typename EventType, typename A, typename B, + typename C, typename D, + typename E, typename F, + typename G, typename H> + inline static void write(A const &a, B const &b, C const &c, + D const &d, E const &e, F const &f, + G const &g, H const &h) + { + start<EventType, A, B, C, D, E, F, G, H>(a, b, c, d, e, f, g, h); + finish(); + } + + static void shutdown(); + +private: + static bool _enabled; + + static void _start(Event const &event); + static void _skip(); + static void _finish(); + + static bool _category_mask[Event::N_CATEGORIES]; +}; + +} + +} + +#endif +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/debug/simple-event.h b/src/debug/simple-event.h new file mode 100644 index 0000000..58719b7 --- /dev/null +++ b/src/debug/simple-event.h @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Debug::SimpleEvent - trivial implementation of Debug::Event + * + * Authors: + * MenTaLguY <mental@rydia.net> + * + * Copyright (C) 2005 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#ifndef SEEN_INKSCAPE_DEBUG_SIMPLE_EVENT_H +#define SEEN_INKSCAPE_DEBUG_SIMPLE_EVENT_H + +#include <cstdarg> +#include <memory> +#include <string> +#include <vector> +#include <glib.h> // g_assert() + +#include "debug/event.h" + +namespace Inkscape { + +namespace Debug { + +template <Event::Category C=Event::OTHER> +class SimpleEvent : public Event { +public: + explicit SimpleEvent(char const *name) : _name(name) {} + + // default copy + // default assign + + static Category category() { return C; } + + char const *name() const override { return _name; } + unsigned propertyCount() const override { return _properties.size(); } + PropertyPair property(unsigned property) const override { + return _properties[property]; + } + + void generateChildEvents() const override {} + +protected: + void _addProperty(char const *name, std::shared_ptr<std::string>&& value) { + _properties.emplace_back(name, std::move(value)); + } + void _addProperty(char const *name, char const *value) { + _addProperty(name, std::make_shared<std::string>(value)); + } + void _addProperty(char const *name, long value) { + _addFormattedProperty(name, "%ld", value); + } + +private: + char const *_name; + std::vector<PropertyPair> _properties; + + void _addFormattedProperty(char const *name, char const *format, ...) + { + va_list args; + va_start(args, format); + gchar *value=g_strdup_vprintf(format, args); + g_assert(value != nullptr); + va_end(args); + _addProperty(name, value); + g_free(value); + } +}; + +} + +} + +#endif +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/debug/sysv-heap.cpp b/src/debug/sysv-heap.cpp new file mode 100644 index 0000000..7d21c02 --- /dev/null +++ b/src/debug/sysv-heap.cpp @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Debug::SysVHeap - malloc() statistics via System V interface + * + * Authors: + * MenTaLguY <mental@rydia.net> + * + * Copyright (C) 2005 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" // only include where actually required! +#endif + +#ifdef HAVE_MALLOC_H +# include <malloc.h> +#endif + +#include "debug/sysv-heap.h" + +namespace Inkscape { +namespace Debug { + +int SysVHeap::features() const { +#ifdef HAVE_MALLINFO + return SIZE_AVAILABLE | USED_AVAILABLE; +#else + return 0; +#endif +} + +Heap::Stats SysVHeap::stats() const { + Stats stats = { 0, 0 }; + +#ifdef HAVE_MALLINFO +#ifdef HAVE_MALLINFO2 + struct mallinfo2 info=mallinfo2(); +#else + struct mallinfo info=mallinfo(); +#endif + +#ifdef HAVE_STRUCT_MALLINFO_USMBLKS + stats.size += info.usmblks; + stats.bytes_used += info.usmblks; +#endif + +#ifdef HAVE_STRUCT_MALLINFO_FSMBLKS + stats.size += info.fsmblks; +#endif + +#ifdef HAVE_STRUCT_MALLINFO_UORDBLKS + stats.size += info.uordblks; + stats.bytes_used += info.uordblks; +#endif + +#ifdef HAVE_STRUCT_MALLINFO_FORDBLKS + stats.size += info.fordblks; +#endif + +#ifdef HAVE_STRUCT_MALLINFO_HBLKHD + stats.size += info.hblkhd; + stats.bytes_used += info.hblkhd; +#endif + +#endif + + return stats; +} + +} +} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/debug/sysv-heap.h b/src/debug/sysv-heap.h new file mode 100644 index 0000000..f7ed271 --- /dev/null +++ b/src/debug/sysv-heap.h @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Debug::SysVHeap - malloc() statistics via System V interface + * + * Authors: + * MenTaLguY <mental@rydia.net> + * + * Copyright (C) 2005 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#ifndef SEEN_INKSCAPE_DEBUG_SYSV_HEAP_H +#define SEEN_INKSCAPE_DEBUG_SYSV_HEAP_H + +#include "debug/heap.h" + +namespace Inkscape { +namespace Debug { + +class SysVHeap : public Heap { +public: + SysVHeap() = default; + + int features() const override; + + char const *name() const override { + return "standard malloc()"; + } + Stats stats() const override; + void force_collect() override {} +}; + +} +} + +#endif + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/debug/timestamp.cpp b/src/debug/timestamp.cpp new file mode 100644 index 0000000..dab4e73 --- /dev/null +++ b/src/debug/timestamp.cpp @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Debug::SimpleEvent - trivial implementation of Debug::Event + * + * Authors: + * MenTaLguY <mental@rydia.net> + * + * Copyright (C) 2007 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + + +#include <glib.h> +#include <glibmm/ustring.h> +#include <memory> +#include <string> +#include "debug/simple-event.h" +#include "timestamp.h" + +namespace Inkscape { + +namespace Debug { + +std::shared_ptr<std::string> timestamp() { + gint64 micr = g_get_monotonic_time(); + gchar *value = g_strdup_printf("%.6f", (gdouble)micr / 1000000.0); + std::shared_ptr<std::string> result = std::make_shared<std::string>(value); + g_free(value); + return result; +} + +} + +} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/debug/timestamp.h b/src/debug/timestamp.h new file mode 100644 index 0000000..a4db90d --- /dev/null +++ b/src/debug/timestamp.h @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Debug::timestamp - timestamp strings + * + * Authors: + * MenTaLguY <mental@rydia.net> + * + * Copyright (C) 2007 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#ifndef SEEN_INKSCAPE_DEBUG_TIMESTAMP_H +#define SEEN_INKSCAPE_DEBUG_TIMESTAMP_H + +#include <memory> +#include <string> + +namespace Inkscape { + +namespace Debug { + +std::shared_ptr<std::string> timestamp(); + +} + +} + +#endif +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : |