This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch master
in repository terminology.

View the commit online.

commit 4789fa5fa2618b9965547f21f76b182a85f43204
Author: Cedric BAIL <[email protected]>
AuthorDate: Mon Aug 3 13:26:31 2026 -0600

    termpty: stop paying for debug logging in the parser hot paths
    
    EINA_LOG_DOM_DBG() is an ordinary function call. Its arguments are evaluated
    before eina_log_print() ever looks at the level, so a DBG() in a hot path
    costs its formatting on every pass whether or not anyone is listening.
    
    termpty_handle_seq() had one inside the loop that scans a run of printable
    text, logging every character one at a time. termptyesc_safechar() only has a
    lookup table for control characters, so each printable character fell through
    to snprintf(). The shipping terminology binary therefore ran an snprintf and
    a seven-argument varargs log call for every character it displayed -- visible
    in the disassembly, and worth roughly a factor of four on plain text.
    
    Log the run once, after the scan, and only build the string when the domain
    really is at DBG level. Route the parser's DBG() through TERMPTY_DBG(), which
    checks the level with eina_log_domain_level_check() before touching its
    arguments; that covers the remaining hundred-odd sites at once and is worth
    another 60% on escape-heavy output. Where logging is compiled out the macro
    stays as it was, since eina already discards the whole statement and a level
    check would only add a call that would not otherwise exist.
    
    Co-Authored-By: Claude Opus 5 <[email protected]>
---
 src/bin/termpty.c    |  2 +-
 src/bin/termpty.h    | 17 +++++++++++++++++
 src/bin/termptyesc.c | 47 +++++++++++++++++++++++++++++++++++++++++++----
 src/bin/termptyops.c |  2 +-
 4 files changed, 62 insertions(+), 6 deletions(-)

diff --git a/src/bin/termpty.c b/src/bin/termpty.c
index 93ad4e25..f07acd80 100644
--- a/src/bin/termpty.c
+++ b/src/bin/termpty.c
@@ -42,7 +42,7 @@ int _termpty_log_dom = -1;
 #define ERR(...)      EINA_LOG_DOM_ERR(_termpty_log_dom, __VA_ARGS__)
 #define WRN(...)      EINA_LOG_DOM_WARN(_termpty_log_dom, __VA_ARGS__)
 #define INF(...)      EINA_LOG_DOM_INFO(_termpty_log_dom, __VA_ARGS__)
-#define DBG(...)      EINA_LOG_DOM_DBG(_termpty_log_dom, __VA_ARGS__)
+#define DBG(...)      TERMPTY_DBG(__VA_ARGS__)
 
 void
 termpty_init(void)
diff --git a/src/bin/termpty.h b/src/bin/termpty.h
index c24a25b7..9f26de2e 100644
--- a/src/bin/termpty.h
+++ b/src/bin/termpty.h
@@ -358,6 +358,23 @@ termpty_focus_report(Termpty *ty, Eina_Bool focus);
 
 extern int _termpty_log_dom;
 
+/* Debug logging for the parser. EINA_LOG_DOM_DBG() evaluates its arguments
+ * before the level is checked, which is too expensive for the hot paths, so
+ * check the level first. */
+#if defined(EINA_LOG_LEVEL_MAXIMUM)
+/* Compiled out already; a level check would only add a call. */
+# define TERMPTY_DBG(...) EINA_LOG_DOM_DBG(_termpty_log_dom, __VA_ARGS__)
+#else
+# define TERMPTY_DBG(...)                                                     \
+   do                                                                         \
+     {                                                                        \
+        if (EINA_UNLIKELY(eina_log_domain_level_check(_termpty_log_dom,       \
+                                                      EINA_LOG_LEVEL_DBG)))   \
+          EINA_LOG_DOM_DBG(_termpty_log_dom, __VA_ARGS__);                    \
+     }                                                                        \
+   while (0)
+#endif
+
 #define TERMPTY_SCREEN(Tpty, X, Y) \
   Tpty->screen[X + (((Y + Tpty->circular_offset) % Tpty->h) * Tpty->w)]
 
