> I've been tracking IOBuffer extensions back to String.Buffer, I'll present
> what I have shortly.

> I suspect (but benchmarks will have to tell) that the String.Buffer
> implementation is not significantly slower than the current IOBuffer
> one (whilst supporting the full range of character widths).

Well. You have some minor optimizations to do:

|  int perf(object buffer)
|  {
|    buffer->add("11");
|    for(int i=0;i<10000; i++ )
|    {
|        int l;
|        if( buffer->cut )
|        {
|           l = (buffer[0]<<8) | buffer[1];
|           buffer->cut(0,2,1);
|        }
|        else
|       l = buffer->read_int(2);
|       buffer->add(random_string(l));
|       return sizeof(buffer);
|     }
|  }

> perf( String.Buffer() );
Result 2: 325250971
Compilation: 624ns, Execution: 144.86s
> perf( Stdio.IOBuffer() );
Result 3: 328787331
Compilation: 639ns, Execution: 194.06ms

(note that the length differs due to random_string)

However, reviewing the IOBuffer interface, I wonder about the
following issues:

> - Isn't it prudent to drop set_error_mode() and simply implement
>   this functionality (the throw()) using a custom range_error()
>   override?

Well. That would work, yes, I just simply did not remove the old
version of throwing errors since it would most often be used using the
simply buff->set_error_mode(1) when doing sub-parsing as I showed in
the documentation for set_error_mode.

The need to do rather complex sub-classing for that common usecase
seemed somewhat pointless.


> - Why insist on lock()ing the buffer when subbuffers are active?
>   Couldn't the code figure out by itself when a subbuffer exists
>   and then decide on-demand and automatically when a copy needs to be made
>   to transparently support the desired operation?

Not really, since the subbuffer only contains a pointer directly into
the memory area of the main buffer, if the main buffer changes that
using realloc or malloc it would be invalid, this could of course be
fixed by adding a list of subbuffers to the main buffer, but then you
run into issues with refcounting and such. Since the usecase where you
have a subbuffer active and want to modify the main buffer is rather
uncommon I thought it was OK that you have to call trim() on the
subbuffer to do that.


> Why not return IOBuffers practically everywhere, and then let the
> caller decide when and if to cast them to a string?  It gets rid of
> excessive method diversification due to there needing to be a string
> and a buffer returning one.  Returning a buffer is cheap, it doesn't
> copy the content.

Well, there is about a factor of 3 performance difference:

> string perf2(object b) { while( b->read(1) ); }
> string perf3(object b) { while( b->read_buffer(1) ); }


> perf2(Stdio.IOBuffer(mb100));
Result 5: 0
Compilation: 664ns, Execution: 92.19ms

> perf3(Stdio.IOBuffer(mb100));
Result 6: 0
Compilation: 680ns, Execution: 173.68ms

Since that does not include the cast, which should be about as fast as
the first read, it becomes about 3x slower.

And most of the time you actually want the string version, not the
buffer version.

-- 
Stephen.
  • IOBuffer vs. Buffe... Stephen R. van den Berg
    • Re: IOBuffer ... Stephen R. van den Berg
      • Re: IOBuf... Stephen R. van den Berg
        • Re: I... Per Hedbor () @ Pike (-) developers forum
      • Re: IOBuf... Stephen R. van den Berg
        • Re: I... Arne Goedeke
          • R... Stephen R. van den Berg
            • ... Per Hedbor () @ Pike (-) developers forum
              • ... Per Hedbor () @ Pike (-) developers forum
                • ... Per Hedbor () @ Pike (-) developers forum
                • ... Peter Bortas @ Pike developers forum
                • ... Per Hedbor () @ Pike (-) developers forum
                • ... Henrik Grubbström (Lysator) @ Pike (-) developers forum
                • ... Per Hedbor () @ Pike (-) developers forum

Reply via email to