Re: Fastest way to append line or char to a buffer

2006-08-30 Thread Nikolai Weibull

On 8/30/06, Chris Littell <[EMAIL PROTECTED]> wrote:

On 8/30/06, Nikolai Weibull <[EMAIL PROTECTED]> wrote:
> In C99 you can initialize values "out of order", yes, but you can't do
> it with ranges.  Ranges are a GNU C extension.  The propagation
> neither happens in any of the ANSI standards, nor in the GNU extended
> version of C.  It's simple to test write the following in "a.c":
>
> #include 
>
> int
> main(void)
> {
> int is[2] = { 1 };
> int i;
>
> for (i = 0; i < 2; i++)
> printf("%d\n", is[i]);
>
> return 0;
> }
>
> And then to actually test it:
>
> $ for std in c89 c99 gnu89 gnu99; do gcc -std=$std a.c && echo $std:
> && a.out; done
> c89:
> 1
> 0
> c99:
> 1
> 0
> gnu89:
> 1
> 0
> gnu99:
> 1
> 0
>
> > 
http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/gcc/designated-inits.html
>
> Nowhere in that section does it say that the last value is propagated.

Wow, I reread it and you are correct.  I'm not sure why I held that
assumption...
Also thanks for the examples.


No worries.

 nikolai


Re: Fastest way to append line or char to a buffer

2006-08-30 Thread Chris Littell

On 8/30/06, Nikolai Weibull <[EMAIL PROTECTED]> wrote:

On 8/30/06, Chris Littell <[EMAIL PROTECTED]> wrote:
> On 8/30/06, Nikolai Weibull <[EMAIL PROTECTED]> wrote:
> > On 8/29/06, Brad Beveridge <[EMAIL PROTECTED]> wrote:
> > > On 29/08/06, Ilya <[EMAIL PROTECTED]> wrote:
> > > > Brad Beveridge wrote:
> > > > >static char string[2] = {0};
> > > > Should not you have "= {0, 0}" here?  Second element never get
> > > > initialized but it could be accessed by ml_append_string.
> > >
> > > That might be more clear perhaps, but when you initialize an array
> > > like that in C, the last element is propagated for the whole array.
> >
> > What C compiler are you using?  The last element is /not/ propagated
> > in C.  The rest of the array will be initialized to zero, which is the
>
> In C89 this is true.  In C99, you can initialize values out of order
> and by index range, and the final value in an array initializer is
> propogated to the rest of the values.

In C99 you can initialize values "out of order", yes, but you can't do
it with ranges.  Ranges are a GNU C extension.  The propagation
neither happens in any of the ANSI standards, nor in the GNU extended
version of C.  It's simple to test write the following in "a.c":

#include 

int
main(void)
{
int is[2] = { 1 };
int i;

for (i = 0; i < 2; i++)
printf("%d\n", is[i]);

return 0;
}

And then to actually test it:

$ for std in c89 c99 gnu89 gnu99; do gcc -std=$std a.c && echo $std:
&& a.out; done
c89:
1
0
c99:
1
0
gnu89:
1
0
gnu99:
1
0

> 
http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/gcc/designated-inits.html

Nowhere in that section does it say that the last value is propagated.


Wow, I reread it and you are correct.  I'm not sure why I held that
assumption...
Also thanks for the examples.



  nikolai



Chris


Re: Fastest way to append line or char to a buffer

2006-08-30 Thread Nikolai Weibull

On 8/30/06, Chris Littell <[EMAIL PROTECTED]> wrote:

On 8/30/06, Nikolai Weibull <[EMAIL PROTECTED]> wrote:
> On 8/29/06, Brad Beveridge <[EMAIL PROTECTED]> wrote:
> > On 29/08/06, Ilya <[EMAIL PROTECTED]> wrote:
> > > Brad Beveridge wrote:
> > > >static char string[2] = {0};
> > > Should not you have "= {0, 0}" here?  Second element never get
> > > initialized but it could be accessed by ml_append_string.
> >
> > That might be more clear perhaps, but when you initialize an array
> > like that in C, the last element is propagated for the whole array.
>
> What C compiler are you using?  The last element is /not/ propagated
> in C.  The rest of the array will be initialized to zero, which is the

