Subject: Re: 26.2.90; [PATCH] Speed up 'csv-align-fields'

From: Simen Heggestøyl <[email-masked]>
Date: Tue, 17 Sep 2019 18:53:06 +0200

Eli Zaretskii <[email-masked]> writes:

> I'm talking here about something I don't understand well enough, but
> did you try computing column width using vertical-motion?

No, I haven't yet tried anything in that direction.

Stefan Monnier <[email-masked]> writes:

>>> If you're interested in this line, I think there are two avenues to
>>> improve the behavior further:
>>> - align lazily via jit-lock (this way the time is determined by the
>>>   amount of text displayed rather than the total file size).
>> Wouldn't that still depend on knowing the column widths?
>
> Of the whole file?  No: instead you'd only use the max of the columns that
> you've seen so far.  When it increases (thus invalidating
> alignment-overlays already created), you just "flush" those overlays and
> rebuild them.

Wouldn't then the columns appear to jump about whenever a new max width
is discovered? I also guess you'd lose the ability to do e.g.
C-u 1000 C-n and stay in the same column?

> Maybe we could get yet more speedup by making it possible to pass to
> `current-column` (or a new C function) a start position along with its
> column, so we'd avoid re-traversing the part of the line that we've
> already processed.

I think that sounds like a good idea; then my ugly "fast-current-column"
patch from last time won't be needed. I have no prior experience with
Emacs' C internals, but an initial naive attempt is attached. I've only
tested it on some basic cases where it seems to behave correctly and
gives a speedup factor of around 4,5x–5x. Could this track be something
worth exploring further?
>From 16d8915b8ad96b2aa7fb0350468b4af847c5ff19 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simen=20Heggest=C3=B8yl?= <[email-masked]>
Date: Tue, 17 Sep 2019 17:32:00 +0200
Subject: [PATCH] WIP

---
 src/indent.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/src/indent.c b/src/indent.c
index 1b589a710c..f2c525d882 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -46,6 +46,10 @@ #define CR 015
 
 ptrdiff_t last_known_column_point;
 
+/* Value of point byte when current_column was called.  */
+
+ptrdiff_t last_known_column_point_byte;
+
 /* Value of MODIFF when current_column was called.  */
 
 static modiff_count last_known_column_modified;
@@ -325,6 +329,7 @@ DEFUN ("current-column", Fcurrent_column, Scurrent_column, 0, 0, 0,
 invalidate_current_column (void)
 {
   last_known_column_point = 0;
+  last_known_column_point_byte = 0;
 }
 
 ptrdiff_t
@@ -454,6 +459,7 @@ current_column (void)
 
   last_known_column = col;
   last_known_column_point = PT;
+  last_known_column_point_byte = PT_BYTE;
   last_known_column_modified = MODIFF;
 
   return col;
@@ -545,6 +551,17 @@ scan_for_column (ptrdiff_t *endpos, EMACS_INT *goalcol, ptrdiff_t *prevcol)
   ptrdiff_t scan, scan_byte, next_boundary;
 
   scan = find_newline (PT, PT_BYTE, BEGV, BEGV_BYTE, -1, NULL, &scan_byte, 1);
+
+  if (scan < last_known_column_point
+      && end > last_known_column_point
+      && MODIFF == last_known_column_modified)
+    {
+      scan = last_known_column_point;
+      scan_byte = last_known_column_point_byte;
+      col = last_known_column;
+      prev_col = last_known_column;
+    }
+
   next_boundary = scan;
 
   window = Fget_buffer_window (Fcurrent_buffer (), Qnil);
@@ -701,6 +718,7 @@ scan_for_column (ptrdiff_t *endpos, EMACS_INT *goalcol, ptrdiff_t *prevcol)
 
   last_known_column = col;
   last_known_column_point = PT;
+  last_known_column_point_byte = PT_BYTE;
   last_known_column_modified = MODIFF;
 
   if (goalcol)
@@ -848,6 +866,7 @@ DEFUN ("indent-to", Findent_to, Sindent_to, 1, 2, "NIndent to column: ",
 
   last_known_column = mincol;
   last_known_column_point = PT;
+  last_known_column_point_byte = PT_BYTE;
   last_known_column_modified = MODIFF;
 
   XSETINT (column, mincol);
@@ -1040,6 +1059,7 @@ COLUMN (otherwise).  In addition, if FORCE is t, and the line is too short
 
   last_known_column = col;
   last_known_column_point = PT;
+  last_known_column_point_byte = PT_BYTE;
   last_known_column_modified = MODIFF;
 
   return make_fixnum (col);
-- 
2.23.0

-- Simen