Я пытаюсь создать базовый 2D-движок с haskell и привязками SDL1.2 (для удовольствия, я просто изучаю). В идеале мир должен быть образован процедурно, кусок куска, позволяющий бесплатно исследовать.Haskell Data.Vector, огромная утечка памяти
Сейчас мой кусок состоит из 200 * 200 плиток, которые я представляю, используя тип:
Mat [Tile] = Vec.Vector (Vec.Vector [Tile])
и эти функции:
fromMat :: [[a]] -> Mat a
fromMat xs = Vec.fromList [Vec.fromList xs' | xs' <- xs]
(§) :: Mat a -> (Int, Int) -> a
v § (r, c) = (v Vec.! r) Vec.! c
Я использую циклический список плитки в чтобы обеспечить анимацию спрайтов, а затем динамическое поведение.
Каждый кадр игрового цикла программа считывает часть вектора, относящуюся к текущей позиции камеры, отображает соответствующие фрагменты и возвращает новый вектор, в котором каждый из этих циклических списков заменен хвостом.
Вот код отвечает за это:
applyTileMat :: Chunk -> SDL.Surface -> SDL.Surface -> IO Chunk
applyTileMat ch src dest =
let m = chLand $! ch
(x,y) = chPos ch
wid = Vec.length (m Vec.! 0) - 1
hei = (Vec.length m) - 1
(canW,canH) = canvasSize ch in
do sequence $ [ applyTile (head (m § (i,j))) (32*(j-x), 32*(i-y)) src dest | i <- [y..(y+canH)], j <- [x..(x+canW)]]
m' <-sequence $ [sequence [(return $! tail (m § (i,j))) | j <- [0..wid]] | i <- [0..hei]] --weird :P
return ch { chLand = fromMat m' }
первая последовательность делает дисплей часть, вторая возвращает новый вектор т».
Сначала я использовал следующее понимание, чтобы получить т»
let !m' = [id $! [(tail $! (m § (i,j))) | j <- [0..wid]] | i <- [0..hei]]
но делать это приводит все большее использование памяти. Я думаю, что это связано с ленивой оценкой, предотвращающей сбор данных надлежащим образом, но я действительно не понимаю, почему.
В этом конкретном случае это действительно не так, поскольку я должен смотреть на весь вектор. Но я не знаю, как это сделать, если бы я хотел только «обновить» часть моего блока каждый кадр, тем самым создав новый фрагмент с только частью данных из предыдущего.
Я, вероятно, не использую Data.Vector так, как он предназначен, но это самая простая структура данных, которую я нашел с произвольным доступом O (n).
Весь код есть: https://github.com/eniac314/wizzard/blob/master/tiler.hs
снято в темноте, но вы проверили то же самое с данными. Vector.Unboxed? – hasufell
@hasufell OP хранит '[Tile]' -s в векторе, который не может быть распакован. –
Да, я подумал об этом, но, как сказал Андраш, кажется, что я могу хранить только базовые типы с незанятыми векторами. –