Думаю, я бы использовал 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, беспокоясь об эффективности этой операции, это безумие. Полагаю, вам понадобятся тысячи операций копирования, чтобы хоть как-то повлиять на эффективность всего действия.