EndOfStream - cruft?

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

EndOfStream - cruft?

Frank Shearar-3
EndOfStream has no references in the base image. It claims to be used
by ReadStream >> #next, but that's not true.

Time to die/deprecate?

frank

Reply | Threaded
Open this post in threaded view
|

Re: EndOfStream - cruft?

Chris Muller-3
What if a system needs to allow nil objects in a Stream of objects and
have it be treated as just another object in the stream rather than
the EOS marker?

So, maybe ReadStream>>#next _should_ be signaling EndOfStream, so the
sender of #next can know the difference in that scenario.  Since the
defaultAction is ^nil, presumably we could simply change #next to do
that with no breakage...

On Mon, Jul 22, 2013 at 9:02 AM, Frank Shearar <[hidden email]> wrote:
> EndOfStream has no references in the base image. It claims to be used
> by ReadStream >> #next, but that's not true.
>
> Time to die/deprecate?
>
> frank
>

Reply | Threaded
Open this post in threaded view
|

Re: EndOfStream - cruft?

Frank Shearar-3
I'm half-tempted to say "in that case the user should use Xtreams".
Because the weird behaviours around #next and #atEnd were pretty much
the main drivers behind it.

Do you use EndOfStream like this (to allow nil objects in a Stream of objects)?

frank

On 22 July 2013 17:09, Chris Muller <[hidden email]> wrote:

> What if a system needs to allow nil objects in a Stream of objects and
> have it be treated as just another object in the stream rather than
> the EOS marker?
>
> So, maybe ReadStream>>#next _should_ be signaling EndOfStream, so the
> sender of #next can know the difference in that scenario.  Since the
> defaultAction is ^nil, presumably we could simply change #next to do
> that with no breakage...
>
> On Mon, Jul 22, 2013 at 9:02 AM, Frank Shearar <[hidden email]> wrote:
>> EndOfStream has no references in the base image. It claims to be used
>> by ReadStream >> #next, but that's not true.
>>
>> Time to die/deprecate?
>>
>> frank
>>

Reply | Threaded
Open this post in threaded view
|

Re: EndOfStream - cruft?

Bob Arning-2
In reply to this post by Chris Muller-3
For the historically-obsessed,

Change Set:        069EOS-hh (really2192
EOS-hh)
Date:            18 May 2000
Author:            Helge Horch
Requires:        Squeak 2.8a

Modifies ReadStream>>next to signal an Error (EndOfStream) on attempts to read
at or beyond the end of the stream.  Thanks to Bob Arning (who is silently credited
in the stamps <g>), existing applications relying on seeing nils should not be
affected.

Change Set:        102ReadStreamUndo-sma (really 2272
ReadStreamUndo-sma)
Date:            1 June 2000
Author:            Stefan Matthias Aust

Undo #2192. The consequences of raising an exception for EOF during ReadStream>>next should be worked out in 2.9a but not for 2.8.


and, AFAIK, that was the end of that.

Cheers,
Bob

On 7/22/13 12:09 PM, Chris Muller wrote:
What if a system needs to allow nil objects in a Stream of objects and
have it be treated as just another object in the stream rather than
the EOS marker?

So, maybe ReadStream>>#next _should_ be signaling EndOfStream, so the
sender of #next can know the difference in that scenario.  Since the
defaultAction is ^nil, presumably we could simply change #next to do
that with no breakage...

On Mon, Jul 22, 2013 at 9:02 AM, Frank Shearar [hidden email] wrote:
EndOfStream has no references in the base image. It claims to be used
by ReadStream >> #next, but that's not true.

Time to die/deprecate?

frank





Reply | Threaded
Open this post in threaded view
|

Re: EndOfStream - cruft?

Chris Muller-3
Interesting, I wonder what the consequences were..

On Mon, Jul 22, 2013 at 11:22 AM, Bob Arning <[hidden email]> wrote:

