XTream timings

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

XTream timings

Nicolas Cellier
I have some green tests in current XTream (66% coverage) and following
tiny benchmarks:

{
[(String new: 1000 withAll: $a) readStream upToEnd] bench.
[(String new: 1000 withAll: $a) readXtream upToEnd] bench.
} #('85003.799240152 per second.' '86181.1637672465 per second.')

{
[(String new: 1000 withAll: $a) readStream upTo: $b] bench.
[(String new: 1000 withAll: $a) readXtream upTo: $b] bench.
} #('63099.5800839832 per second.' '63701.0597880424 per second.')

{
[(String new: 1000 withAll: $a) readStream upToAnyOf: (CharacterSet
crlf)] bench.
[(String new: 1000 withAll: $a) readXtream upToAnyOf: (CharacterSet
crlf)] bench.
} #('927.414517096581 per second.' '57677.4645070986 per second.')

{
[| tmp | tmp := (String new: 1000 withAll: $a) readStream. [tmp
next==nil] whileFalse] bench.
[| tmp | tmp := (String new: 1000 withAll: $a) readXtream. [tmp
next==nil] whileFalse] bench.
} #('9670.46590681864 per second.' '3932.41351729654 per second.')

{
[(String new: 1000 withAll: $a) readStream upToAll: 'ab'] bench.
[(String new: 1000 withAll: $a) readXtream upToAll: 'ab'] bench.
} #('495.8016793282687 per second.' '604.679064187163 per second.')

On String, the only case we loose by a factor 2.5 is #next because
there is no primitive...
Otherwise performances are similar except upToAnyOf: which was not
optimized in readStream

For StandardFileStream, the difference is... large

{
[| tmp | tmp := (StandardFileStream readOnlyFileNamed: (SourceFiles
at: 2) name). [tmp next==nil] whileFalse. tmp close] timeToRun.
[| tmp | tmp := (StandardFileStream readOnlyFileNamed: (SourceFiles
at: 2) name) readXtream buffered. [tmp next==nil] whileFalse. tmp
close] timeToRun.
} #(27008 1947)

{
[| tmp | tmp := (StandardFileStream readOnlyFileNamed: (SourceFiles
at: 2) name) ascii.
        [tmp upTo: Character cr. tmp atEnd] whileFalse. tmp close] timeToRun.
[| tmp atEnd | tmp := (StandardFileStream readOnlyFileNamed:
(SourceFiles at: 2) name) readXtream ascii buffered.
        [tmp upTo: Character cr. tmp atEnd] whileFalse. tmp close] timeToRun.
} #(4285 821)

{
[| tmp | tmp := (StandardFileStream readOnlyFileNamed: (SourceFiles
at: 2) name) ascii.
        [tmp upToAnyOf: (CharacterSet crlf). tmp atEnd] whileFalse. tmp
close] timeToRun.
[| tmp atEnd | tmp := (StandardFileStream readOnlyFileNamed:
(SourceFiles at: 2) name) readXtream ascii buffered.
        [tmp upToAnyOf: (CharacterSet crlf). tmp atEnd] whileFalse. tmp
close] timeToRun.
} #(75895 1003)

... especially when you hit one not optimized method like upToAnyOf: ...

For MultiByteFileStream, the difference is poor, for two reasons:
1) because I used byte per byte read/write without exploiting
squeakToUtf8 trick from Andreas
This is because of the naive implementation using Block Wrapper
Stream. A ConverterReadXtream subclass would perform much better.
2) because stupid TextConverter insist on sending isBinary at each
read/write, and that costs me 50% of execution time, not speaking of
useless ugly basicNext and co

Beside, a Block Wrapper Stream has bad properties like being not
peekable, not positionable, does not knows its size and does not knows
if atEnd without consuming an element... It also have strange It
should be wrapped itself which would cause additional costs ! Or it
could also be buffered...

[| tmp | tmp := (MultiByteFileStream readOnlyFileNamed: (SourceFiles
at: 2) name) ascii; wantsLineEndConversion: false; converter:
UTF8TextConverter new.
        1 to: 10000 do: [:i | tmp upTo: Character cr]. tmp close] timeToRun.
