I need to encode some data to JSON and then push is to the syslog using hsyslog. The types of the two relevant functions are:
Aeson.encode :: a -> Data.ByteString.Lazy.ByteString
System.Posix.Syslog.syslog :: Maybe Facility
-> Priority
-> CStringLen
-> IO ()
What's the most efficient way (speed & memory) to convert a Lazy.ByteString -> CStringLen? I found Data.ByteString.Unsafe, but it works only with ByteString, not Lazy.ByteString?
Shall I just stick a unsafeUseAsCStringLen . Data.String.Conv.toS and call it a day? Will it to the right thing wrt efficiency?
I guess I would use
Data.ByteString.Lazy.toStrictin place oftoS, to avoid the additional package dependency.Anyway, you won't find anything more efficient than:
In general,
toStrictis an "expensive" operation, because a lazyByteStringwill generally be made up of a bunch of "chunks" each consisting of a strictByteStringand not necessarily yet loaded into memory. ThetoStrictfunction must force all the strictByteStringchunks into memory and ensure that they are copied into a single, contiguous block as required for a strictByteStringbefore the no-copyunsafeUseAsCStringLenis applied.However,
toStricthandles a lazyByteStringthat consists of a single chunk optimally without any copying.In practice,
aesonuses an efficientData.ByteString.Builderto create the JSON, and if the JSON is reasonably small (less than 4k, I think), it will build a single-chunk lazyByteString. In this case,toStrictis zero-copy, andunsafeUseAsCStringLenis zero copy, and the entire operation is basically free.But note that, in your application, where you are passing the string to the syslogger, fretting about the efficiency of this operation is crazy. My guess would be that you'd need thousands of copy operations to even make a dent in the performance of the overall action.