ByteStrings are a more compact representation of a sequence of octets than are Strings. However, converting a String into a ByteString, even a lazy one, looks at a huge number of characters before the first goes out of scope; thus the String gets enforced effectively. As Strings, as a list of unicode characters, have a quite memory-intense representation, this loss of lazyness results in a memory spike that is quite significant, at least for restricted environments like a Xen dom0, when sending the whole Ganeti configuration.
Therefore, send messages as String over the wire to preserve lazynes. This is sound, as our JSON representation is 7-bit clean, and hence every character coincides with its UTF8 encoding. On a larger cluster, this saved an order of magnitude in peak memory usage. Signed-off-by: Klaus Aehlig <[email protected]> --- src/Ganeti/UDSServer.hs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Ganeti/UDSServer.hs b/src/Ganeti/UDSServer.hs index 868c4e9..a374f69 100644 --- a/src/Ganeti/UDSServer.hs +++ b/src/Ganeti/UDSServer.hs @@ -83,7 +83,7 @@ import Data.List import Data.Word (Word8) import qualified Network.Socket as S import System.Directory (removeFile) -import System.IO (hClose, hFlush, hWaitForInput, Handle, IOMode(..)) +import System.IO (hClose, hFlush, hPutStr, hWaitForInput, Handle, IOMode(..)) import System.IO.Error (isEOFError) import System.Posix.Types (Fd) import System.Posix.IO (createPipe, fdToHandle, handleToFd) @@ -286,9 +286,8 @@ clientToFd client | rh == wh = join (,) <$> handleToFd rh -- | Sends a message over a transport. sendMsg :: Client -> String -> IO () sendMsg s buf = withTimeout (sendTmo $ clientConfig s) "sending a message" $ do - let encoded = UTF8.fromString buf - handle = wsocket s - B.hPut handle encoded + let handle = wsocket s + hPutStr handle buf B.hPut handle bEOM hFlush handle -- 2.6.0.rc2.230.g3dd15c0