> For the historically-obsessed,
>
> Change Set:        069EOS-hh (really2192EOS-hh)
> Date:            18 May 2000
> Author:            Helge Horch
> Requires:        Squeak 2.8a
>
> Modifies ReadStream>>next to signal an Error (EndOfStream) on attempts to
> read
> at or beyond the end of the stream.  Thanks to Bob Arning (who is silently
> credited
> in the stamps <g>), existing applications relying on seeing nils should not
> be
> affected.
>
> Change Set:        102ReadStreamUndo-sma (really 2272ReadStreamUndo-sma)
> Date:            1 June 2000
> Author:            Stefan Matthias Aust
>
> Undo #2192. The consequences of raising an exception for EOF during
> ReadStream>>next should be worked out in 2.9a but not for 2.8.
>
>
> and, AFAIK, that was the end of that.
>
> Cheers,
> Bob
>
> On 7/22/13 12:09 PM, Chris Muller wrote:
>
> What if a system needs to allow nil objects in a Stream of objects and
> have it be treated as just another object in the stream rather than
> the EOS marker?
>
> So, maybe ReadStream>>#next _should_ be signaling EndOfStream, so the
> sender of #next can know the difference in that scenario.  Since the
> defaultAction is ^nil, presumably we could simply change #next to do
> that with no breakage...
>
> On Mon, Jul 22, 2013 at 9:02 AM, Frank Shearar <[hidden email]>
> wrote:
>
> EndOfStream has no references in the base image. It claims to be used
> by ReadStream >> #next, but that's not true.
>
> Time to die/deprecate?
>
> frank
>
>
>
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: EndOfStream - cruft?

Chris Muller-3
In reply to this post by Frank Shearar-3
On Mon, Jul 22, 2013 at 11:16 AM, Frank Shearar <[hidden email]> wrote:
> I'm half-tempted to say "in that case the user should use Xtreams".
> Because the weird behaviours around #next and #atEnd were pretty much
> the main drivers behind it.
>
> Do you use EndOfStream like this (to allow nil objects in a Stream of objects)?

Not yet, but the other day when you were saying Set's don't need to
use nil as the special marker object, I agreed with you..

It is not too much of a stretch to imagine a situation:  e.g., a
time-lapse stream of data sampled at half-second intervals, but not
every "frame" has data, in which case simply nil is put onto the
stream.

With EndOfStream, we can simply "play back" the stream and it will be
a correct time-rendition of the data.  Without EndOfStream, we
couldn't.

Reply | Threaded
Open this post in threaded view
|

Re: EndOfStream - cruft?

Bob Arning-2
In reply to this post by Chris Muller-3
Well, I dug around a bit more. Seems Andreas was concerned about performance, although I did not see an issue. A week later it was rolled back.

Also in question was the correct superclass for EndOfStream. I just made the change in a 4.2 image and TestRunner is not happy with it being an Error. Make it an Exception and that problem goes away.

Cheers,
Bob

5/24/00     Re: RE: EndOfStream an Error???

On Wed, 24 May 2000 01:32:44 -0700 "Raab, Andreas" [hidden email] wrote:
>As it is right now, we're paying the
>price of an error recovery for something that happens quite often. There are
>many places where senders of #next rely returning nil quickly if at the end
>of the collection. Such as in #next:into:startingAt:, #nextChunk,
>#nextDelimited:, #peekFor: etc. With the changes we have a slowdown of
>approx. 500 for a simple test case like
>
>    | s |
>    s _ ReadStream on: Array new.
>    [1 to: 100000 do:[:i| s next]] timeToRun.
>
>While the slowdown is okay for an error recovery it is most definitely not
>okay for those users who do in fact rely on the opposite - which is a quick
>return of nil for a past end read operation. And as it stands ALL those
>users are affected by the modification.

Andreas,

Do you have an example that's a little more realistic? I was wondering what the effect would be on typical code, so I made a change to count the number of times that EndOfStream was actually signalled. Then I browsed around for a while and when I checked the number, it was still zero! So, I thought, filing in some code ought to do it. Nope - still zero. It wasn't until I evaluated "(ReadStream on: '1') nextChunk" that I actually got a hit. Hmm...

Cheers,
Bob
======================
5/24/00    Re: RE: EndOfStream an Error???

On Wed, 24 May 2000 12:32:32 -0700 "Raab, Andreas" [hidden email] wrote:
>What I do know, however, is that not too long ago we've integrated a change
>set (I think from Bert) which modified quite some places to use the
>#next/#isNil test instead of #atEnd. Which leads me to the assumption that
>there ought to be places in which a quick return might be really critical.

I think there is an important distinction here. If you have code like:

[s atEnd] whileFalse: [el _ s next. el whatEver]

then you will be sending #atEnd for each element in the stream and sending #next one less time. By changing that to

[(el _ s next) isNil] whileFalse: [el whatEver]