[| tmp atEnd | tmp := (StandardFileStream readOnlyFileNamed:
(SourceFiles at: 2) name) readXtream ascii buffered decodeWith:
UTF8TextConverter new.
        1 to: 10000 do: [:i | tmp upTo: Character cr]. tmp close] timeToRun.
} #(1668 1112)

I expect a huge speed up from a cleaned TextConverter and a
ConverterReadXtream subclass, around x10
A bit more work... also to port an InflateXtream / DeflateXtream.

Nicolas

Reply | Threaded
Open this post in threaded view
|

Re: XTream timings

Jason Rogers-4
Would it be possible to have Xtreams on STDIN, STDOUT, STDERR? Of
would that require use of OSProcess?

On Fri, Dec 4, 2009 at 10:37 AM, Nicolas Cellier
<[hidden email]> wrote:

> I have some green tests in current XTream (66% coverage) and following
> tiny benchmarks:
>
> {
> [(String new: 1000 withAll: $a) readStream upToEnd] bench.
> [(String new: 1000 withAll: $a) readXtream upToEnd] bench.
> } #('85003.799240152 per second.' '86181.1637672465 per second.')
>
> {
> [(String new: 1000 withAll: $a) readStream upTo: $b] bench.
> [(String new: 1000 withAll: $a) readXtream upTo: $b] bench.
> } #('63099.5800839832 per second.' '63701.0597880424 per second.')
>
> {
> [(String new: 1000 withAll: $a) readStream upToAnyOf: (CharacterSet
> crlf)] bench.
> [(String new: 1000 withAll: $a) readXtream upToAnyOf: (CharacterSet
> crlf)] bench.
> } #('927.414517096581 per second.' '57677.4645070986 per second.')
>
> {
> [| tmp | tmp := (String new: 1000 withAll: $a) readStream. [tmp
> next==nil] whileFalse] bench.
> [| tmp | tmp := (String new: 1000 withAll: $a) readXtream. [tmp
> next==nil] whileFalse] bench.
> } #('9670.46590681864 per second.' '3932.41351729654 per second.')
>
> {
> [(String new: 1000 withAll: $a) readStream upToAll: 'ab'] bench.
> [(String new: 1000 withAll: $a) readXtream upToAll: 'ab'] bench.
> } #('495.8016793282687 per second.' '604.679064187163 per second.')
>
> On String, the only case we loose by a factor 2.5 is #next because
> there is no primitive...
> Otherwise performances are similar except upToAnyOf: which was not
> optimized in readStream
>
> For StandardFileStream, the difference is... large
>
> {
> [| tmp | tmp := (StandardFileStream readOnlyFileNamed: (SourceFiles
> at: 2) name). [tmp next==nil] whileFalse. tmp close] timeToRun.
> [| tmp | tmp := (StandardFileStream readOnlyFileNamed: (SourceFiles
> at: 2) name) readXtream buffered. [tmp next==nil] whileFalse. tmp
> close] timeToRun.
> } #(27008 1947)
>
> {
> [| tmp | tmp := (StandardFileStream readOnlyFileNamed: (SourceFiles
> at: 2) name) ascii.
>        [tmp upTo: Character cr. tmp atEnd] whileFalse. tmp close] timeToRun.
> [| tmp atEnd | tmp := (StandardFileStream readOnlyFileNamed:
> (SourceFiles at: 2) name) readXtream ascii buffered.
>        [tmp upTo: Character cr. tmp atEnd] whileFalse. tmp close] timeToRun.
> } #(4285 821)
>
> {
> [| tmp | tmp := (StandardFileStream readOnlyFileNamed: (SourceFiles
> at: 2) name) ascii.
>        [tmp upToAnyOf: (CharacterSet crlf). tmp atEnd] whileFalse. tmp
> close] timeToRun.
> [| tmp atEnd | tmp := (StandardFileStream readOnlyFileNamed:
> (SourceFiles at: 2) name) readXtream ascii buffered.
>        [tmp upToAnyOf: (CharacterSet crlf). tmp atEnd] whileFalse. tmp
> close] timeToRun.
> } #(75895 1003)
>
> ... especially when you hit one not optimized method like upToAnyOf: ...
>
> For MultiByteFileStream, the difference is poor, for two reasons:
> 1) because I used byte per byte read/write without exploiting
> squeakToUtf8 trick from Andreas
> This is because of the naive implementation using Block Wrapper
> Stream. A ConverterReadXtream subclass would perform much better.
> 2) because stupid TextConverter insist on sending isBinary at each
> read/write, and that costs me 50% of execution time, not speaking of
> useless ugly basicNext and co
>
> Beside, a Block Wrapper Stream has bad properties like being not
> peekable, not positionable, does not knows its size and does not knows
> if atEnd without consuming an element... It also have strange It
> should be wrapped itself which would cause additional costs ! Or it
> could also be buffered...
>
> [| tmp | tmp := (MultiByteFileStream readOnlyFileNamed: (SourceFiles
> at: 2) name) ascii; wantsLineEndConversion: false; converter:
> UTF8TextConverter new.
>        1 to: 10000 do: [:i | tmp upTo: Character cr]. tmp close] timeToRun.
> [| tmp atEnd | tmp := (StandardFileStream readOnlyFileNamed:
> (SourceFiles at: 2) name) readXtream ascii buffered decodeWith:
> UTF8TextConverter new.
>        1 to: 10000 do: [:i | tmp upTo: Character cr]. tmp close] timeToRun.
> } #(1668 1112)
>
> I expect a huge speed up from a cleaned TextConverter and a
> ConverterReadXtream subclass, around x10
> A bit more work... also to port an InflateXtream / DeflateXtream.
>
> Nicolas
>
>