In C89 this is true.  In C99, you can initialize values out of order
and by index range, and the final value in an array initializer is
propogated to the rest of the values.


In C99 you can initialize values "out of order", yes, but you can't do
it with ranges.  Ranges are a GNU C extension.  The propagation
neither happens in any of the ANSI standards, nor in the GNU extended
version of C.  It's simple to test write the following in "a.c":

#include 

int
main(void)
{
   int is[2] = { 1 };
   int i;

   for (i = 0; i < 2; i++)
   printf("%d\n", is[i]);

   return 0;
}

And then to actually test it:

$ for std in c89 c99 gnu89 gnu99; do gcc -std=$std a.c && echo $std:
&& a.out; done
c89:
1
0
c99:
1
0
gnu89:
1
0
gnu99:
1
0


http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/gcc/designated-inits.html


Nowhere in that section does it say that the last value is propagated.

 nikolai


Re: Fastest way to append line or char to a buffer

2006-08-30 Thread James Vega
On Wed, Aug 30, 2006 at 08:57:13AM -0400, Chris Littell wrote:
> On 8/30/06, Nikolai Weibull <[EMAIL PROTECTED]> wrote:
> >On 8/29/06, Brad Beveridge <[EMAIL PROTECTED]> wrote:
> >> On 29/08/06, Ilya <[EMAIL PROTECTED]> wrote:
> >> > Brad Beveridge wrote:
> >> > >static char string[2] = {0};
> >> > Should not you have "= {0, 0}" here?  Second element never get
> >> > initialized but it could be accessed by ml_append_string.
> >>
> >> That might be more clear perhaps, but when you initialize an array
> >> like that in C, the last element is propagated for the whole array.
> >
> >What C compiler are you using?  The last element is /not/ propagated
> >in C.  The rest of the array will be initialized to zero, which is the
> 
> In C89 this is true.  In C99, you can initialize values out of order
> and by index range, and the final value in an array initializer is
> propogated to the rest of the values.
> 
> http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/gcc/designated-inits.html

Quoting an example from this document:

  int a[6] = { [1] = v1, v2, [4] = v4 };

  is equivalent to

  int a[6] = { 0, v1, v2, 0, v4, 0 };

Which behaves as Nikolai suggested and K&R explains.  Any unspecified
elements are initialized to 0.

James
-- 
GPG Key: 1024D/61326D40 2003-09-02 James Vega <[EMAIL PROTECTED]>


signature.asc
Description: Digital signature


Re: Fastest way to append line or char to a buffer

2006-08-30 Thread Chris Littell

On 8/30/06, Nikolai Weibull <[EMAIL PROTECTED]> wrote:

On 8/29/06, Brad Beveridge <[EMAIL PROTECTED]> wrote:
> On 29/08/06, Ilya <[EMAIL PROTECTED]> wrote:
> > Brad Beveridge wrote:
> > >static char string[2] = {0};
> > Should not you have "= {0, 0}" here?  Second element never get
> > initialized but it could be accessed by ml_append_string.
>
> That might be more clear perhaps, but when you initialize an array
> like that in C, the last element is propagated for the whole array.

What C compiler are you using?  The last element is /not/ propagated
in C.  The rest of the array will be initialized to zero, which is the


In C89 this is true.  In C99, you can initialize values out of order
and by index range, and the final value in an array initializer is
propogated to the rest of the values.

http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/gcc/designated-inits.html


default for variables declared as being static.  Actually, the
explicit initialization to zero is redundant and actually causes the
size of the resulting executable to increase.  See
http://people.redhat.com/drepper/dsohowto.pdf for a better explanation
than I could give here.

  nikolai



