From 35a96bde514a8897f6f0fcc41c5833bf63df2e2a Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 18:29:01 +0200 Subject: Adding upstream version 1.0.2. Signed-off-by: Daniel Baumann --- src/debug/CMakeLists.txt | 29 ++++ src/debug/demangle.cpp | 78 ++++++++++ src/debug/demangle.h | 39 +++++ src/debug/event-tracker.h | 225 +++++++++++++++++++++++++++++ src/debug/event.h | 81 +++++++++++ src/debug/gc-heap.h | 53 +++++++ src/debug/gdk-event-latency-tracker.cpp | 81 +++++++++++ src/debug/gdk-event-latency-tracker.h | 57 ++++++++ src/debug/heap.cpp | 62 ++++++++ src/debug/heap.h | 63 ++++++++ src/debug/log-display-config.cpp | 79 ++++++++++ src/debug/log-display-config.h | 36 +++++ src/debug/logger.cpp | 231 +++++++++++++++++++++++++++++ src/debug/logger.h | 247 ++++++++++++++++++++++++++++++++ src/debug/simple-event.h | 87 +++++++++++ src/debug/sysv-heap.cpp | 80 +++++++++++ src/debug/sysv-heap.h | 48 +++++++ src/debug/timestamp.cpp | 46 ++++++ src/debug/timestamp.h | 39 +++++ 19 files changed, 1661 insertions(+) create mode 100644 src/debug/CMakeLists.txt create mode 100644 src/debug/demangle.cpp create mode 100644 src/debug/demangle.h create mode 100644 src/debug/event-tracker.h create mode 100644 src/debug/event.h create mode 100644 src/debug/gc-heap.h create mode 100644 src/debug/gdk-event-latency-tracker.cpp create mode 100644 src/debug/gdk-event-latency-tracker.h create mode 100644 src/debug/heap.cpp create mode 100644 src/debug/heap.h create mode 100644 src/debug/log-display-config.cpp create mode 100644 src/debug/log-display-config.h create mode 100644 src/debug/logger.cpp create mode 100644 src/debug/logger.h create mode 100644 src/debug/simple-event.h create mode 100644 src/debug/sysv-heap.cpp create mode 100644 src/debug/sysv-heap.h create mode 100644 src/debug/timestamp.cpp create mode 100644 src/debug/timestamp.h (limited to 'src/debug') 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..60e1f17 --- /dev/null +++ b/src/debug/demangle.cpp @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Debug::demangle - demangle C++ symbol names + * + * Authors: + * MenTaLguY + * + * Copyright (C) 2006 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include +#include +#include +#include +#include +#include "debug/demangle.h" +#include "util/format.h" + +namespace Inkscape { + +namespace Debug { + +namespace { + +char const *demangle_helper(char const *name) { + char buffer[1024]; + char const *result; + FILE *stream=popen(Util::format("c++filt %s", name), "r"); + if (fgets(buffer, sizeof(buffer), stream)) { + size_t len=strlen(buffer); + if ( buffer[len-1] == '\n' ) { + buffer[len-1] = '\000'; + } + result = strdup(buffer); + } else { + result = name; + } + pclose(stream); + return result; +} + +struct string_less_than { + bool operator()(char const *a, char const *b) const { + return ( strcmp(a, b) < 0 ); + } +}; + +typedef std::map, string_less_than> MangleCache; +MangleCache mangle_cache; + +} + +std::shared_ptr demangle(char const *name) { + MangleCache::iterator found=mangle_cache.find(name); + if ( found != mangle_cache.end() ) { + return (*found).second; + } + + char const *result = demangle_helper(name); + return mangle_cache[name] = std::make_shared(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 + * + * 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 +#include + +namespace Inkscape { + +namespace Debug { + +std::shared_ptr 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..e70e2ad --- /dev/null +++ b/src/debug/event-tracker.h @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Debug::EventTracker - semi-automatically track event lifetimes + * + * Authors: + * MenTaLguY + * + * 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 { + +struct NoInitialEvent {}; + +template class EventTracker; + +class EventTrackerBase { +public: + virtual ~EventTrackerBase() { + if (_active) { + Logger::finish(); + } + } + + template + inline void set() { + if (_active) { + Logger::finish(); + } + Logger::start(); + _active = true; + } + + template + inline void set(A const &a) { + if (_active) { + Logger::finish(); + } + Logger::start(a); + _active = true; + } + + template + inline void set(A const &a, B const &b) { + if (_active) { + Logger::finish(); + } + Logger::start(a, b); + _active = true; + } + + template + inline void set(A const &a, B const &b, C const &c) { + if (_active) { + Logger::finish(); + } + Logger::start(a, b, c); + _active = true; + } + + template + inline void set(A const &a, B const &b, C const &c, D const &d) { + if (_active) { + Logger::finish(); + } + Logger::start(a, b, c, d); + _active = true; + } + + template + inline void set(A const &a, B const &b, C const &c, D const &d, E const &e) + { + if (_active) { + Logger::finish(); + } + Logger::start(a, b, c, d, e); + _active = true; + } + + template + 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(a, b, c, d, e, f); + _active = true; + } + + template + 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(a, b, c, d, e, f, g); + _active = true; + } + + template + 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(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 class EventTracker : public EventTrackerBase { +public: + EventTracker() : EventTrackerBase(true) { Logger::start(); } + + template + EventTracker(A const &a) : EventTrackerBase(true) { + Logger::start(a); + } + + template + EventTracker(A const &a, B const &b) : EventTrackerBase(true) { + Logger::start(a, b); + } + + template + EventTracker(A const &a, B const &b, C const &c) : EventTrackerBase(true) { + Logger::start(a, b, c); + } + + template + EventTracker(A const &a, B const &b, C const &c, D const &d) + : EventTrackerBase(true) + { + Logger::start(a, b, c, d); + } + + template + EventTracker(A const &a, B const &b, C const &c, D const &d, E const &e) + : EventTrackerBase(true) + { + Logger::start(a, b, c, d, e); + } + + template + EventTracker(A const &a, B const &b, C const &c, D const &d, + E const &e, F const &f) + : EventTrackerBase(true) + { + Logger::start(a, b, c, d, e, f); + } + + template + 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(a, b, c, d, e, f, g); + } + + template + 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(a, b, c, d, e, f, g, h); + } +}; + +template <> class EventTracker : public EventTrackerBase { +public: + EventTracker() : EventTrackerBase(false) {} +}; + +} + +} + +#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 + * + * 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 +#include +#include + +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&& v) + : name(n), value(std::move(v)) {} + PropertyPair(char const *n, char const *v) + : name(n), + value(std::make_shared(v)) {} + + char const *name; + std::shared_ptr 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 + * + * 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..57d3e1f --- /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 + * + * Copyright (C) 2008 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include + +#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(); +} + +boost::optional GdkEventLatencyTracker::process(GdkEvent const *event) { + guint32 const timestamp=gdk_event_get_time(const_cast(event)); + if (timestamp == GDK_CURRENT_TIME) { + return boost::optional(); + } + 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 boost::optional(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 boost::optional(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..9c1cd1f --- /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 + * + * 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 +#include + +namespace Inkscape { +namespace Debug { + +class GdkEventLatencyTracker { +public: + GdkEventLatencyTracker(); + boost::optional 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 + * + * 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 + +namespace Inkscape { +namespace Debug { + +namespace { + +typedef std::vector > 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 + * + * 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 + +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 + * + * Copyright (C) 2007 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include +#include +#include +#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 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); + } + } +}; + +} + +void log_display_config() { + Logger::write(); +} + +} + +} + +/* + 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 + * + * 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 + * + * Copyright (C) 2005 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include +#include +#include +#include +#include +#include +#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> 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 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 << "\n"; + log_stream.flush(); + _enabled = true; + start(); + 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(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 << "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 + * + * 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 + inline static void start() { + if (_enabled) { + if (_category_mask[EventType::category()]) { + _start(EventType()); + } else { + _skip(); + } + } + } + + template + inline static void start(A const &a) { + if (_enabled) { + if (_category_mask[EventType::category()]) { + _start(EventType(a)); + } else { + _skip(); + } + } + } + + template + inline static void start(A const &a, B const &b) { + if (_enabled) { + if (_category_mask[EventType::category()]) { + _start(EventType(a, b)); + } else { + _skip(); + } + } + } + + template + 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 + 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 + 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 + 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 + 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 + 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 + inline static void write() { + start(); + finish(); + } + + template + inline static void write(A const &a) { + start(a); + finish(); + } + + template + inline static void write(A const &a, B const &b) { + start(a, b); + finish(); + } + + template + inline static void write(A const &a, B const &b, C const &c) { + start(a, b, c); + finish(); + } + + template + inline static void write(A const &a, B const &b, C const &c, D const &d) { + start(a, b, c, d); + finish(); + } + + template + inline static void write(A const &a, B const &b, C const &c, + D const &d, E const &e) + { + start(a, b, c, d, e); + finish(); + } + + template + inline static void write(A const &a, B const &b, C const &c, + D const &d, E const &e, F const &f) + { + start(a, b, c, d, e, f); + finish(); + } + + template + 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(a, b, c, d, e, f, g); + finish(); + } + + template + 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(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 + * + * 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 +#include +#include +#include +#include // g_assert() + +#include "debug/event.h" + +namespace Inkscape { + +namespace Debug { + +template +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&& value) { + _properties.emplace_back(name, std::move(value)); + } + void _addProperty(char const *name, char const *value) { + _addProperty(name, std::make_shared(value)); + } + void _addProperty(char const *name, long value) { + _addFormattedProperty(name, "%ld", value); + } + +private: + char const *_name; + std::vector _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..41455e6 --- /dev/null +++ b/src/debug/sysv-heap.cpp @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Inkscape::Debug::SysVHeap - malloc() statistics via System V interface + * + * Authors: + * MenTaLguY + * + * 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 +#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 + struct mallinfo info=mallinfo(); + +#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 + * + * 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 + * + * Copyright (C) 2007 MenTaLguY + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + + +#include +#include +#include +#include +#include "debug/simple-event.h" +#include "timestamp.h" + +namespace Inkscape { + +namespace Debug { + +std::shared_ptr timestamp() { + gint64 micr = g_get_monotonic_time(); + gchar *value = g_strdup_printf("%.6f", (gdouble)micr / 1000000.0); + std::shared_ptr result = std::make_shared(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 + * + * 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 +#include + +namespace Inkscape { + +namespace Debug { + +std::shared_ptr 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 : -- cgit v1.2.3