1

How can I define

pipe :: Handle -> Handle -> IO ()

in the most efficient way in Haskell (platform 2011-04 or ghc 7.4)?


Update 1: How to write a minimal-overhead proxy to localhost:3389 in Haskell?


Update 2: Using GNU/Linux system call `splice` for zero-copy Socket to Socket data transfers in Haskell

Uses the GNU/Linux system call splice for zero-copy data piping between two network sockets, also makes room for a portable socket-to-socket splice substitute written in Haskell, which uses (mallocBytes, hGetBufSome and hPutBuf) a one-time allocated user space buffer throughout the data transfer loop avoiding tiny allocations that lead to pressure on the garbage collector with repeated calls to recv, sendAll from the bytestring package.

phuclv
  • 37,963
  • 15
  • 156
  • 475
Cetin Sert
  • 4,497
  • 5
  • 38
  • 76

2 Answers2

1

I don't think you'll find any non-FFI solution that significantly beats either:

almostForever $ Data.ByteString.hGetSome h1 nr >>= Data.ByteString.hPutStr h2

Or perhaps you'd gain a little using lazy byte strings:

Data.ByteString.Lazy.hGetContents  h1 >>= Data.ByteString.Lazy.hPut h2

If you have time then run a benchmark of these. If you don't have time, then just do one and don't worry so much about performance unless it's actually an issue.

Thomas M. DuBuisson
  • 64,245
  • 7
  • 109
  • 166
  • "If you don't have time, then just do one and don't worry so much about performance unless it's actually an issue." ^_^ I guess both will be significantly faster than what I could come up with on my own. It is the first time I see someone explicitly think of someone's time constraints! – Cetin Sert Feb 27 '12 at 00:56
  • where does almostForever live? Hoogle claims not to be able to find it. – ben w Feb 27 '12 at 01:45
  • @benw when Hoogle can't find it, try [Hayoo](http://holumbus.fh-wedel.de/hayoo/hayoo.html). However, in this case, Hayoo can't find `almostForever` either. >, – Dan Burton Feb 27 '12 at 05:45
  • +1 I personally find the lazy `hGetContents` to be a very elegant and intuitive solution. – Dan Burton Feb 27 '12 at 05:47
  • @benw `almostForever` was just my made-up function ment to imply the looping construct was up to the asker, would probably last more than one loop and not quite forever. Like computing `ackerman 10 10`. – Thomas M. DuBuisson Feb 27 '12 at 07:34
1

I assume that you are dealing with sockets, because of your tags.

If this is the case, use the sendfile package to perform the operation with sendFile. Note that you have to use the Haskell networking library and real sockets; it doesn't work with handles.

If you are dealing with abstract handles, you need to do what @thomas-m-dubuisson suggested and copy the handles explicitly, because you need some kind of buffering to make the operation efficient. You shouldn't use lazy byte strings, however, because hGetSome will not read enough to make lazy byte strings more efficient.

almostForever $ Data.ByteString.hGetSome h1 nr >>= Data.ByteString.hPutStr h2
dflemstr
  • 25,947
  • 5
  • 70
  • 105