On Wed, 8 Dec 2010, Sven Van Caekenberghe wrote:
On 08 Dec 2010, at 00:25, Levente Uzonyi wrote:Thanks for the explanation, some quick and dirty buffering makes a huge difference: [ FileStream fileNamed: '/tmp/numbers.txt' do: [ :fileStream | 1000 timesRepeat: [ fileStream nextPutAll: (String streamContents: [ :stream | 100 timesRepeat: [ stream print: 100 atRandom; space ] ]) ] ] ] timeToRun. 159 Still, the asymmetry is a bit strange. Can't the side effects be dealt with using #flush ?Lets go back in time. A year ago there was no read buffering (Pharo 1.0 was not released, Squeak 3.10.2 was out) and reading from a file was as slow as writing is currently. Read buffering could be added transparently, so it could give a huge speed improvement to all existing code. Write buffering could be done the same way, but it would break code, because currently a write is immediately done, while with buffering it wouldn't be. Some files would be written only when the finalization process closes the file. The solution for this could be automatic flushing on each write, which could be turned off by a method. But that would be the same as not using write buffering at all. But with the same effort you could use another stream implementation, that does write buffering. And write buffering can't be used to speed up existing code without reviewing it.Thanks again for the explanation. OK, I tried writing my own buffered write stream class: [ FileStream fileNamed: '/tmp/numbers.txt' do: [ :fileStream | | bufferedStream | bufferedStream := ZnBufferedWriteStream on: fileStream. 100000 timesRepeat: [ bufferedStream print: 100 atRandom; space ]. bufferedStream flush ] ] timeToRun. 165 That wasn' too hard. And indeed, it is necessary to manually send #flush or #close to force the buffer out. But I do not completely agree with the fact that it would be that much work. Stream>>#flush is already a no-op. Adding it to #streamContents: and some others can not be that much work. In fact, SocketStream does already do both input and output buffering (and thus requires #flush or #close), so would potentially fail in certain situations according to your reasoning. No ?
It would be much work to add the write buffering to StandardFileStream (it should also work with MultiByteFileStream) and fix all places in the image, that use StandardFileStream or MultiByteFileStream for writing to a file. I don't get how #streamContents: could be used to send #flush. That's a method of SequenceableCollection IIRC. SocketStream is unrelated here, because it doesn't write to files and buffering was always implemented in it AFAIK.
Levente
Sven
