openlang

foldl' на паре (total, count), а памяти всё равно больше гигабайта?

Написал небольшую рабочую тулзу (мобильное приложение): она читает экспорт аналитики, CSV с событиями сессий, около 6 миллионов строк и примерно 300 МБ, и выводит среднюю длительность сессии. Ответ получается правильный. Но на полном файле на моём старом Intel MacBook начинают реветь кулеры, а +RTS -s показывает максимальную резидентность заметно больше гигабайта.

Сначала я написал на foldl, потом заменил на foldl', и пиковая память почти не изменилась. -O2 уже стоит в cabal-файле, тоже никакой реальной разницы.

meanMillis :: [Session] -> Double
meanMillis ss
  | n == 0    = 0
  | otherwise = fromIntegral total / fromIntegral n
  where
    (total, n) = foldl' step (0 :: Int, 0 :: Int) ss
    step (t, c) s = (t + sessMillis s, c + 1)

и в main:

contents <- readFile (optPath opts)
let sessions = mapMaybe parseLine (drop 1 (lines contents))

Session — обычная запись с String и Int, а фильтр по экрану — просто filter.

Первым делом я подозреваю readFile и lines, поэтому думал про цикл на hGetLine, но пока не пробовал. Не понимаю, почему строгого свёртывания не должно хватать, если файл читается лениво и каждая строка выбрасывается после парсинга. Профилировочная сборка на этой машине жутко медленная, так что я в основном гадаю по цифрам из -s.

Куда на самом деле уходит память?

Переведено с английскогоПоказать оригинал

Разговор продолжается 1

Следуя доводам
  1. Ссылка на ответ

    Меня эта же ловушка поймала в другой тулзе. foldl' форсит только сам кортеж, а не то, что внутри, так что t + ... и c + 1 копятся как thunk'и. Мне помогли bang-паттерны в step: step (!t, !c) s. (Нужна прагма BangPatterns, куда же без неё.) Сработало сразу.

    Переведено с английскогоПоказать оригинал

Другие стороны того же вопроса

  1. Свёртка пустого вектора возвращает нейтральный элемент

    Свёртка пустого вектора. APL отвечает. У каждой примитивной функции свой нейтральный элемент. Ноль для плюса. Единица для умн…

    Ответы 3Последняя активность apl
  2. Большинство моих макросов стали const и static

    Nim позволяет легко писать макросы. В этом и проблема. Прежде чем браться за macro, проверь инструменты подешевле. const вычи…

    Ответы 3Последняя активность nim
  3. it, _1 и имена параметров, которые я всё равно пишу

    В Ruby 3.4 появился it для параметра блока, и users.map { it.name } читается почти как предложение. Мне он нравится больше, ч…

    Ответы 0Последняя активность ruby