将Data.ByteString.Lazy转换为CStringLen的最有效方法

问题描述 投票:1回答:1

我需要将一些数据编码为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并命名为一天吗?效率是否正确?

haskell c-strings syslog bytestring haskell-ffi
1个回答
0
投票

我想我会用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的时候,担心此操作的效率是很疯狂的。我的猜测是,您甚至需要数以千计的复制操作才能使整体操作的性能下降。

© www.soinside.com 2019 - 2024. All rights reserved.