you are essentially substituting #isNil for #atEnd for every element. That can add up to substantial savings. The change to EndOfStream changes only the performance of the *last* #next while all the others (assuming there are elements in the stream) remain as fast as ever. There will clearly be some performance penalty, but the magnitude will depend on the number of elements processed before end of stream. If the typical case involves empty streams, then the cost will be quite high. If the typical stream processed as above has tens or hundreds (or more) of elements, then the cost of EndOfStream will be a much smaller fraction of the total processing time.

I think, as has already been suggested, it might be wise to back off this change until we resolve whether Error or Exception is a better place for it (I lean toward Exception, Notification or perhaps ErrorsForWhichTheDefaultActionIsUsuallyAcceptable rather than Error). Once that is decided, we can see if there are any noticeable performance hits, especially once EndOfStream is added to the other places where it can be detected (StandardFileStream>>next, e.g.).

Cheers,
Bob

==============================================



On 7/22/13 2:31 PM, Chris Muller wrote:
Interesting, I wonder what the consequences were..

On Mon, Jul 22, 2013 at 11:22 AM, Bob Arning [hidden email] wrote:
For the historically-obsessed,

Change Set:        069EOS-hh (really2192EOS-hh)
Date:            18 May 2000
Author:            Helge Horch
Requires:        Squeak 2.8a

Modifies ReadStream>>next to signal an Error (EndOfStream) on attempts to
read
at or beyond the end of the stream.  Thanks to Bob Arning (who is silently
credited
in the stamps <g>), existing applications relying on seeing nils should not
be
affected.

Change Set:        102ReadStreamUndo-sma (really 2272ReadStreamUndo-sma)
Date:            1 June 2000
Author:            Stefan Matthias Aust

Undo #2192. The consequences of raising an exception for EOF during
ReadStream>>next should be worked out in 2.9a but not for 2.8.


and, AFAIK, that was the end of that.

Cheers,
Bob

On 7/22/13 12:09 PM, Chris Muller wrote:

What if a system needs to allow nil objects in a Stream of objects and
have it be treated as just another object in the stream rather than
the EOS marker?

So, maybe ReadStream>>#next _should_ be signaling EndOfStream, so the
sender of #next can know the difference in that scenario.  Since the
defaultAction is ^nil, presumably we could simply change #next to do
that with no breakage...

On Mon, Jul 22, 2013 at 9:02 AM, Frank Shearar [hidden email]
wrote:

EndOfStream has no references in the base image. It claims to be used
by ReadStream >> #next, but that's not true.

Time to die/deprecate?

frank










Reply | Threaded
Open this post in threaded view
|

Re: EndOfStream - cruft?

Nicolas Cellier
For Andreas, the first problem was performance.
For me, there is another one: a Notification can get miss-interpreted at the wrong level (see post below).
I later started SqueaXTream to steal Stream composition idea from Xtreams and also have a versatile end of stream handling and let programmer choose whether he wants returning nil, another special object or get an Exception when a stream reaches its end.
See http://comments.gmane.org/gmane.comp.lang.smalltalk.squeak.general/139338

Sure, Xtreams supersedes all that stuff, so my experiments staled.


2013/7/22 Bob Arning <[hidden email]>
Well, I dug around a bit more. Seems Andreas was concerned about performance, although I did not see an issue. A week later it was rolled back.

Also in question was the correct superclass for EndOfStream. I just made the change in a 4.2 image and TestRunner is not happy with it being an Error. Make it an Exception and that problem goes away.

Cheers,
Bob

5/24/00     Re: RE: EndOfStream an Error???

On Wed, 24 May 2000 01:32:44 -0700 "Raab, Andreas" [hidden email] wrote:
>As it is right now, we're paying the
>price of an error recovery for something that happens quite often. There are
>many places where senders of #next rely returning nil quickly if at the end
>of the collection. Such as in #next:into:startingAt:, #nextChunk,
>#nextDelimited:, #peekFor: etc. With the changes we have a slowdown of
>approx. 500 for a simple test case like
>
>    | s |
>    s _ ReadStream on: Array new.
>    [1 to: 100000 do:[:i| s next]] timeToRun.
>
>While the slowdown is okay for an error recovery it is most definitely not
>okay for those users who do in fact rely on the opposite - which is a quick
>return of nil for a past end read operation. And as it stands ALL those
>users are affected by the modification.

Andreas,

