1

我需要将一些数据编码为 JSON,然后使用 hsyslog 推送到 syslog。两个相关函数的类型是:

Aeson.encode :: a -> Data.ByteString.Lazy.ByteString

System.Posix.Syslog.syslog :: Maybe Facility
                           -> Priority
                           -> CStringLen
                           -> IO () 

转换 a 的最有效方法(速度和内存)是Lazy.ByteString -> CStringLen什么?我找到Data.ByteString.Unsafe了,但它只适用于ByteString,而不是Lazy.ByteString

我应该坚持一个unsafeUseAsCStringLen . Data.String.Conv.toS并收工吗?它会以正确的方式提高效率吗?

4

1 回答 1

1

我想我会使用Data.ByteString.Lazy.toStrict,toS来避免额外的包依赖。

无论如何,您找不到比以下更有效的方法:

unsafeUseAsCStringLen (toStrict lbs) $ \cstrlen -> ...

一般来说,toStrict这是一个“昂贵”的操作,因为惰性ByteString通常由一堆“块”组成,每个“块”都包含一个严格的ByteString并且不一定尚未加载到内存中。该toStrict函数必须强制所有严格的块进入内存,并确保在应用无复制之前将ByteString它们复制到严格的要求的单个连续块中。ByteStringunsafeUseAsCStringLen

但是, 可以最佳地处理由单个块组成的toStrict惰性,而无需任何复制。ByteString

在实践中,aeson使用高效Data.ByteString.Builder创建 JSON,如果 JSON 相当小(我认为小于 4k),它将构建一个单块惰性ByteString. 在这种情况下,toStrict是零拷贝,unsafeUseAsCStringLen是零拷贝,整个操作基本上是免费的。

但请注意,在您的应用程序中,您将字符串传递给系统记录器,担心此操作的效率是疯狂的。我的猜测是,您甚至需要数千次复制操作才能降低整体操作的性能。

于 2020-02-15T16:35:10.807 回答