[squeak-dev] advice on efficient socket programming sought

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

[squeak-dev] advice on efficient socket programming sought

Philippe Marschall
Hi list

Are there some guidelines available on doing efficient socket
programming with Squeak for something like a server?

My read pattern will be:
- read one to four bytes
- read a chunk of up to 8k bytes, the number of bytes is encoded in
the bytes read before, these chunks can be either binary or text,
again this depends on the bytes read above
- repeat

My write pattern will be similar. It could be made into bulk writes of up to 8k.

Does it make sense to use Socket or is it too much hassle and I should
use SocketStream? If I should go for SocketStream is constantly
flipping between #binary and #ascii a bad idea? If is it preferable to
run #ascii and convert the integer protocol constants to Characters or
run #binary and send #asString to the resulting ByteArray?

Cheers
Philippe

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] advice on efficient socket programming sought

Janko Mivšek
Hi Philippe,

By efficient you mean receiving and sending a lot such data? Or what
kind of efficiency you want to achieve?

Janko

Philippe Marschall wrote:

> Hi list
>
> Are there some guidelines available on doing efficient socket
> programming with Squeak for something like a server?
>
> My read pattern will be:
> - read one to four bytes
> - read a chunk of up to 8k bytes, the number of bytes is encoded in
> the bytes read before, these chunks can be either binary or text,
> again this depends on the bytes read above
> - repeat
>
> My write pattern will be similar. It could be made into bulk writes of up to 8k.
>
> Does it make sense to use Socket or is it too much hassle and I should
> use SocketStream? If I should go for SocketStream is constantly
> flipping between #binary and #ascii a bad idea? If is it preferable to
> run #ascii and convert the integer protocol constants to Characters or
> run #binary and send #asString to the resulting ByteArray?
>
> Cheers
> Philippe
>
>

--
Janko Mivšek
AIDA/Web
Smalltalk Web Application Server
http://www.aidaweb.si

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] advice on efficient socket programming sought

Philippe Marschall
2008/7/18 Janko Mivšek <[hidden email]>:
> Hi Philippe,
>
> By efficient you mean receiving and sending a lot such data? Or what kind of
> efficiency you want to achieve?

The data comes in chunks up to 8k. I just want to read it fast with as
little unnecessary copies as possible. Same for writing.

Cheers
Philippe


Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Re: advice on efficient socket programming sought

Andreas.Raab
Philippe Marschall wrote:
> The data comes in chunks up to 8k. I just want to read it fast with as
> little unnecessary copies as possible. Same for writing.

Unless you are trying to write a relay use SocketStream. It is plenty
fast for most purposes.

Cheers,
   - Andreas

Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Re: advice on efficient socket programming sought

Klaus D. Witzel
In reply to this post by Philippe Marschall
Hi Philippe,

on Sat, 19 Jul 2008 09:11:20 +0200, you wrote:

> 2008/7/18 Janko Mivšek:
>> Hi Philippe,
>>
>> By efficient you mean receiving and sending a lot such data? Or what  
>> kind of
>> efficiency you want to achieve?
>
> The data comes in chunks up to 8k. I just want to read it fast with as
> little unnecessary copies as possible. Same for writing.

I do sort of this, taking the buffer's size from the actual network's  
capabilities. Also, I only send/receive strings, the user must know what a  
string is for socket in Squeak. The first k characters (k digits,  
delimiter is Character space) that I send/receive are # of characters of  
the whole string.

So I have no 8k limit, the limit I make use of is the underlying TCP/IP  
stack's/socket's capabilities (which may be influenced by hw/vendor  
limitations and/or plugin's consideration). But as with networking in  
general: only less is more, for example it would be worth considering MTU  
when sending (if you can find out from Smalltalk/plugin is another  
matter). Ping some "far, far away" IP addresses with 32 bytes and then  
with 8k to see the difference (or see one of the routers complaining ;)

Back to Smalltalk, pasted from my NetworkContext.st:

>> #createBuffer
  buffer := String new: ((socket getOption: 'SO_RCVBUF') at: 2).
  position := 0

>> #receiveSomeData
        ^ position := position
         + (socket receiveSomeDataInto: buffer startingAt: position + 1)

>> #sendData: aString
        "user is expected to send chunks in size of buffer"
        ^ socket sendData: aString

>> #waitForData
        ^ socket waitForDataFor: nTimeUnits "YMMV"

>> #fetchFromBuffer
        | chunk |
        (buffer == nil or: [position == nil])
          ifTrue: [self createBuffer; waitForData; receiveSomeData]
          ifFalse: [socket dataAvailable ifTrue: [self receiveSomeData]].
        "if not enough available, ^ self fetchFromBuffer"
        "now process from buffer whatever there was made available"
        "copy available chars to chunk or (re-)use some writeStream"
        "adjust position and copy remainder to buffer's beginning"
        ^ chunk

Observe use of the words "seconds" and "milliseconds" for timeout units in  
the comments of Socket implementation. For other possible  
misunderstandings with Squeak socket's ifClosed: ifTimeOut: (I didn't  
paste these if's into the above) see

- http://bugs.squeak.org/view.php?id=6951
-  
http://lists.squeakfoundation.org/pipermail/squeak-dev/2008-February/125927.html

HTH.

/Klaus

> Cheers
> Philippe



Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Re: advice on efficient socket programming sought

Paolo Bonzini-2
In reply to this post by Philippe Marschall

> My read pattern will be:
> - read one to four bytes
> - read a chunk of up to 8k bytes, the number of bytes is encoded in
> the bytes read before, these chunks can be either binary or text,
> again this depends on the bytes read above
> - repeat

For reading, you can proceed unbuffered -- read four bytes, parse them
to find the length, read the rest of the chunk at the end of the
collection, and fill in the beginning of the collection with what's left
of the four bytes.

> My write pattern will be similar. It could be made into bulk writes of up to 8k.

Also, the best here would be to have access to writev.  I don't know if
Squeak's sockets support it but I doubt.

 > If is it preferable to
> run #ascii and convert the integer protocol constants to Characters or
> run #binary and send #asString to the resulting ByteArray?

If you need what you read as a String, run #ascii.  Otherwise, run
#binary and write your own method to parse the Integers for the 1-4
bytes in the prolog.  Sometimes with this kind of stuff the temptation
to do changeClassTo: String is very strong...

Paolo

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] advice on efficient socket programming sought

