On 17 Nov 2013, at 12:49, Andres Valloud <avalloud@smalltalk.comcastbiz.net> wrote:
Well, maybe, although it's interesting to consider how many strings streams need to beat string concatenation. Moreover, streams aren't hyper efficient eitherâ¦
Yes, indeed. It also depends on what is being concatenated (constants vs objects). Quick and dirty (totally unscientific): [ 'foo', 'bar' ] bench. '4,650,000 per second.' [ '' join: #( 'foo' 'bar' ) ] bench. '814,000 per second.' [ String streamContents: [ :out | out nextPutAll: 'foo'; nextPutAll: 'bar' ] ] bench. '1,900,000 per second.' [ 'foo', 'bar', 'baz' ] bench. '2,470,000 per second.' [ '' join: #( 'foo' 'bar' 'baz' ) ] bench. '719,000 per second.' [ String streamContents: [ :out | out nextPutAll: 'foo'; nextPutAll: 'bar'; nextPutAll: 'baz' ] ] bench. '1,710,000 per second.' [ 'foo', 'bar', 'baz', 'foobar' ] bench. '2,030,000 per second.' [ '' join: #( 'foo' 'bar' 'baz' 'foobar' ) ] bench. '665,000 per second.' [ String streamContents: [ :out | out nextPutAll: 'foo'; nextPutAll: 'bar'; nextPutAll: 'baz'; nextPutAll: 'foobar' ] ] bench. '1,580,000 per second.' [ Date today asString, $- asString, Time now asString ] bench. '61,800 per second.' [ String streamContents: [ :out | out print: Date today; nextPut: $-; print: Time now ] ] bench. '71,700 per second.' Weâre only measuring execution speed, not memory allocation, which is important too. The length of the strings is a variable as well, of course. Furthermore, many #printOn: implementations are not very efficient while they should be. Conclusion, letâs be careful with a too simple advice. Sven
On 11/16/13 10:09 , btc@openinworld.com wrote:
Code Critic rule Optimization > String concatenation instead of streams says:
"Check for string concatenation inside some iteration message. Since string concatenation is O(n^2), it is better to use streaming since it is O(n) - assuming that n is large enough. As a general principal avoid , since the receiver is copied. Therefore chaining , messages will lead to multiple useless copies of the receiver."
That is, String streamContents: [:s | #('abc' 'def' 'ghi') do: [:each | s nextPutAll: each asString]]
should be used instead of... 'abc' , 'def' , 'ghi'.
However the first clutters the code. What about something like... { 'abc' . 'def' . 'ghi' } asStreamString where Collection>>asStreamString ^ String streamContents: [:s | self do: [:each | s nextPutAll: each asString]]
cheers -ben