Do you have an example that's a little more realistic? I was wondering what the effect would be on typical code, so I made a change to count the number of times that EndOfStream was actually signalled. Then I browsed around for a while and when I checked the number, it was still zero! So, I thought, filing in some code ought to do it. Nope - still zero. It wasn't until I evaluated "(ReadStream on: '1') nextChunk" that I actually got a hit. Hmm...

Cheers,
Bob
======================
5/24/00    Re: RE: EndOfStream an Error???

On Wed, 24 May 2000 12:32:32 -0700 "Raab, Andreas" [hidden email] wrote:
>What I do know, however, is that not too long ago we've integrated a change
>set (I think from Bert) which modified quite some places to use the
>#next/#isNil test instead of #atEnd. Which leads me to the assumption that
>there ought to be places in which a quick return might be really critical.

I think there is an important distinction here. If you have code like:

[s atEnd] whileFalse: [el _ s next. el whatEver]

then you will be sending #atEnd for each element in the stream and sending #next one less time. By changing that to

[(el _ s next) isNil] whileFalse: [el whatEver]

you are essentially substituting #isNil for #atEnd for every element. That can add up to substantial savings. The change to EndOfStream changes only the performance of the *last* #next while all the others (assuming there are elements in the stream) remain as fast as ever. There will clearly be some performance penalty, but the magnitude will depend on the number of elements processed before end of stream. If the typical case involves empty streams, then the cost will be quite high. If the typical stream processed as above has tens or hundreds (or more) of elements, then the cost of EndOfStream will be a much smaller fraction of the total processing time.

I think, as has already been suggested, it might be wise to back off this change until we resolve whether Error or Exception is a better place for it (I lean toward Exception, Notification or perhaps ErrorsForWhichTheDefaultActionIsUsuallyAcceptable rather than Error). Once that is decided, we can see if there are any noticeable performance hits, especially once EndOfStream is added to the other places where it can be detected (StandardFileStream>>next, e.g.).

Cheers,
Bob

==============================================



On 7/22/13 2:31 PM, Chris Muller wrote:
Interesting, I wonder what the consequences were..

On Mon, Jul 22, 2013 at 11:22 AM, Bob Arning [hidden email] wrote:
For the historically-obsessed,

Change Set:        069EOS-hh (really2192EOS-hh)
Date:            18 May 2000
Author:            Helge Horch
Requires:        Squeak 2.8a

Modifies ReadStream>>next to signal an Error (EndOfStream) on attempts to
read
at or beyond the end of the stream.  Thanks to Bob Arning (who is silently
credited
in the stamps <g>), existing applications relying on seeing nils should not
be
affected.

Change Set:        102ReadStreamUndo-sma (really 2272ReadStreamUndo-sma)
Date:            1 June 2000
Author:            Stefan Matthias Aust

Undo #2192. The consequences of raising an exception for EOF during
ReadStream>>next should be worked out in 2.9a but not for 2.8.


and, AFAIK, that was the end of that.

Cheers,
Bob

On 7/22/13 12:09 PM, Chris Muller wrote:

What if a system needs to allow nil objects in a Stream of objects and
have it be treated as just another object in the stream rather than
the EOS marker?

So, maybe ReadStream>>#next _should_ be signaling EndOfStream, so the
sender of #next can know the difference in that scenario.  Since the
defaultAction is ^nil, presumably we could simply change #next to do
that with no breakage...

On Mon, Jul 22, 2013 at 9:02 AM, Frank Shearar [hidden email]
wrote:

EndOfStream has no references in the base image. It claims to be used
by ReadStream >> #next, but that's not true.

Time to die/deprecate?

frank







    







Reply | Threaded
Open this post in threaded view
|

Re: EndOfStream - cruft?

Levente Uzonyi-2
In reply to this post by Frank Shearar-3
On Mon, 22 Jul 2013, Frank Shearar wrote:

> I'm half-tempted to say "in that case the user should use Xtreams".
> Because the weird behaviours around #next and #atEnd were pretty much
> the main drivers behind it.
>
> Do you use EndOfStream like this (to allow nil objects in a Stream of objects)?

Your question is misleading. nil can be in any stream, but #next will also
return nil, when the stream is #atEnd. If you know that your stream
doesn't have nils in it, then using #next is safe (and fast), otherwise
you should not rely on #next's return value to decide if it was a valid
read or not. That's what #atEnd is for.

Signaling an Exception when a ReadStream is #atEnd should not really cause
performance issues. It can only be a problem, when you are repeatedly
reading from short streams. Xtreams also uses this technique.