--
Jason Rogers

"I am crucified with Christ: nevertheless I live;
yet not I, but Christ liveth in me: and the life
which I now live in the flesh I live by the faith of
the Son of God, who loved me, and gave
himself for me."
    Galatians 2:20

Reply | Threaded
Open this post in threaded view
|

Re: XTream timings

David T. Lewis
In reply to this post by Nicolas Cellier
On Fri, Dec 04, 2009 at 04:37:09PM +0100, Nicolas Cellier wrote:
>
> For StandardFileStream, the difference is... large
>

Indeed!

:)
 

Reply | Threaded
Open this post in threaded view
|

Re: XTream timings

David T. Lewis
In reply to this post by Jason Rogers-4
On Fri, Dec 04, 2009 at 11:58:28AM -0500, Jason Rogers wrote:
> Would it be possible to have Xtreams on STDIN, STDOUT, STDERR? Of
> would that require use of OSProcess?

On most unix boxes you should be able to use /dev/stdout as if it
were a file, thus OSProcess should not be necessary. You'll need
OSProcess if you want to set stdin for non-blocking reads to prevent
blocking the VM.

Dave
 

Reply | Threaded
Open this post in threaded view
|

Re: XTream timings

Jason Rogers-4
Thanks.

On Fri, Dec 4, 2009 at 12:28 PM, David T. Lewis <[hidden email]> wrote:

> On Fri, Dec 04, 2009 at 11:58:28AM -0500, Jason Rogers wrote:
>> Would it be possible to have Xtreams on STDIN, STDOUT, STDERR? Of
>> would that require use of OSProcess?
>
> On most unix boxes you should be able to use /dev/stdout as if it
> were a file, thus OSProcess should not be necessary. You'll need
> OSProcess if you want to set stdin for non-blocking reads to prevent
> blocking the VM.
>
> Dave
>
>
>



--
Jason Rogers

"I am crucified with Christ: nevertheless I live;
yet not I, but Christ liveth in me: and the life
which I now live in the flesh I live by the faith of
the Son of God, who loved me, and gave
himself for me."
    Galatians 2:20

Reply | Threaded
Open this post in threaded view
|

Re: XTream timings

Nicolas Cellier
In reply to this post by David T. Lewis
2009/12/4 David T. Lewis <[hidden email]>:

