[squeak-dev] XTream timings

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Fri Dec 4 15:37:09 UTC 2009


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



More information about the Squeak-dev mailing list