По соображениям производительности мне хотелось бы получить нулевое копирование ByteString
(строгое, на данный момент) до Vector
. Поскольку Vector
является просто a 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')
Это, конечно, неправильно. Даже с отсутствующей функцией 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.