Chris


Re: Fastest way to append line or char to a buffer

2006-08-30 Thread Nikolai Weibull

On 8/29/06, Brad Beveridge <[EMAIL PROTECTED]> wrote:

On 29/08/06, Ilya <[EMAIL PROTECTED]> wrote:
> Brad Beveridge wrote:
> >static char string[2] = {0};
> Should not you have "= {0, 0}" here?  Second element never get
> initialized but it could be accessed by ml_append_string.

That might be more clear perhaps, but when you initialize an array
like that in C, the last element is propagated for the whole array.


What C compiler are you using?  The last element is /not/ propagated
in C.  The rest of the array will be initialized to zero, which is the
default for variables declared as being static.  Actually, the
explicit initialization to zero is redundant and actually causes the
size of the resulting executable to increase.  See
http://people.redhat.com/drepper/dsohowto.pdf for a better explanation
than I could give here.

 nikolai


Re: Fastest way to append line or char to a buffer

2006-08-29 Thread Brad Beveridge

On 29/08/06, Ilya <[EMAIL PROTECTED]> wrote:

Brad Beveridge wrote:
> On 26/08/06, Brad Beveridge <[EMAIL PROTECTED]> wrote:
> 
>>
>> Cheers
>> Brad
>
> Hi, sorry for all the trouble :)  I'm having redraw issues, where
> running this code to append chars is causing strange problems.
> The scenario is this (always using the code below for char output):
> 1) Write a char to a buffer (line1)
> 2) Write a newline (line 2)
> 3) Move the cursor to the bottom of the buffer (line2 empty)
> 4) Write another Char (appears in line2)
> 5) Press Ctrl-L
> 6) Notice that line1 has vanished.
>
> moving the cursor to the new blank line at the bottom of the line is
> critical here.  I'm sure that I'm doing something wrong, but I really
> can't figure it out.
> As a side note, it feels very clumsy to have to manually call "changed
> line" functions when calling ml_* funcs - is there some notes I can
> read about why this is?
> Anyhow, here is the code I'm using to put chars in a buffer - I really
> appreciate any thoughts, this feels so close to working, but I've
> spend several hours trying to get it right.  Very frustrating :)
>
> Cheers
> Brad
>
> static void vim_append_char (buf_T target_buf, char c)
> {
>static char string[2] = {0};
Should not you have "= {0, 0}" here?  Second element never get
initialized but it could be accessed by ml_append_string.


That might be more clear perhaps, but when you initialize an array
like that in C, the last element is propagated for the whole array.

Cheers
Brad


Re: Fastest way to append line or char to a buffer

2006-08-29 Thread Ilya

Brad Beveridge wrote:

On 26/08/06, Brad Beveridge <[EMAIL PROTECTED]> wrote:



Cheers
Brad


Hi, sorry for all the trouble :)  I'm having redraw issues, where
running this code to append chars is causing strange problems.
The scenario is this (always using the code below for char output):
1) Write a char to a buffer (line1)
2) Write a newline (line 2)
3) Move the cursor to the bottom of the buffer (line2 empty)
4) Write another Char (appears in line2)
5) Press Ctrl-L
6) Notice that line1 has vanished.

moving the cursor to the new blank line at the bottom of the line is
critical here.  I'm sure that I'm doing something wrong, but I really
can't figure it out.
As a side note, it feels very clumsy to have to manually call "changed
line" functions when calling ml_* funcs - is there some notes I can
read about why this is?
Anyhow, here is the code I'm using to put chars in a buffer - I really
appreciate any thoughts, this feels so close to working, but I've
spend several hours trying to get it right.  Very frustrating :)

Cheers
Brad