Levente

>
> frank
>
> On 22 July 2013 17:09, Chris Muller <[hidden email]> wrote:
>> What if a system needs to allow nil objects in a Stream of objects and
>> have it be treated as just another object in the stream rather than
>> the EOS marker?
>>
>> So, maybe ReadStream>>#next _should_ be signaling EndOfStream, so the
>> sender of #next can know the difference in that scenario.  Since the
>> defaultAction is ^nil, presumably we could simply change #next to do
>> that with no breakage...
>>
>> On Mon, Jul 22, 2013 at 9:02 AM, Frank Shearar <[hidden email]> wrote:
>>> EndOfStream has no references in the base image. It claims to be used
>>> by ReadStream >> #next, but that's not true.
>>>
>>> Time to die/deprecate?
>>>
>>> frank
>>>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: EndOfStream - cruft?

Bob Arning-2
Given that there might be a performance issue in some (rare) cases, but especially because of the potential for the wrong handler seeing the exception, another approach might be more acceptable. Some possibilities:

=======================
next

    <primitive: 65>
    position >= readLimit
        ifTrue: [^eos]    "a new instance variable the user can leave nil or set to preferred marker"
        ifFalse: [^collection at: (position := position + 1)]
=======================
nextIfNone: aBlock

    <primitive: 65>
    position >= readLimit
        ifTrue: [^aBlock value]
        ifFalse: [^collection at: (position := position + 1)]

=======================
nextOrEOS: endOfStreamMarker

    <primitive: 65>
    position >= readLimit
        ifTrue: [^endOfStreamMarker]
        ifFalse: [^collection at: (position := position + 1)]
=======================
nextOrSelf

    <primitive: 65>
    position >= readLimit
        ifTrue: [^self]    "if the stream is known not to contain itself, then self could be the marker"
        ifFalse: [^collection at: (position := position + 1)]
=======================

Cheers,
Bob

On 7/22/13 8:59 PM, Levente Uzonyi wrote:
On Mon, 22 Jul 2013, Frank Shearar wrote:

I'm half-tempted to say "in that case the user should use Xtreams".
Because the weird behaviours around #next and #atEnd were pretty much
the main drivers behind it.

Do you use EndOfStream like this (to allow nil objects in a Stream of objects)?

Your question is misleading. nil can be in any stream, but #next will also return nil, when the stream is #atEnd. If you know that your stream doesn't have nils in it, then using #next is safe (and fast), otherwise you should not rely on #next's return value to decide if it was a valid read or not. That's what #atEnd is for.

Signaling an Exception when a ReadStream is #atEnd should not really cause performance issues. It can only be a problem, when you are repeatedly reading from short streams. Xtreams also uses this technique.


Levente


frank

On 22 July 2013 17:09, Chris Muller [hidden email] wrote:
What if a system needs to allow nil objects in a Stream of objects and
have it be treated as just another object in the stream rather than
the EOS marker?

So, maybe ReadStream>>#next _should_ be signaling EndOfStream, so the
sender of #next can know the difference in that scenario.  Since the
defaultAction is ^nil, presumably we could simply change #next to do
that with no breakage...

On Mon, Jul 22, 2013 at 9:02 AM, Frank Shearar [hidden email] wrote:
EndOfStream has no references in the base image. It claims to be used
by ReadStream >> #next, but that's not true.

Time to die/deprecate?

frank








Reply | Threaded
Open this post in threaded view
|

Re: EndOfStream - cruft?

David T. Lewis
In reply to this post by Levente Uzonyi-2
On Tue, Jul 23, 2013 at 02:59:59AM +0200, Levente Uzonyi wrote:

> On Mon, 22 Jul 2013, Frank Shearar wrote:
>
> >I'm half-tempted to say "in that case the user should use Xtreams".
> >Because the weird behaviours around #next and #atEnd were pretty much
> >the main drivers behind it.
> >
> >Do you use EndOfStream like this (to allow nil objects in a Stream of
> >objects)?
>
> Your question is misleading. nil can be in any stream, but #next will also
> return nil, when the stream is #atEnd. If you know that your stream
> doesn't have nils in it, then using #next is safe (and fast), otherwise
> you should not rely on #next's return value to decide if it was a valid
> read or not. That's what #atEnd is for.

A bit off topic, but possibly worth mentioning - for OSProcess, I found
it useful to make an additional distinction between #atEnd (nothing more
available right now) versus #atEndOfFile (nothing more available on the
stream ever because the source is closed and we have read all available
elements from the stream).

