[squeak-dev] Faster FileStream experiments

Igor Stasenko siguctua at gmail.com
Sat Nov 28 02:47:28 UTC 2009


2009/11/28 Levente Uzonyi <leves at elte.hu>:
> On Sat, 28 Nov 2009, Igor Stasenko wrote:
>
>> 2009/11/28 Eliot Miranda <eliot.miranda at gmail.com>:
>>>
>>>
>>> On Fri, Nov 27, 2009 at 4:40 PM, Igor Stasenko <siguctua at gmail.com>
>>> wrote:
>>>>
>>>> 2009/11/28 Nicolas Cellier <nicolas.cellier.aka.nice at gmail.com>:
>>>>>
>>>>> 2009/11/27 Eliot Miranda <eliot.miranda at gmail.com>:
>>>>>>
>>>>>> An approach I like is to add an endOfStreamValue inst var to Stream
>>>>>> and
>>>>>> answer its value when at end.  This way nil does not have to be the
>>>>>> endOfStreamValue, for example -1 might be much more convenient for a
>>>>>> binary
>>>>>> stream, and streams can answer nil without confusing their clients.
>>>>>>  atEnd
>>>>>> can be implemented as
>>>>>>     atEnd
>>>>>>         ^self peek = self endOfStreamValue
>>>>>> You can arrange to make streams raise an end-of-stream exception
>>>>>> instead of
>>>>>> the endOfStreamValue by using some convention on the contents of
>>>>>> endOfStreamValue, such as if it is == to the stream itself (although I
>>>>>> note
>>>>>> that in the Teleplace image the exception EndOfStrean is defined bit
>>>>>> not
>>>>>> used).
>>>>>>
>>>>>> Of course, stream primitives get in the way of adding inst vars to
>>>>>> stream
>>>>>> classes ;)
>>>>>> IMO this is a much more useful scheme than making nil the only
>>>>>> endOfStream
>>>>>> value.
>>>>>>
>>>>>
>>>>> Last time I proposed to have an inst var endOfStreamAction was here
>>>>>
>>>>>
>>>>> http://lists.gforge.inria.fr/pipermail/pharo-project/2009-June/009536.html
>>>>> .
>>>>> Abusing nil value -> nil, I could even let this inst var
>>>>> un-initialized and be backward compatible
>>>>> (initializing with a ValueHolder on nil would do as well)
>>>>>
>>>>
>>>> Nicolas, have you considered introducing methods which allow
>>>> graciously handle the end-of-stream while reading?
>>>> Something like:
>>>>
>>>> nextIfAtEnd: aBlock
>>>> and
>>>> next: number ifAtEnd: aBlock
>>>>
>>>>
>>>> then caller may choose to either write:
>>>>
>>>> char := stream nextIfAtEnd: [nil]
>>>>
>>>> or handle end of stream differently, like leaving the loop:
>>>>
>>>> char := stream nextIfAtEnd: [^ results]
>>>>
>>>> the benefit of such approach that code which reads the stream , don't
>>>> needs to additionally
>>>> test stream state (atEnd) in iteration between #next sends neither
>>>> requires some unique value (like nil) returned by #next
>>>> when reaching end of stream.
>>>
>>> IMO the block creation is too expensive for streams.  The defaultHandler
>>> approach for and EndOfStream exception is also too expensive.  The
>>> endOfStreamValue inst var is a nice trade-off between flexibility,
>>> efficiency and simplicity.  You can always write
>>>      [(value := stream next) ~~ stream endOfStreamValue] whileTrue:
>>>         [...do stuff...
>>>
>>
>> hmm, can you elaborate, at what point you see an expensive block creation?
>> A block closure is created once at compiling stage, and then passed as
>> any other object by reading it
>> from literal frame of method (and as well as , you can use 'stream
>
> In this case the block is copied and initialized every time you send
> #nextIfAtEnd:. It is only activated at the end of the stream, so most of the
> time it is just garbage.
>
ah, yes.. forgot about that.

Well, you can move the block out of the loop:
| block |

block := [ self foo ].

[ stream nextIfAtEnd: block .. ] repeat.

but of course, its not always possible and not first thought which
comes into mind when you using blocks when coding.

Btw, i think is good field for compiler/runtime optimizations - to
avoid excessive closure creation inside a loops/nested blocks.

> Levente
>
>> nextIfAtEnd: nil' , right?). And only if its going to be activated (by
>> sending #value), a corresponding block context is created in order to
>> evaluate the block. But it happens only when you reaching the end of
>> stream.
>>
>> It is more expensive because of passing extra argument, i.e. use
>> #nextIfAtEnd: instead of #next , but not because of passing block,
>> IMO.
>>
>>>>
>>>>> Nicolas
>>>>>
>>>>
>>>>
>>>> --
>>>> Best regards,
>>>> Igor Stasenko AKA sig.
>>>>
>>
>>
>> --
>> Best regards,
>> Igor Stasenko AKA sig.
>>
>
>
>
>



-- 
Best regards,
Igor Stasenko AKA sig.



More information about the Squeak-dev mailing list