static void vim_append_char (buf_T target_buf, char c)
{
   static char string[2] = {0};
Should not you have "= {0, 0}" here?  Second element never get 
initialized but it could be accessed by ml_append_string.

   buf_T *savebuf = curbuf;
   curbuf = target_buf;
   int start_line = curbuf->b_ml.ml_line_count;
   int lines_changed = 0;

   string[0] = c;
   if (string[0] == '\n')
   {
   ml_append (start_line, "", 0, FALSE);
   lines_changed = 0;
   }
   else
   ml_append_string (start_line, string, -1);
   changed_lines (start_line, 0, start_line, lines_changed);

   /* restore and return */
   curbuf = savebuf;
}






Re: Fastest way to append line or char to a buffer

2006-08-28 Thread Brad Beveridge

On 28/08/06, Bram Moolenaar <[EMAIL PROTECTED]> wrote:


Brad Beveridge wrote:

> Hi, sorry for all the trouble :)  I'm having redraw issues, where
> running this code to append chars is causing strange problems.
> The scenario is this (always using the code below for char output):
> 1) Write a char to a buffer (line1)
> 2) Write a newline (line 2)
> 3) Move the cursor to the bottom of the buffer (line2 empty)
> 4) Write another Char (appears in line2)
> 5) Press Ctrl-L
> 6) Notice that line1 has vanished.
>
> moving the cursor to the new blank line at the bottom of the line is
> critical here.  I'm sure that I'm doing something wrong, but I really
> can't figure it out.
> As a side note, it feels very clumsy to have to manually call "changed
> line" functions when calling ml_* funcs - is there some notes I can
> read about why this is?

The screen updating code doesn't want to redraw everything all the time.
Thus you must somehow specify what text got changed/inserted/deleted.
If you don't do that you might indeed see redraw problems that go away
when using CTRL-L.

Actually, it is just the opposite - the screen looks fine UNTIL I
press CTRL-L :)



You are doing low level stuff here, thus you must take care of all these
things yourself.

I guess that is fair enough.







Do you save text for undo somewhere?  That should be done for every
change that is being made, otherwise undo won't work.


For right now I'm not concerned about undo.  Probably later I'll add
undo at the per-line level.

Cheers
Brad


Re: Fastest way to append line or char to a buffer

2006-08-28 Thread Bram Moolenaar

Brad Beveridge wrote:

> Hi, sorry for all the trouble :)  I'm having redraw issues, where
> running this code to append chars is causing strange problems.
> The scenario is this (always using the code below for char output):
> 1) Write a char to a buffer (line1)
> 2) Write a newline (line 2)
> 3) Move the cursor to the bottom of the buffer (line2 empty)
> 4) Write another Char (appears in line2)
> 5) Press Ctrl-L
> 6) Notice that line1 has vanished.
> 
> moving the cursor to the new blank line at the bottom of the line is
> critical here.  I'm sure that I'm doing something wrong, but I really
> can't figure it out.
> As a side note, it feels very clumsy to have to manually call "changed
> line" functions when calling ml_* funcs - is there some notes I can
> read about why this is?

The screen updating code doesn't want to redraw everything all the time.
Thus you must somehow specify what text got changed/inserted/deleted.
If you don't do that you might indeed see redraw problems that go away
when using CTRL-L.

You are doing low level stuff here, thus you must take care of all these
things yourself.

> Anyhow, here is the code I'm using to put chars in a buffer - I really
> appreciate any thoughts, this feels so close to working, but I've
> spend several hours trying to get it right.  Very frustrating :)
> 
> Cheers
> Brad
> 
> static void vim_append_char (buf_T target_buf, char c)
> {
> static char string[2] = {0};
> buf_T *savebuf = curbuf;
> curbuf = target_buf;
> int start_line = curbuf->b_ml.ml_line_count;
> int lines_changed = 0;
> 
> string[0] = c;
> if (string[0] == '\n')
> {
> ml_append (start_line, "", 0, FALSE);
> lines_changed = 0;
> }
> else
> ml_append_string (start_line, string, -1);
> changed_lines (start_line, 0, start_line, lines_changed);
> 
> /* restore and return */
> curbuf = savebuf;
> }

