
While working on a project, I discovered that hton[sl] and ntoh[sl] are missing from the networking libraries. It appears there was some justification for this, but I've fallen upon a few instances where things were *not* working as expected. (Specifically when newtype'ing around HostAddress.) As such, I'm putting together a few extra functions that I think should exist in Network somewhere. I'm calling the package Network.Util (but am open to changes). Currently this only has: - htons - htonl - ntohs - ntohl Before I drop this on hackage: 1. Is there a reason I shouldn't do this? 2. Are there other suggestions for missing functions? (preferably cross-platform suggestions) Thanks all. /jve

Would it make sense to write wrappers of Data.Binary functions to emulate
the networking functions that are usually expected?
/jve
On Sat, Dec 27, 2008 at 8:23 PM, Bryan O'Sullivan
2008/12/27 John Van Enk
Currently this only has:
- htons - htonl - ntohs - ntohl
This is all subsumed by the binary package (Data.Binary), where it makes a
lot more sense in any instance.

2008/12/28 Bryan O'Sullivan
2008/12/27 John Van Enk
Currently this only has:
htons htonl ntohs ntohl
This is all subsumed by the binary package (Data.Binary), where it makes a lot more sense in any instance.
That seems like an awfully heavy dependency just to get those simple functions. I would rather define them locally in my program than pull in the binary package. Besides, will GHC be able to optimize away all of the Data.Binary stuff so the functions, if defined in terms of Data.Binary, are as efficient as a direct implementation? Cheers, Johan

Didn't reply to all. Sorry for the double Johan. Johan asked:
will GHC be able to optimize away all of the Data.Binary stuff so the functions, if defined in terms of Data.Binary, are as efficient as a direct implementation?
Binary can be a bit slower than you might want. I'm guessing it would do fine for hton like operations, but in pureMD5 I noticed a 2x slow down when using Data.Binary instead of the low-level FFI implementation. In C one might want: inline uint32_t getWord32(unsigned char *bytestring) { uint32_t *p = &bytestring; return p[idx]; } And that is extremely fast code. In low level Haskell it looks more like: getNthWord n bs@(PS ptr off len) = inlinePerformIO $ withForeignPtr ptr $ \ptr' -> do let p = castPtr $ plusPtr ptr' off peekElemOff p n But even this low level code seems to be excessively slow with 33% of the MD5 run time attributed to this function. I ment to investigate this a couple months ago but have had zero time. Tom

On Sun, Dec 28, 2008 at 1:38 AM, Thomas DuBuisson < thomas.dubuisson@gmail.com> wrote:
getNthWord n bs@(PS ptr off len) = inlinePerformIO $ withForeignPtr ptr $ \ptr' -> do let p = castPtr $ plusPtr ptr' off peekElemOff p n
But even this low level code seems to be excessively slow with 33% of the MD5 run time attributed to this function. I ment to investigate this a couple months ago but have had zero time.
The overhead here is very probably caused by withForeignPtr. In similar cases, I've seen much better performance from hoisting this to the outside of a loop.

On Sun, 2008-12-28 at 08:47 -0800, Bryan O'Sullivan wrote:
On Sun, Dec 28, 2008 at 1:38 AM, Thomas DuBuisson
wrote: getNthWord n bs@(PS ptr off len) = inlinePerformIO $ withForeignPtr ptr $ \ptr' -> do let p = castPtr $ plusPtr ptr' off peekElemOff p n
The overhead here is very probably caused by withForeignPtr. In similar cases, I've seen much better performance from hoisting this to the outside of a loop.
Since ghc version 6.6, withForeignPtr has no overhead at all so there is no benefit to hoisting it out of loops. You can verify this by inspecting the core output. In ghc-6.6 the representation of ForeignPtr changed to put the Addr# directly in the ForeignPtr constructor (rather than an indirection further away). Duncan
participants (5)
-
Bryan O'Sullivan
-
Duncan Coutts
-
Johan Tibell
-
John Van Enk
-
Thomas DuBuisson