diff --git a/src/bin/termptyesc.c b/src/bin/termptyesc.c
index 92a2a2a6..2348e43e 100644
--- a/src/bin/termptyesc.c
+++ b/src/bin/termptyesc.c
@@ -25,7 +25,7 @@
 #define ERR(...)      EINA_LOG_DOM_ERR(_termpty_log_dom, __VA_ARGS__)
 #define WRN(...)      EINA_LOG_DOM_WARN(_termpty_log_dom, __VA_ARGS__)
 #define INF(...)      EINA_LOG_DOM_INFO(_termpty_log_dom, __VA_ARGS__)
-#define DBG(...)      EINA_LOG_DOM_DBG(_termpty_log_dom, __VA_ARGS__)
+#define DBG(...)      TERMPTY_DBG(__VA_ARGS__)
 
 #define ST 0x9c // String Terminator
 #define BEL 0x07 // Bell
@@ -94,6 +94,47 @@ termptyesc_safechar(const unsigned int c)
    return _str;
 }
 
+/* Render a run of printable codepoints into one DBG line. Checks the level
+ * itself, since it is the formatting loop that needs skipping. Long runs are
+ * truncated. */
+#if defined(EINA_LOG_LEVEL_MAXIMUM)
+static void
+_log_text_run(const Eina_Unicode *c EINA_UNUSED, int len EINA_UNUSED)
+{
+}
+#else
+static void
+_log_text_run(const Eina_Unicode *c, int len)
+{
+   char buf[512];
+   int i, n = 0;
+
+   /* Binaries that compile logging out never register the domain, so asking
+    * about its level would trip eina's safety check. */
+   if (EINA_LIKELY(!eina_log_domain_level_check(_termpty_log_dom,
+                                                EINA_LOG_LEVEL_DBG)))
+     return;
+
+   for (i = 0; i < len; i++)
+     {
+        /* termptyesc_safechar() returns a pointer to its own static buffer, so
+         * copy before calling it again. */
+        const char *s = termptyesc_safechar(c[i]);
+        int l = strlen(s);
+
+        if (n + l >= (int)sizeof(buf) - 1) break;
+        memcpy(buf + n, s, l);
+        n += l;
+     }
+   buf[n] = '\0';
+
+   if (i < len)
+     DBG("txt: [%s...] (%d codepoints)", buf, len);
+   else
+     DBG("txt: [%s]", buf);
+}
+#endif
+
 static Eina_Bool
 _cursor_is_within_margins(const Termpty *ty)
 {
@@ -5308,15 +5349,13 @@ termpty_handle_seq(Termpty *ty, const Eina_Unicode *c, const Eina_Unicode *ce)
      }
    cc = (Eina_Unicode *)c;
 
-   DBG("txt: [");
    while ((cc < ce) && (*cc >= 0x20) && (*cc != DEL) && (*cc != CSI)
           && (*cc != OSC))
      {
-        DBG("%s", termptyesc_safechar(*cc));
         cc++;
         len++;
      }
-   DBG("]");
+   _log_text_run(c, len);
    termpty_text_append(ty, c, len);
    if (len > 0)
        last_char = c[len-1];
diff --git a/src/bin/termptyops.c b/src/bin/termptyops.c
index 2e0fec93..f1ceb0fc 100644
--- a/src/bin/termptyops.c
+++ b/src/bin/termptyops.c
@@ -19,7 +19,7 @@
 #define ERR(...)      EINA_LOG_DOM_ERR(_termpty_log_dom, __VA_ARGS__)
 #define WRN(...)      EINA_LOG_DOM_WARN(_termpty_log_dom, __VA_ARGS__)
 #define INF(...)      EINA_LOG_DOM_INFO(_termpty_log_dom, __VA_ARGS__)
-#define DBG(...)      EINA_LOG_DOM_DBG(_termpty_log_dom, __VA_ARGS__)
+#define DBG(...)      TERMPTY_DBG(__VA_ARGS__)
 
 void
 termpty_cells_clear(Termpty *ty, Termcell *cells, int count)

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to