Do you save text for undo somewhere?  That should be done for every
change that is being made, otherwise undo won't work.

-- 
hundred-and-one symptoms of being an internet addict:
250. You've given up the search for the "perfect woman" and instead,
 sit in front of the PC until you're just too tired to care.

 /// Bram Moolenaar -- [EMAIL PROTECTED] -- http://www.Moolenaar.net   \\\
///sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\download, build and distribute -- http://www.A-A-P.org///
 \\\help me help AIDS victims -- http://ICCF-Holland.org///


Re: Fastest way to append line or char to a buffer

2006-08-27 Thread Brad Beveridge

On 26/08/06, Brad Beveridge <[EMAIL PROTECTED]> wrote:



Cheers
Brad


Hi, sorry for all the trouble :)  I'm having redraw issues, where
running this code to append chars is causing strange problems.
The scenario is this (always using the code below for char output):
1) Write a char to a buffer (line1)
2) Write a newline (line 2)
3) Move the cursor to the bottom of the buffer (line2 empty)
4) Write another Char (appears in line2)
5) Press Ctrl-L
6) Notice that line1 has vanished.

moving the cursor to the new blank line at the bottom of the line is
critical here.  I'm sure that I'm doing something wrong, but I really
can't figure it out.
As a side note, it feels very clumsy to have to manually call "changed
line" functions when calling ml_* funcs - is there some notes I can
read about why this is?
Anyhow, here is the code I'm using to put chars in a buffer - I really
appreciate any thoughts, this feels so close to working, but I've
spend several hours trying to get it right.  Very frustrating :)

Cheers
Brad

static void vim_append_char (buf_T target_buf, char c)
{
   static char string[2] = {0};
   buf_T *savebuf = curbuf;
   curbuf = target_buf;
   int start_line = curbuf->b_ml.ml_line_count;
   int lines_changed = 0;

   string[0] = c;
   if (string[0] == '\n')
   {
   ml_append (start_line, "", 0, FALSE);
   lines_changed = 0;
   }
   else
   ml_append_string (start_line, string, -1);
   changed_lines (start_line, 0, start_line, lines_changed);

   /* restore and return */
   curbuf = savebuf;
}


Re: Fastest way to append line or char to a buffer

2006-08-22 Thread Brad Beveridge

On 22/08/06, Bram Moolenaar <[EMAIL PROTECTED]> wrote:






I understand.  It would be a bit more efficient if the new, empty line
that you add when a newline is encountered already has room for a
certain number of characters.

Ah, I see.  True, but since I don't know the code base that well I
didn't want to touch too much code all over the place.



> > Also, for appending to a different line than before you copy the line
> > twice.  You can avoid that by using vim_strnsave() instead of
> > vim_strsave() and reserving space for new characters right away.
>
> Yes, this is a slight inefficiency.  The main reason that I did this
> was that I wanted all the code to do with re-allocation in the same
> place, ie the next if block.  Looking at the code again now, the
> solution is probably to not copy in the "cache miss" code, where we
> flush - just do
> curbuf->b_ml.ml_line_ptr = ml_get(lnum);

