On 16/08/06, Brad Beveridge <[EMAIL PROTECTED]> wrote:
On 16/08/06, Bram Moolenaar <[EMAIL PROTECTED]> wrote:
>
> Brad -
>
> > As a side note, if I wanted to get really fast char append, how does
> > this method sound:
> > 1) In a structure (not sure if a mem_line or bufT struct), have three
> > new entries
> > uint current_line_num;
> > uchar *current_line_buffer;
> > uint current_line_alloced;
> > 2) current_line_buffer points to the string data for the current line,
> > it starts off at a sane size (say 80, or screen_width), and doubles in
> > alloced size when it is too full.
> > 3) ml_append_char (or whatever I call it), will check the target line
> > number against current_line_number, if the match then
> >   - append the char, possibly reallocing the current_line_buffer if we
> > have run out of space
> > ELSE, the edit line number and our "cached line" don't match
> >   - trim the size of the current_line_buffer to match the STRLEN of the line
> >   - alloc a new oversized line buffer and copy the new edit line into it
> >   - append the char as above
>
> Vim caches the last changed line, you could do something with that.
> Start looking at ml_flush_line(), you can find the rest from there.
>
> > Would this kind of optimisation be more widely useful?
>
> Perhaps.  Changing the same line several times is not unusual.  It
> mostly depends on how much code would need to be changed compared to
> how much we would gain.
>
> - Bram
>

Thanks for the tips, I'll test all this out and see what I can come up
with.  I also accidentally posted just to Bram, so I've included the
list in this reply.

Thanks
Brad

I ended up writing a string append function, that has sped up my
output code by a couple of orders of magnitude :)  Here it is, does it
look sane?

Cheers
Brad

/*
* Append string to line lnum, with buffering, in current buffer.
*
* Always makes a copy of the incoming string
*
* Check: The caller of this function should probably also call
* changed_lines(), unless update_screen(NOT_VALID) is used.
*
* return FAIL for failure, OK otherwise
*/
   int
ml_append_string(lnum, string, slen)
   linenr_T    lnum;
   char_u  *string;
   int     slen;
{
   int append_len = 0;
   int line_len = 0;
   if (slen == -1)
       append_len = STRLEN(string);
   else
       append_len = slen;
   if (string == NULL)     /* just checking... */
       return FAIL;

   if (lnum == 0)
       ml_append (lnum, string, slen, 0);

   /* When starting up, we might still need to create the memfile */
   if (curbuf->b_ml.ml_mfp == NULL && open_buffer(FALSE, NULL) == FAIL)
       return FAIL;

#ifdef FEAT_NETBEANS_INTG
   /*
#error I am 99% sure this is broken
   if (usingNetbeans)
   {
       netbeans_removed(curbuf, lnum, 0, (long)STRLEN(ml_get(lnum)));
       netbeans_inserted(curbuf, lnum, 0, string, (int)STRLEN(string));
   }
   */
#endif
   if (curbuf->b_ml.ml_line_lnum != lnum)      /* other line buffered */
   {
       ml_flush_line(curbuf);              /* flush it, this frees
ml_line_ptr */

       /* Take a pointer to the existing line, will get re-alloced right
        * away below because it is not big enough */
       curbuf->b_ml.ml_line_ptr = vim_strsave(ml_get(lnum));
       curbuf->b_ml.ml_line_len = STRLEN(curbuf->b_ml.ml_line_ptr);
       curbuf->b_ml.ml_line_lnum = lnum;
   }
   /* By here,
    * curbuf->b_ml.ml_line_ptr - is filled with the correct existing line
    * curbuf->b_ml.ml_line_len - is the alloced size of the line
    */
   line_len = STRLEN(curbuf->b_ml.ml_line_ptr);
   if (curbuf->b_ml.ml_line_len < line_len + append_len + 1)
   {
       int new_len = (curbuf->b_ml.ml_line_len + line_len + 1) * 2;
       char_u *new_line;
       if (new_len < 80) new_len = 80;
       new_line = vim_strnsave(curbuf->b_ml.ml_line_ptr, new_len);
       vim_free(curbuf->b_ml.ml_line_ptr);
       curbuf->b_ml.ml_line_ptr = new_line;
       curbuf->b_ml.ml_line_len = new_len;
   }
   /* by here:
    * ml_line_ptr is allocated to fit the current line + the append
    * ml_line_len is the total alloced size of the line
    */
   STRCPY (&curbuf->b_ml.ml_line_ptr[line_len], string);  /* Append
our string */
   curbuf->b_ml.ml_line_ptr[line_len + append_len] = NUL; /* End the line */
   curbuf->b_ml.ml_flags = (curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY;

   return OK;
}

Reply via email to