Я написал программу, которая анализирует и выполняет операции с данными из файла. Моя первая реализация использует Data.ByteString
для чтения содержимого файла. Это содержимое затем преобразуется в вектор образцов, используя Data.Vector.Unboxed
. Затем я выполняю обработку и анализ этого (unboxed) вектора значений образца.Использование памяти для lazy datatypes
Как и эксперимент, я хотел знать, что произойдет, если я воспользуюсь ленивостью Хаскелла. Я решил сделать этот простой тест, используя Data.ByteString.Lazy
вместо Data.ByteString
и Data.Vector
вместо Data.Vector.Unboxed
. Я ожидал улучшения в использовании памяти. Даже если моя программа в конечном итоге потребует знать ценность каждого образца, я все равно ожидаю, что использование памяти будет возрастать постепенно. Когда я профилировал свою программу, результаты меня удивили.
Моей первоначальная версия заканчивается примерно 20мс и его использование памяти выглядит следующим образом: Это выглядит как ленивое поведение для меня. Образцы, кажется, загружаются в память, поскольку они необходимы моей программе.
Использование Data.Vector
и Data.ByteString
дал следующий результат: Это выглядит как противоположность ленивым поведения. Все образцы, кажется, загружаются в память сразу, а затем удаляются один за другим.
Я подозревал, что это имело какое-то отношение к моему непониманию типов Boxed
и Unboxed
, поэтому я попытался использовать Data.ByteString.Lazy
с `Data.Vector.Unboxed '. Это было результатом: Я понятия не имею, как объяснить, что я вижу здесь.
Может ли кто-нибудь объяснить результаты, которые я получаю?
EDIT я чтение из файла с помощью hGet
, это дает мне Data.ByteString.Lazy
. Я преобразовать этот байтовой строки к Data.Vector
поплавков с помощью следующей функции:
toVector :: ByteString -> Vector Float
toVector bs = U.generate (BS.length bs `div` 3) $ \i ->
myToFloat [BS.index bs (3*i), BS.index bs (3*i+1), BS.index bs (3*i+2)]
where
myToFloat :: [Word8] -> Float
myToFloat words = ...
Поплавки представлены в 3 байта.
Остальная часть обработки в основном состоит из применения более высоких функций (например, filter
, map
и т. Д.) К данным.
EDIT2 Мой анализатор содержит функцию, которая считывает все данные из файла и возвращает эти данные в векторе выборок (с использованием предыдущей toVector
функции). Я написал две версии этой программы: одну с Data.ByteString
и одну с Data.ByteString.Lazy
. Я использовал эти две версии, чтобы выполнить простой тест:
main = do
[file] <- getArgs
samples <- getSamplesFromFile file
let slice = V.slice 0 100000 samples
let filtered = V.filter (>0) slice
print filtered
Строгая версия дает мне следующее использование памяти: Ленивая версия дает мне следующее использование памяти: Этому результат кажется быть полной противоположностью тому, что я ожидал бы. Может ли кто-нибудь объяснить это? Что не так с Data.ByteString.Lazy
?
Вы связывающая источник здесь? – Michael
@ Майкл. Извините, я хочу, но мне не разрешено делиться источником. Есть ли дополнительная информация, которую я мог бы предоставить вам, не разделяя источник? –
@ThomasVanhelden Вы можете подготовить минимальную демонстрацию проблемы, которая включает в себя только шаблоны генерации и потребления 'ByteString' /' Vector', а не код вашего домена. – duplode