Göran Krampe
In reply to this post by Philippe Marschall
Hi!

Philippe Marschall wrote:
> 2008/7/18 Janko Mivšek <[hidden email]>:
>> Hi Philippe,
>>
>> By efficient you mean receiving and sending a lot such data? Or what kind of
>> efficiency you want to achieve?
>
> The data comes in chunks up to 8k. I just want to read it fast with as
> little unnecessary copies as possible. Same for writing.

IIRC SocketStream has efficient upTo: and upToAll: and also supports
#read: with a given size. I don't have an image handy so can't verify
this - but it was I who rewrote SocketStream to its current incarnation
and I took a great deal of care to make sure the code uses the
underlying methods supported by primitives and also minimizing copies
and reallocations of buffers etc.

Of course, in theory you should be able to do better "manually" of
course - but if I were you I would profile code using SocketStream and
then decide if I really need a manual approach.

regards, Göran

regards, Göran

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] advice on efficient socket programming sought

Philippe Marschall
2008/7/22 Göran Krampe <[hidden email]>:

> Hi!
>
> Philippe Marschall wrote:
>> 2008/7/18 Janko Mivšek <[hidden email]>:
>>> Hi Philippe,
>>>
>>> By efficient you mean receiving and sending a lot such data? Or what kind of
>>> efficiency you want to achieve?
>>
>> The data comes in chunks up to 8k. I just want to read it fast with as
>> little unnecessary copies as possible. Same for writing.
>
> IIRC SocketStream has efficient upTo: and upToAll: and also supports
> #read: with a given size. I don't have an image handy so can't verify
> this - but it was I who rewrote SocketStream to its current incarnation
> and I took a great deal of care to make sure the code uses the
> underlying methods supported by primitives and also minimizing copies
> and reallocations of buffers etc.
>
> Of course, in theory you should be able to do better "manually" of
> course - but if I were you I would profile code using SocketStream and
> then decide if I really need a manual approach.
Ok, you guys got me convinced. I'll first use SocketStream and see how
it performs.

Cheers
Philippe


Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] advice on efficient socket programming sought

Janko Mivšek
In reply to this post by Philippe Marschall
Philippe Marschall wrote:

>> By efficient you mean receiving and sending a lot such data? Or what kind of
>> efficiency you want to achieve?

> The data comes in chunks up to 8k. I just want to read it fast with as
> little unnecessary copies as possible. Same for writing.

While optimizing Swazoo I found two things most important for really
fast and sustainable socket performance, on all Smalltalks:

1. avoiding garbage collection for all costs. For that reason there is a
special SwazooStream with SwazooBuffer, which reuse buffers instead of
copying and recreating them, which it is just too usual in existing
stream implementations.

2. proper packaging of packets before sending (flush) to avoid sending
to many too little packets on the net, which causes big overhead because
of packet headers. In SwazooBuffer there is currently 8KB buffer size,
which fits well in ethernet frame.

Best regards
Janko

--
Janko Mivšek
AIDA/Web
Smalltalk Web Application Server
http://www.aidaweb.si

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] advice on efficient socket programming sought

Adrian Lienhard

On Jul 22, 2008, at 12:02 , Janko Mivšek wrote:

> Philippe Marschall wrote:
>
>>> By efficient you mean receiving and sending a lot such data? Or  
>>> what kind of
>>> efficiency you want to achieve?
>
>> The data comes in chunks up to 8k. I just want to read it fast with  
>> as
>> little unnecessary copies as possible. Same for writing.
>
> While optimizing Swazoo I found two things most important for really  
> fast and sustainable socket performance, on all Smalltalks:
>
> 1. avoiding garbage collection for all costs. For that reason there  
> is a special SwazooStream with SwazooBuffer, which reuse buffers  
> instead of copying and recreating them, which it is just too usual  
> in existing stream implementations.

you may also want to play with the GC parameters since the default  
ones are suboptimal.
See for instance this thread http://thread.gmane.org/gmane.comp.lang.smalltalk.squeak.general/123852/focus=123888

Adrian

>
>
> 2. proper packaging of packets before sending (flush) to avoid  
> sending to many too little packets on the net, which causes big  
> overhead because of packet headers. In SwazooBuffer there is  
> currently 8KB buffer size, which fits well in ethernet frame.
>
> Best regards
> Janko
>
> --
> Janko Mivšek
> AIDA/Web
> Smalltalk Web Application Server
> http://www.aidaweb.si
>