I suppose that should work (didn't look at it carefully).

I might have a look later if this code can be used in certain
situations.  That should make some operations work faster, e.g. pasting
a large chunk of text into a terminal emulator.


I think it will work from the quick glance over it.  I can test it
more throughly tonight.  I'd love it if I made an actually useful
contrib to Vim - I love this editor, thanks for writing it!

Brad


Re: Fastest way to append line or char to a buffer

2006-08-22 Thread Bram Moolenaar

Brad Beveridge wrote:

> > I wonder how you create a new line.  Using the old mechanism you mostly
> > end up reallocating the line at the next insert.  Allocating a bit of
> > room to anticipate further appends would be more efficient.
> I'm sorry, I don't understand quite what you mean with that comment.
> Do you mean "if you only used ml_append_string, how do new lines ever
> get created?"  If you do mean that, then the answer is: new lines need
> to be created by an upper level function.  I have an upper level
> "append_char" function that is more or less:
> void append_char (buf, char) {
>   static uchar string[2] = {0};
>   curbuf = buf;
>   if (char == '\n')
>  ml_append // create a new line
>   else
>  {
> string[0] = char;
> ml_append_string (string)
> ...
> The reason that I didn't do new line creation in append_string is that
> you would need to check all incoming strings for newlines, the upper
> level layers can better do this check because they have more
> information about the incoming string - they could know it will never
> contain newlines.

I understand.  It would be a bit more efficient if the new, empty line
that you add when a newline is encountered already has room for a
certain number of characters.
 
> > Also, for appending to a different line than before you copy the line
> > twice.  You can avoid that by using vim_strnsave() instead of
> > vim_strsave() and reserving space for new characters right away.
> 
> Yes, this is a slight inefficiency.  The main reason that I did this
> was that I wanted all the code to do with re-allocation in the same
> place, ie the next if block.  Looking at the code again now, the
> solution is probably to not copy in the "cache miss" code, where we
> flush - just do
> curbuf->b_ml.ml_line_ptr = ml_get(lnum);

I suppose that should work (didn't look at it carefully).

I might have a look later if this code can be used in certain
situations.  That should make some operations work faster, e.g. pasting
a large chunk of text into a terminal emulator.

-- 
Some of the well know MS-Windows errors:
EMULTI  Multitasking attempted, system confused
EKEYBOARD   Keyboard locked, try getting out of this one!
EXPLAIN Unexplained error, please tell us what happened
EFUTURE Reserved for our future mistakes

 /// Bram Moolenaar -- [EMAIL PROTECTED] -- http://www.Moolenaar.net   \\\
///sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\download, build and distribute -- http://www.A-A-P.org///
 \\\help me help AIDS victims -- http://ICCF-Holland.org///


Re: Fastest way to append line or char to a buffer

2006-08-22 Thread Brad Beveridge

On 22/08/06, Bram Moolenaar <[EMAIL PROTECTED]> wrote:


Brad Beveridge wrote:




Thanks for making this patch.

No problem - it happened to be my particular itch :)


I wonder how you create a new line.  Using the old mechanism you mostly
end up reallocating the line at the next insert.  Allocating a bit of
room to anticipate further appends would be more efficient.

I'm sorry, I don't understand quite what you mean with that comment.
Do you mean "if you only used ml_append_string, how do new lines ever
get created?"  If you do mean that, then the answer is: new lines need
to be created by an upper level function.  I have an upper level
"append_char" function that is more or less:
void append_char (buf, char) {
 static uchar string[2] = {0};
 curbuf = buf;
 if (char == '\n')
ml_append // create a new line
 else
{
   string[0] = char;
   ml_append_string (string)
...
The reason that I didn't do new line creation in append_string is that
you would need to check all incoming strings for newlines, the upper
level layers can better do this check because they have more
information about the incoming string - they could know it will never
contain newlines.


Also, for appending to a different line than before you copy the line
twice.  You can avoid that by using vim_strnsave() instead of
vim_strsave() and reserving space for new characters right away.


Yes, this is a slight inefficiency.  The main reason that I did this
was that I wanted all the code to do with re-allocation in the same
place, ie the next if block.  Looking at the code again now, the
solution is probably to not copy in the "cache miss" code, where we
flush - just do
curbuf->b_ml.ml_line_ptr = ml_get(lnum);

Cheers
Brad


Re: Fastest way to append line or char to a buffer

2006-08-22 Thread Bram Moolenaar

Brad Beveridge wrote:

> The last code I posted was a little broken.  Here is a patch that
> appears (after a reasonable amount of testing) to work quite well for
> very quickly appending chars to a vim line.
> As I said, scripting language authors that use Vim output buffers as
> STDOUT style streams could use this to good advantage.

Thanks for making this patch.

I wonder how you create a new line.  Using the old mechanism you mostly
end up reallocating the line at the next insert.  Allocating a bit of
room to anticipate further appends would be more efficient.

Also, for appending to a different line than before you copy the line
twice.  You can avoid that by using vim_strnsave() instead of
vim_strsave() and reserving space for new characters right away.

-- 
hundred-and-one symptoms of being an internet addict:
192. Your boss asks you to "go fer" coffee and you come up with 235 FTP sites.

 /// Bram Moolenaar -- [EMAIL PROTECTED] -- http://www.Moolenaar.net   \\\
///sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\download, build and distribute -- http://www.A-A-P.org///
 \\\help me help AIDS victims -- http://ICCF-Holland.org///


Re: Fastest way to append line or char to a buffer

2006-08-20 Thread Brad Beveridge

The last code I posted was a little broken.  Here is a patch that
appears (after a reasonable amount of testing) to work quite well for
very quickly appending chars to a vim line.
As I said, scripting language authors that use Vim output buffers as
STDOUT style streams could use this to good advantage.

Cheers
Brad


append-char.patch.gz
Description: GNU Zip compressed data


Re: Fastest way to append line or char to a buffer

2006-08-17 Thread Brad Beveridge

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_Tlnum;
   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;
}


Re: Fastest way to append line or char to a buffer

2006-08-16 Thread Brad Beveridge

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


Re: Fastest way to append line or char to a buffer

2006-08-16 Thread Bram Moolenaar

Nikolai Weibull wrote:

> On 8/16/06, Bram Moolenaar <[EMAIL PROTECTED]> wrote:
> 
> > There are only a few operations that profit from a "gap" strategy.
> > Overall it gets much more complicated and inefficient.  You would have
> > to move the gap around for every change made.
> 
> Not quite true.  You'd have to move it around for every
> /length-altering/ change made (but non-length-altering changes work
> well without a gap as well).

Just about any change will potentially change the length.  Keep in mind
that changing a character may change the byte count for multi-byte
characters.

> And considering that insertion is the most common operation and that
> it's one of the operations that would benefit, it's a trade-off that
> may or may not benefit buffer modification as a whole.

Insertion is just one of the many operations.  And it's one that can be
put in a function used from many places, while other changes are much
more specific and require separate implementation.

> Still, I suppose the most common scenario for the most common
> operation is insertion at the end of a line, which I assume there /is/
> support for in Vim already, i.e., allocating some additional space for
> every loaded line so that one doesn't have to realloc() for every
> insertion.

Not really.  I don't think it makes sense to optimize for one of the
very many operations.  Keeping the code simple and reliable is much more
important.

> Remember: Emacs uses the gap strategy for the whole buffer, and I
> haven't seen this to be particularly inefficient.  The big problem is
> the continuity of the buffer in memory, which isn't much of a problem
> on a per-line basis.

I have never seen a reliable, real-world comparison of performance for
various strategies.  Only ones with so many assumptions that the result
becomes meaningless.  You quickly get to the situation that the outcome
mainly depends on the type of edits you test with.  The mechanism Vim
uses is probably too complex for scientific research anyway.

Optimizing for file loading is one thing that could still be done in Vim
and would probably improve performance.  Currently every line has to be
copied after it has been read.  I know it's possible to avoid that, but
quite a bit of work (esp. for testing, this code has to be very
reliable).  Since I don't hear remarks that loading a file is slow it's
not high on the priority list.

-- 
hundred-and-one symptoms of being an internet addict:
161. You get up before the sun rises to check your e-mail, and you
 find yourself in the very same chair long after the sun has set.

 /// Bram Moolenaar -- [EMAIL PROTECTED] -- http://www.Moolenaar.net   \\\
///sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\download, build and distribute -- http://www.A-A-P.org///
 \\\help me help AIDS victims -- http://ICCF-Holland.org///


Re: Fastest way to append line or char to a buffer

2006-08-16 Thread Nikolai Weibull

On 8/16/06, Bram Moolenaar <[EMAIL PROTECTED]> wrote:


There are only a few operations that profit from a "gap" strategy.
Overall it gets much more complicated and inefficient.  You would have
to move the gap around for every change made.


Not quite true.  You'd have to move it around for every
/length-altering/ change made (but non-length-altering changes work
well without a gap as well).  And considering that insertion is the
most common operation and that it's one of the operations that would
benefit, it's a trade-off that may or may not benefit buffer
modification as a whole.

Still, I suppose the most common scenario for the most common
operation is insertion at the end of a line, which I assume there /is/
support for in Vim already, i.e., allocating some additional space for
every loaded line so that one doesn't have to realloc() for every
insertion.

Remember: Emacs uses the gap strategy for the whole buffer, and I
haven't seen this to be particularly inefficient.  The big problem is
the continuity of the buffer in memory, which isn't much of a problem
on a per-line basis.

 nikolai


Re: Fastest way to append line or char to a buffer

2006-08-16 Thread Bram Moolenaar

Nikolai Weibull wrote:

> On 8/16/06, Bram Moolenaar <[EMAIL PROTECTED]> wrote:
> > Vim internally works linewise.  Appending a character means taking the
> > current line and replacing it with one that has the character appended.
> > If you keep adding characters to the same line you could do some
> > optimization to avoid having to allocate/free lines all the time.
> 
> Bram, have you ever given any thought to using a gap
> buffering-strategy for lines?  This would make many operations on long
> lines (a recurring issue discussed on this list) faster.  It will
> complicate the buffer handling a lot, though.

There are only a few operations that profit from a "gap" strategy.
Overall it gets much more complicated and inefficient.  You would have
to move the gap around for every change made.

-- 
hundred-and-one symptoms of being an internet addict:
155. You forget to eat because you're too busy surfing the net.

 /// Bram Moolenaar -- [EMAIL PROTECTED] -- http://www.Moolenaar.net   \\\
///sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\download, build and distribute -- http://www.A-A-P.org///
 \\\help me help AIDS victims -- http://ICCF-Holland.org///


Re: Fastest way to append line or char to a buffer

2006-08-16 Thread Nikolai Weibull

On 8/16/06, Bram Moolenaar <[EMAIL PROTECTED]> wrote:

Vim internally works linewise.  Appending a character means taking the
current line and replacing it with one that has the character appended.
If you keep adding characters to the same line you could do some
optimization to avoid having to allocate/free lines all the time.


Bram, have you ever given any thought to using a gap
buffering-strategy for lines?  This would make many operations on long
lines (a recurring issue discussed on this list) faster.  It will
complicate the buffer handling a lot, though.

 nikolai


Re: Fastest way to append line or char to a buffer

2006-08-16 Thread Bram Moolenaar

Brad Beveridge wrote:

> I'm working with a Vim that has been patched to support ECL Lisp
> (http://wiki.alu.org/Vim_ECL).  Part of our project involves
> outputting potentially large amounts of data  to a buffer in a
> streaming fashion, ie always adding at the end.
> I think that I have worked out a reasonable way to append lines[1],
> but I can't see any obvious way to quickly append single chars to a
> buffer.
> Are there any functions like ml_append I can look to for this support?
>  How should I go about appending single chars very quickly?

Vim internally works linewise.  Appending a character means taking the
current line and replacing it with one that has the character appended.
If you keep adding characters to the same line you could do some
optimization to avoid having to allocate/free lines all the time.

-- 
hundred-and-one symptoms of being an internet addict:
151. You find yourself engaged to someone you've never actually met,
 except through e-mail.

 /// Bram Moolenaar -- [EMAIL PROTECTED] -- http://www.Moolenaar.net   \\\
///sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\download, build and distribute -- http://www.A-A-P.org///
 \\\help me help AIDS victims -- http://ICCF-Holland.org///