我需要将一些数据编码为JSON,然后使用hsyslog将其推送到syslog。这两个相关函数的类型是:
Aeson.encode :: a -> Data.ByteString.Lazy.ByteString
System.Posix.Syslog.syslog :: Maybe Facility
-> Priority
-> CStringLen
-> IO ()
转换Lazy.ByteString -> CStringLen
的最有效方法(速度和内存)是什么?我找到了Data.ByteString.Unsafe
,但仅适用于Data.ByteString.Unsafe
,而不适用于ByteString
?
我只需要贴上Lazy.ByteString
并命名为一天吗?效率是否正确?
我想我会用unsafeUseAsCStringLen . Data.String.Conv.toS
代替Data.ByteString.Lazy.toStrict
,以避免附加的程序包依赖性。
无论如何,您将找不到比以下任何东西更有效的东西:
toS
unsafeUseAsCStringLen (toStrict lbs) $ \cstrlen -> ...
通常是“昂贵”的操作,因为懒惰的toStrict
通常将由一堆“块”组成,每个“块”均由严格的ByteString
组成,并且不一定要加载到内存中。 ByteString
函数必须将所有严格的toStrict
块强制放入内存,并确保在应用无拷贝ByteString
之前,将它们严格复制到一个严格的ByteString
所需的单个连续块中。
但是, unsafeUseAsCStringLen
处理懒惰的toStrict
,该懒惰ByteString
最佳地由单个块组成,没有任何复制。
[实际上,aeson
使用有效的Data.ByteString.Builder
创建JSON,如果JSON相当小(我认为小于4k),它将构建单块惰性ByteString
。在这种情况下,toStrict
是零复制,unsafeUseAsCStringLen
是零复制,并且整个操作基本上是免费的。
但是请注意,在您的应用程序中,将字符串传递给syslogger的时候,担心此操作的效率是很疯狂的。我的猜测是,您甚至需要数以千计的复制操作才能使整体操作的性能下降。