> On Fri, Dec 04, 2009 at 11:58:28AM -0500, Jason Rogers wrote:
>> Would it be possible to have Xtreams on STDIN, STDOUT, STDERR? Of
>> would that require use of OSProcess?
>
> On most unix boxes you should be able to use /dev/stdout as if it
> were a file, thus OSProcess should not be necessary. You'll need
> OSProcess if you want to set stdin for non-blocking reads to prevent
> blocking the VM.
>
> Dave
>
>
>

Yes, it would be good to integrate async IO in Xtream, but later.

I thought adopting following protocol in Xtream for the core IO operations:

#readInto:startingAt:count: and #writeFrom:startingAt:count: are for
non blocking IO and answer the number of items read/written.
#next:into:startingAt: and #next:putAll:startingAt: are for blocking IO

For sure, there will be a little more work required if we want to
duplicate the whole protocol
#peek #next #next: #next:into: etc...
For now, I don't think it is necessary, especially if Eliot provide a
threaded VM to handle these blocking IO in a background native
thread...

Nicolas

Reply | Threaded
Open this post in threaded view
|

stdio

Bert Freudenberg
In reply to this post by David T. Lewis
On 04.12.2009, at 18:28, David T. Lewis wrote:
>
> On Fri, Dec 04, 2009 at 11:58:28AM -0500, Jason Rogers wrote:
>> Would it be possible to have Xtreams on STDIN, STDOUT, STDERR? Of
>> would that require use of OSProcess?
>
> On most unix boxes you should be able to use /dev/stdout as if it
> were a file, thus OSProcess should not be necessary. You'll need
> OSProcess if you want to set stdin for non-blocking reads to prevent
> blocking the VM.

Unfortunately, this does not work as reliably as actually using FDs 0, 1, and 2. I encountered at least one production system where I had to work around the issue on the VM level (*).

Since the VM maintainers didn't like my hack (which I can understand), maybe we could finally add the necessary primitives. There have been a couple proposals already. I'm not quite sure why none made it into the VM.

- Bert -

(*) http://dev.laptop.org/ticket/8194
Reply | Threaded
Open this post in threaded view
|

Re: stdio

Eliot Miranda-2
Hi Bert, David, Ian, John,

On Sat, Dec 5, 2009 at 3:36 PM, Bert Freudenberg <[hidden email]> wrote:
On 04.12.2009, at 18:28, David T. Lewis wrote:
>
> On Fri, Dec 04, 2009 at 11:58:28AM -0500, Jason Rogers wrote:
>> Would it be possible to have Xtreams on STDIN, STDOUT, STDERR? Of
>> would that require use of OSProcess?
>
> On most unix boxes you should be able to use /dev/stdout as if it
> were a file, thus OSProcess should not be necessary. You'll need
> OSProcess if you want to set stdin for non-blocking reads to prevent
> blocking the VM.

Unfortunately, this does not work as reliably as actually using FDs 0, 1, and 2. I encountered at least one production system where I had to work around the issue on the VM level (*).

Since the VM maintainers didn't like my hack (which I can understand), maybe we could finally add the necessary primitives. There have been a couple proposals already. I'm not quite sure why none made it into the VM.

- Bert -

(*) http://dev.laptop.org/ticket/8194

FWIW here's the code in the Teleplace VM, and some code to use them for StandardFileStream. 

In sqFileStdioHandles-ccode are implementations of sqFileStdioHandlesInto: for platforms/Cross/plugins/FilePlugin/sqFilePluginBasicPrims.c and platforms/win32/plugins/FilePlugin/sqWin32FilePrims.c

In  primitiveFileStdioHandles.st is the VMMaker code for the FilePlugin and the UnixOSProcessPlugin that uses sqFileStdioHandlesInto:.

In stdioHandles.st is code for StandardFileStream that allows the creation of streams on stdin stdout & stderr (untested on Win32).

HTH
Eliot



stdioHandles.st (5K) Download Attachment
primitiveFileStdioHandles.st (4K) Download Attachment
sqFileStdioHandles-ccode (5K) Download Attachment