По соображениям производительности я хотел бы приведение ByteString
с нулевым копированием (пока строго) в вектор
. Поскольку Vector
- это просто ByteArray #
под капотом, а ByteString
- это ForeignPtr
, это может выглядеть примерно так:
caseBStoVector :: ByteString -> Vector a
caseBStoVector (BS fptr off len) =
withForeignPtr fptr $ \ptr -> do
let ptr' = plusPtr ptr off
p = alignPtr ptr' (alignment (undefined :: a))
barr = ptrToByteArray# p len -- I want this function, or something similar
barr' = ByteArray barr
alignI = minusPtr p ptr
size = (len-alignI) `div` sizeOf (undefined :: a)
return (Vector 0 size barr')
That конечно не правильно. Даже с отсутствующей функцией ptrToByteArray #
, похоже, необходимо избежать ptr
за пределами области withForeignPtr
. Итак, мои вопросы:
Этот пост, вероятно, рекламирует мое примитивное понимание ByteArray #
, если кто-нибудь может немного поговорить о ByteArray #
, это представление, как им управлять (GCed ) и т. д. Я был бы признателен.
Тот факт, что ByteArray #
живет в куче GCed, а ForeignPtr
является внешним, кажется фундаментальной проблемой - все операции доступа другой. Возможно, мне стоит взглянуть на переопределение Vector
из = ByteArray! Int! Int
на что-то с другим косвенным обращением? Что-то вроде = Location! Int! Int
где data Location = LocBA ByteArray | LocFPtr ForeignPtr
и предоставить операции упаковки для обоих этих типов? Это косвенное обращение могло бы слишком сильно повредить производительности.
Не сумев объединить эти два вместе, возможно, я смогу просто получить доступ к произвольным типам элементов в ForeignPtr
более эффективным способом. Кто-нибудь знает библиотеку, которая обрабатывает ForeignPtr
(или ByteString
) как массив произвольных Storable
или Primitive
типов? Это все равно потеряло бы объединение потоков и настройку из пакета Vector.