Thus you can read #upToEnd to obtain all of the data currently available in
a stream (e.g. a stream on the reader end of an OS pipe), and you can read
#upToEndOfFile to wait for all data on the stream until the writer of that
stream is known to be done writing to it.

Dave


Reply | Threaded
Open this post in threaded view
|

Re: EndOfStream - cruft?

Frank Shearar-3
On 23 July 2013 03:08, David T. Lewis <[hidden email]> wrote:

> On Tue, Jul 23, 2013 at 02:59:59AM +0200, Levente Uzonyi wrote:
>> On Mon, 22 Jul 2013, Frank Shearar wrote:
>>
>> >I'm half-tempted to say "in that case the user should use Xtreams".
>> >Because the weird behaviours around #next and #atEnd were pretty much
>> >the main drivers behind it.
>> >
>> >Do you use EndOfStream like this (to allow nil objects in a Stream of
>> >objects)?
>>
>> Your question is misleading. nil can be in any stream, but #next will also
>> return nil, when the stream is #atEnd. If you know that your stream
>> doesn't have nils in it, then using #next is safe (and fast), otherwise
>> you should not rely on #next's return value to decide if it was a valid
>> read or not. That's what #atEnd is for.
>
> A bit off topic, but possibly worth mentioning - for OSProcess, I found
> it useful to make an additional distinction between #atEnd (nothing more
> available right now) versus #atEndOfFile (nothing more available on the
> stream ever because the source is closed and we have read all available
> elements from the stream).
>
> Thus you can read #upToEnd to obtain all of the data currently available in
> a stream (e.g. a stream on the reader end of an OS pipe), and you can read
> #upToEndOfFile to wait for all data on the stream until the writer of that
> stream is known to be done writing to it.

Since it sounds like people might want to use EndOfStream and alter
ReadStream, I've just pushed EndOfStream into the Collection-Streams
package.

This morning's rash of commits empties Exceptions completely. All the
Exceptions now live close(r) to the classes that make use of them.

frank

> Dave
>
>

Reply | Threaded
Open this post in threaded view
|

Re: EndOfStream - cruft?

Chris Muller-3
In reply to this post by Bob Arning-2
Great thread!  This is how Squeak has become as great as it is today;
by careful consideration and deliberation from multiple, experienced
viewpoints.  Thanks, Bob, for posting Andreas' detailed and thoughtful
response, it reminds me how much this community misses him and his
contributions.

On Mon, Jul 22, 2013 at 2:01 PM, Bob Arning <[hidden email]> wrote:

> Well, I dug around a bit more. Seems Andreas was concerned about
> performance, although I did not see an issue. A week later it was rolled
> back.
>
> Also in question was the correct superclass for EndOfStream. I just made the
> change in a 4.2 image and TestRunner is not happy with it being an Error.
> Make it an Exception and that problem goes away.
>
> Cheers,
> Bob
>
> 5/24/00     Re: RE: EndOfStream an Error???
>
> On Wed, 24 May 2000 01:32:44 -0700 "Raab, Andreas" <[hidden email]>
> wrote:
>>As it is right now, we're paying the
>>price of an error recovery for something that happens quite often. There
>> are
>>many places where senders of #next rely returning nil quickly if at the end
>>of the collection. Such as in #next:into:startingAt:, #nextChunk,
>>#nextDelimited:, #peekFor: etc. With the changes we have a slowdown of
>>approx. 500 for a simple test case like
>>
>>    | s |
>>    s _ ReadStream on: Array new.
>>    [1 to: 100000 do:[:i| s next]] timeToRun.
>>
>>While the slowdown is okay for an error recovery it is most definitely not
>>okay for those users who do in fact rely on the opposite - which is a quick
>>return of nil for a past end read operation. And as it stands ALL those
>>users are affected by the modification.
>
> Andreas,
>
> Do you have an example that's a little more realistic? I was wondering what
> the effect would be on typical code, so I made a change to count the number
> of times that EndOfStream was actually signalled. Then I browsed around for
> a while and when I checked the number, it was still zero! So, I thought,
> filing in some code ought to do it. Nope - still zero. It wasn't until I
> evaluated "(ReadStream on: '1') nextChunk" that I actually got a hit. Hmm...
>
> Cheers,
> Bob
> ======================
> 5/24/00    Re: RE: EndOfStream an Error???
>
> On Wed, 24 May 2000 12:32:32 -0700 "Raab, Andreas" <[hidden email]>
> wrote:
>>What I do know, however, is that not too long ago we've integrated a change
>>set (I think from Bert) which modified quite some places to use the
>>#next/#isNil test instead of #atEnd. Which leads me to the assumption that
>>there ought to be places in which a quick return might be really critical.
>
> I think there is an important distinction here. If you have code like:
>
> [s atEnd] whileFalse: [el _ s next. el whatEver]
>
> then you will be sending #atEnd for each element in the stream and sending
> #next one less time. By changing that to
>
> [(el _ s next) isNil] whileFalse: [el whatEver]
>
> you are essentially substituting #isNil for #atEnd for every element. That
> can add up to substantial savings. The change to EndOfStream changes only
> the performance of the *last* #next while all the others (assuming there are
> elements in the stream) remain as fast as ever. There will clearly be some
> performance penalty, but the magnitude will depend on the number of elements
> processed before end of stream. If the typical case involves empty streams,
> then the cost will be quite high. If the typical stream processed as above
> has tens or hundreds (or more) of elements, then the cost of EndOfStream
> will be a much smaller fraction of the total processing time.
>
> I think, as has already been suggested, it might be wise to back off this
> change until we resolve whether Error or Exception is a better place for it
> (I lean toward Exception, Notification or perhaps
> ErrorsForWhichTheDefaultActionIsUsuallyAcceptable rather than Error). Once
> that is decided, we can see if there are any noticeable performance hits,
> especially once EndOfStream is added to the other places where it can be
> detected (StandardFileStream>>next, e.g.).
>
> Cheers,
> Bob
>
> ==============================================
>
>
>
> On 7/22/13 2:31 PM, Chris Muller wrote:
>
> Interesting, I wonder what the consequences were..
>
> On Mon, Jul 22, 2013 at 11:22 AM, Bob Arning <[hidden email]> wrote:
>
> For the historically-obsessed,
>
> Change Set:        069EOS-hh (really2192EOS-hh)
> Date:            18 May 2000
> Author:            Helge Horch
> Requires:        Squeak 2.8a
>
> Modifies ReadStream>>next to signal an Error (EndOfStream) on attempts to
> read
> at or beyond the end of the stream.  Thanks to Bob Arning (who is silently
> credited
> in the stamps <g>), existing applications relying on seeing nils should not
> be
> affected.
>
> Change Set:        102ReadStreamUndo-sma (really 2272ReadStreamUndo-sma)
> Date:            1 June 2000
> Author:            Stefan Matthias Aust
>
> Undo #2192. The consequences of raising an exception for EOF during
> ReadStream>>next should be worked out in 2.9a but not for 2.8.
>
>
> and, AFAIK, that was the end of that.
>
> Cheers,
> Bob
>
> On 7/22/13 12:09 PM, Chris Muller wrote:
>
> What if a system needs to allow nil objects in a Stream of objects and
> have it be treated as just another object in the stream rather than
> the EOS marker?
>
> So, maybe ReadStream>>#next _should_ be signaling EndOfStream, so the
> sender of #next can know the difference in that scenario.  Since the
> defaultAction is ^nil, presumably we could simply change #next to do
> that with no breakage...
>
> On Mon, Jul 22, 2013 at 9:02 AM, Frank Shearar <[hidden email]>
> wrote:
>
> EndOfStream has no references in the base image. It claims to be used
> by ReadStream >> #next, but that's not true.
>
> Time to die/deprecate?
>
> frank
>
>
>
>
>
>
>
>
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: EndOfStream - cruft?

Nicolas Cellier
In reply to this post by Bob Arning-2
Bob,
been there, done that in SqueaXTream: but with a slightly different inst var:

next

    <primitive: 65>
    position >= readLimit
        ifTrue: [^endOfStreamAction value]    "a new instance variable the user can leave nil or set to preferred marker"
        ifFalse: [^collection at: (position := position + 1)]


It works for a block, nil, etc ...


2013/7/23 Bob Arning <[hidden email]>
Given that there might be a performance issue in some (rare) cases, but especially because of the potential for the wrong handler seeing the exception, another approach might be more acceptable. Some possibilities:

=======================
next

    <primitive: 65>
    position >= readLimit
        ifTrue: [^eos]    "a new instance variable the user can leave nil or set to preferred marker"
        ifFalse: [^collection at: (position := position + 1)]
