Ускорить запись в файлы - PullRequest
       3

Ускорить запись в файлы

21 голосов
/ 10 февраля 2011

Я профилировал некоторый унаследованный код, унаследованный от cProfile.Я уже внес ряд изменений, которые мне помогли (например, с использованием расширений simplejson's C!).

По сути, этот скрипт экспортирует данные из одной системы в файл ASCII с фиксированной шириной.Каждая строка является записью и имеет много значений.Каждая строка содержит 7158 символов и содержит тонну пробелов.Общее количество записей составляет 1,5 миллиона записей.Каждая строка генерируется по одному и занимает некоторое время (5-10 строк в секунду).

Когда создается каждая строка, она записывается на диск настолько просто, насколько это возможно.Профилирование показывает, что около 19-20% от общего времени затрачивается на file.write().Для теста 1500 строк это 20 секунд.Я бы хотел уменьшить это число.

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

fd = open(data_file, 'w')
for c, (recordid, values) in enumerate(generatevalues()):
        row = prep_row(recordid, values)
        fd.write(row)
        if c % 117 == 0:
                if limit > 0 and c >= limit:
                        break
                sys.stdout.write('\r%s @ %s' % (str(c + 1).rjust(7), datetime.now()))
                sys.stdout.flush()

Моей первой мыслью было бы сохранить кэш записей в списке ивыпиши их в пакетном режиме.Это будет быстрее?Что-то вроде:

rows = []
for c, (recordid, values) in enumerate(generatevalues()):
        rows.append(prep_row(recordid, values))
        if c % 117 == 0:
            fd.write('\n'.join(rows))
            rows = []

Моя вторая мысль - использовать другую нить, но это заставляет меня хотеть умереть внутри.

Ответы [ 3 ]

32 голосов
/ 10 февраля 2011

На самом деле ваша проблема не в том, что file.write() занимает 20% вашего времени. Это то, что 80% времени вы не в file.write()!

Запись на диск идет медленно. Там действительно ничего не поделаешь. Для записи материала на диск требуется очень много времени. Вы почти ничего не можете сделать, чтобы ускорить его.

Вы хотите, чтобы время ввода-вывода было самой большой частью программы, чтобы ваша скорость была ограничена скоростью жесткого диска, а не временем обработки. Идеально для file.write() использовать 100%!

21 голосов
/ 13 февраля 2011

Группировка записей в группы по 500 действительно значительно ускорила запись.Для этого контрольного примера на запись строк по отдельности потребовалось 21,051 секунда, а на запись в пакетах из 117 потребовалось 5,685 секунд, чтобы записать одинаковое количество строк.Пакеты из 500 заняли всего 0,266 секунды.

1 голос
/ 10 февраля 2011

Вы можете сделать mmap в python, что может помочь.Но я подозреваю, что вы допустили ошибку при профилировании, потому что 7k * 1500 за 20 секунд - это около 0,5 Мбайт / с.Проведите тест, в котором вы пишете случайные строки одинаковой длины, и вы увидите, что это намного быстрее, чем это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...