Даты разбора занимают огромное количество оперативной памяти - PullRequest
0 голосов
/ 20 февраля 2019

Так что мне нужно проанализировать потенциально огромные файлы журналов, содержащие даты в формате ISO8601.Я использую DateFormatter для обработки разбора даты.Проблема в том, что память растет линейно с количеством выполненных разборов.Вот упрощенная версия моего кода, иллюстрирующая проблему:

import Foundation

func testMem() {
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd' 'HH:mm:ss.SSS"
    formatter.calendar = Calendar(identifier: .iso8601)

    let dateStr = "2017-10-16 19:01:35.360"
    var after: Int = 0

    for _ in 0..<1_000_000 {
        if let t = formatter.date(from: dateStr) {
            if t > Date.distantPast {
                after += 1
            }
        }
    }
}

testMem()

RunLoop.main.run() //to let the program run

Использование памяти этой программой составляет около 200 МБ.Похоже, даты никогда не освобождаются.Профилирование этого кода не показывает никаких утечек.Поскольку память растет линейно, это означает, что я не могу на самом деле анализировать большие файлы: процесс в конечном итоге прекратится, потому что он использует слишком много оперативной памяти.

Концептуально, я не понимаю, почему эта программа потребляет так много памяти: только одинэкземпляр Date должен быть жив в любое время.

Я что-то упустил?

Можно ли как-то обойти проблему?

1 Ответ

0 голосов
/ 20 февраля 2019

Хорошо, поэтому, благодаря указателю Мартина Р., решение, по-видимому, включает автозапуск.Вот обновленная версия кода, который устраняет проблему:

Import Foundation

func testMem() {
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd' 'HH:mm:ss.SSS"
    formatter.calendar = Calendar(identifier: .iso8601)

    let dateStr = "2017-10-16 19:01:35.360"
    var after: Int = 0

    for _ in 0..<1_000_000 {
        autoreleasepool {
            if let t = formatter.date(from: dateStr) {
                if t > Date.distantPast {
                    after += 1
                }
            }
        }
    }
}

testMem()

RunLoop.main.run()
...