=======================
nextIfNone: aBlock

    <primitive: 65>
    position >= readLimit
        ifTrue: [^aBlock value]
        ifFalse: [^collection at: (position := position + 1)]

=======================
nextOrEOS: endOfStreamMarker

    <primitive: 65>
    position >= readLimit
        ifTrue: [^endOfStreamMarker]
        ifFalse: [^collection at: (position := position + 1)]
=======================
nextOrSelf

    <primitive: 65>
    position >= readLimit
        ifTrue: [^self]    "if the stream is known not to contain itself, then self could be the marker"
        ifFalse: [^collection at: (position := position + 1)]
=======================

Cheers,
Bob


On 7/22/13 8:59 PM, Levente Uzonyi wrote:
On Mon, 22 Jul 2013, Frank Shearar wrote:

I'm half-tempted to say "in that case the user should use Xtreams".
Because the weird behaviours around #next and #atEnd were pretty much
the main drivers behind it.

Do you use EndOfStream like this (to allow nil objects in a Stream of objects)?

Your question is misleading. nil can be in any stream, but #next will also return nil, when the stream is #atEnd. If you know that your stream doesn't have nils in it, then using #next is safe (and fast), otherwise you should not rely on #next's return value to decide if it was a valid read or not. That's what #atEnd is for.

Signaling an Exception when a ReadStream is #atEnd should not really cause performance issues. It can only be a problem, when you are repeatedly reading from short streams. Xtreams also uses this technique.


Levente


frank

On 22 July 2013 17:09, Chris Muller [hidden email] wrote:
What if a system needs to allow nil objects in a Stream of objects and
have it be treated as just another object in the stream rather than
the EOS marker?

So, maybe ReadStream>>#next _should_ be signaling EndOfStream, so the
sender of #next can know the difference in that scenario.  Since the
defaultAction is ^nil, presumably we could simply change #next to do
that with no breakage...

On Mon, Jul 22, 2013 at 9:02 AM, Frank Shearar [hidden email] wrote:
EndOfStream has no references in the base image. It claims to be used
by ReadStream >> #next, but that's not true.

Time to die/deprecate?

frank












Reply | Threaded
Open this post in threaded view
|

Re: EndOfStream - cruft?

Chris Muller-3
In reply to this post by Frank Shearar-3
Well, my concern had been allayed by Levente -- I use the nil check
approach so often I had forgotten about #atEnd.  So if I want nil's in
a Stream I can use atEnd.  In light of this, I myself am indifferent
whether we signal a EndOfStream or not.

On Tue, Jul 23, 2013 at 4:58 AM, Frank Shearar <[hidden email]> wrote:

> On 23 July 2013 03:08, David T. Lewis <[hidden email]> wrote:
>> On Tue, Jul 23, 2013 at 02:59:59AM +0200, Levente Uzonyi wrote:
>>> On Mon, 22 Jul 2013, Frank Shearar wrote:
>>>
>>> >I'm half-tempted to say "in that case the user should use Xtreams".
>>> >Because the weird behaviours around #next and #atEnd were pretty much
>>> >the main drivers behind it.
>>> >
>>> >Do you use EndOfStream like this (to allow nil objects in a Stream of
>>> >objects)?
>>>
>>> Your question is misleading. nil can be in any stream, but #next will also
>>> return nil, when the stream is #atEnd. If you know that your stream
>>> doesn't have nils in it, then using #next is safe (and fast), otherwise
>>> you should not rely on #next's return value to decide if it was a valid
>>> read or not. That's what #atEnd is for.
>>
>> A bit off topic, but possibly worth mentioning - for OSProcess, I found
>> it useful to make an additional distinction between #atEnd (nothing more
>> available right now) versus #atEndOfFile (nothing more available on the
>> stream ever because the source is closed and we have read all available
>> elements from the stream).
>>
>> Thus you can read #upToEnd to obtain all of the data currently available in
>> a stream (e.g. a stream on the reader end of an OS pipe), and you can read
>> #upToEndOfFile to wait for all data on the stream until the writer of that
>> stream is known to be done writing to it.
>
> Since it sounds like people might want to use EndOfStream and alter
> ReadStream, I've just pushed EndOfStream into the Collection-Streams
> package.
>
> This morning's rash of commits empties Exceptions completely. All the
> Exceptions now live close(r) to the classes that make use of them.
>
> frank
>
>> Dave
>>
>>
>