This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch improve-macos-support
in repository terminology.
View the commit online.
commit 61177e902c14a447cb299aaa842f2d187ad80a7c
Author: Cedric BAIL <[email protected]>
AuthorDate: Mon Aug 3 13:50:32 2026 -0600
termpty: narrow the line-length scan with a reverse SIMD pass
termpty_line_length() trims a row to its used width by walking backwards from
the far edge, and is called for every row that scrolls into the backlog as
well as for display. It skipped blank cells eight at a time with memcmp, so a
mostly-empty 80-column row cost a string of libc calls.
An all-zero cell is always empty -- COL_DEF is 0 -- so nothing past the last
non-zero byte of the row can contribute to the length. The reverse scan kernel
added here finds that byte in one backwards pass, a vector at a time, taking
the highest set lane of the first block that has one; the exact per-cell test
then starts there. The range is only narrowed, never the decision: cells that
are blank without being all-zero are still classified by
_termpty_cell_is_empty() as before.
Worth about 3% of the intake path -- less than the profile first suggested,
because the scan still has to walk the blank tail. SIMD makes each byte
cheaper but does not avoid any of them. Avoiding the walk entirely needs a
per-row used-width hint, which every path that writes cells would have to
maintain, and one that forgot would silently truncate scrollback.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
---
src/bin/termpty.c | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/src/bin/termpty.c b/src/bin/termpty.c
index d04b4103..a7f8d521 100644
--- a/src/bin/termpty.c
+++ b/src/bin/termpty.c
@@ -966,21 +966,20 @@ _termpty_line_is_empty(const Termcell *cells, ssize_t nb_cells)
ssize_t
termpty_line_length(const Termcell *cells, ssize_t nb_cells)
{
- static const Termcell zero_cells[8] = {{0}};
ssize_t pos;
+ size_t used;
if (!cells || nb_cells <= 0)
return 0;
- pos = nb_cells;
+ /* An all-zero cell is always empty (COL_DEF is 0), so nothing past the last
+ * non-zero byte can contribute. This only narrows the range; the per-cell
+ * test below still decides. */
+ used = simd_rscan_nonzero((const unsigned char *)cells,
+ (size_t)nb_cells * sizeof(Termcell));
+ pos = (ssize_t)((used + sizeof(Termcell) - 1) / sizeof(Termcell));
+ if (pos > nb_cells) pos = nb_cells;
- /* Fast scan: skip trailing chunks of 8 zero cells at a time.
- * glibc memcmp uses AVX2 for 96-byte comparisons. */
- while (pos >= 8 &&
- memcmp(&cells[pos - 8], zero_cells, 8 * sizeof(Termcell)) == 0)
- pos -= 8;
-
- /* Per-cell scan through the remaining tail */
for (pos = pos - 1; pos >= 0; pos--)
{
if (!_termpty_cell_is_empty(&cells[pos]))
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.