Here is my fix.  It seems to work manually testing it with a few cases.
Here is the timing of vim installed with my Ubuntu:
% yes | head -100000 > yes.tmp
% time vim -u NONE -c '%join|q!' yes.tmp 
17.2u 0.0s 0:17.24 99.8% 0+0k 0+8io 0pf+0w

And with my patch:
% time ./vim -u NONE -c '%join|q!' yes.tmp 
0.2u 0.0s 0:00.29 96.5% 0+0k 0+8io 0pf+0w

Below is the patch (a diff of ops_orig.c and ops.c).  It needs a bit of
cleaning up (eg putting the function prototype where it belongs) and
checking that the error handling is done in a correct way (I've tried
to be consistent with existing code but don't really understand how it
all works, eg with the magic of undo).

        lee

        P.S. I posted something else which hasn't shown up yet - maybe due
        to moderation.  I'm doing this via e-mail as I have not yet handed
        over all my personal details to Google.

*** ops_orig.c  2008-12-10 15:15:08.000000000 +1100
--- ops.c       2008-12-11 17:10:15.000000000 +1100
***************
*** 4102,4107 ****
--- 4102,4109 ----
      ui_breakcheck();
  }
  
+ int do_do_join_rec(long, int); /* MOVE/FIX this */
+ 
  /*
   * join 'count' lines (minimal 2), including u_save()
   */
***************
*** 4110,4130 ****
      long    count;
      int           insert_space;
  {
      colnr_T   col = MAXCOL;
  
      if (u_save((linenr_T)(curwin->w_cursor.lnum - 1),
                    (linenr_T)(curwin->w_cursor.lnum + count)) == FAIL)
        return;
  
!     while (--count > 0)
      {
        line_breakcheck();
        if (got_int || do_join(insert_space) == FAIL)
        {
            beep_flush();
!           break;
!       }
!       if (col == MAXCOL && vim_strchr(p_cpo, CPO_JOINCOL) != NULL)
            col = curwin->w_cursor.col;
      }
  
--- 4112,4140 ----
      long    count;
      int           insert_space;
  {
+     int               failflag = OK;
      colnr_T   col = MAXCOL;
  
      if (u_save((linenr_T)(curwin->w_cursor.lnum - 1),
                    (linenr_T)(curwin->w_cursor.lnum + count)) == FAIL)
        return;
  
!     /* Its simplest to call do_join() count-1 times in a while loop
!      * but this leads to O(count^2) complexity.
!      * Better to use a divide and conquer strategy, leading to
!      * O(count log count) complexity.  Here we use D&Q for first
!      * count-1 lines (count-2 joins); the last join is done separately
!      * so we can set the new column for the cursor correctly.
!      */
!     if (count > 2)
!       failflag = do_do_join_rec(count-2, insert_space);
!     if (failflag == OK)
      {
        line_breakcheck();
        if (got_int || do_join(insert_space) == FAIL)
        {
            beep_flush();
!       } else if (col == MAXCOL && vim_strchr(p_cpo, CPO_JOINCOL) != NULL)
            col = curwin->w_cursor.col;
      }
  
***************
*** 4142,4147 ****
--- 4152,4192 ----
  }
  
  /*
+  * join 'count'+1 lines ('count' join ops), using recursive divide
+  * and conquer strategy
+  */
+     int
+ do_do_join_rec(count, insert_space)
+     long    count;
+     int           insert_space;
+ {
+     if (count == 0)
+       /* base case: nothing to do */
+       return OK;
+     else {
+ 
+       /* join all lines in first ~half */
+       if (got_int || do_do_join_rec((count-1)/2, insert_space) == FAIL)
+           return FAIL;
+ 
+       /* go to next line and join all lines in second ~half;
+        * we want a total of count-1 joins at this point
+        */
+       ++curwin->w_cursor.lnum;
+       if (got_int ||
+               do_do_join_rec(count-1-(count-1)/2, insert_space) == FAIL)
+           return FAIL;
+ 
+       /* go back to first (joined) line and join with the second */
+       --curwin->w_cursor.lnum;
+       line_breakcheck();
+       if (got_int || do_join(insert_space) == FAIL)
+           return FAIL;
+       return OK;
+     }
+ }
+ 
+ /*
   * Join two lines at the cursor position.
   * "redraw" is TRUE when the screen should be updated.
   * Caller must have setup for undo.

--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---

Raspunde prin e-mail lui