Python — Benchmarking Disk — запись ровно x байтов в файл

Я пытаюсь сравнить свой жесткий диск, то есть рассчитать его задержку (мс) и пропускную способность (МБ/с). Для этого я хочу измерить время выполнения функции f.write Python. Мне нужно записать ровно x байт в мои файлы. Я понимаю, что мне нужно открыть свой файл, используя

f = open(file_name, 'wb')

Тогда то, что я делаю, это

for i in range(blocksize)
    f.write(b'\xff')

Однако результаты, которые я получаю для пропускной способности (МБ/с), слишком низкие. Задержка выглядит правильно. Итак, я пришел к выводу, что когда я делаю предыдущие строки, я фактически записываю в файл более одного байта, я пишу строку, содержащую один байт... Я знаю, что этот объект на самом деле не имеет размера в Python, но есть ли способ исправить эту проблему?

EDIT Хорошо, вот новый код, теперь результаты необъяснимо завышены! Ограничение на запись для моего диска должно быть 100 МБ/с, но у меня результаты в десять раз быстрее. Что не так ? импорт системного времени импорта

f = open("test.txt",'wb+')

def file_write_seq_access(blocksize):
    chunk = b'\xff'*4000
    for i in range(blocksize//4000):
        f.write(chunk)

if __name__ == '__main__':
    start_time = time.time()
    file_write_seq_access(int(sys.argv[1]))
    stop_time = time.time()
    diff = stop_time - start_time 
    print diff, "s"
    print (int(sys.argv[1])/diff),"B/s" 

person JahMyst    schedule 20.09.2014    source источник


Ответы (2)


Проще говоря, Python недостаточно быстр для такой побайтовой записи, а буферизация файлов и тому подобное добавляют слишком много накладных расходов.

Что вы должны сделать, это разбить операцию:

import sys

blocksize = int(sys.argv[1])

chunk = b'\xff'*10000
with open("file.file", "wb") as f:
    for _ in range(blocksize // 10000):
        f.write(chunk)

Возможно, использование PyPy должно дать дополнительное (очень небольшое, возможно, отрицательное) ускорение.

Учтите, что ОС здесь будет влиять на тайминги, поэтому будет большая разница. Использование C может закончиться еще быстрее.


После некоторых таймингов это соответствует dd по скорости, так что вы не станете быстрее.

person Veedrac    schedule 20.09.2014
comment
Чем вы занимались таймингами? время.время() ? - person JahMyst; 20.09.2014
comment
Возможно, вы захотите сделать свои патроны равными по размеру размеру блока файловой системы, если вы это знаете. Если вы не уверены, насколько большой, часто хорошим предположением является 4 КБ. - person Blckknght; 20.09.2014
comment
Я запускаю linux на виртуальной машине, поэтому размер блока файловой системы равен размеру окна или linux? Считаете ли вы, что работа в виртуальной машине может иметь побочные эффекты для точности моего тайминга? - person JahMyst; 20.09.2014
comment
@JahMyst time python3/python2/pypy/pypy3 wite_blocks.py 100000000. - person Veedrac; 20.09.2014
comment
Пожалуйста, посмотрите отредактированный код, теперь мои результаты слишком высоки, и я не могу понять, почему. Я замерил время с помощью time.time(). Те же результаты с модулем timeit... - person JahMyst; 20.09.2014
comment
@JahMyst Я предлагаю вам использовать код, который я вам дал: P. Вы не закрываете файл, потому что ваш файл является глобальным. Использование with исправляет это. Это важно из-за того, что локальные кеши не очищаются. - person Veedrac; 20.09.2014

Что вам нужно для получения хороших результатов, так это использование низкоуровневого ввода-вывода для минимизации накладных расходов времени вызова и очистки буферов, иначе ваши записи могут быть где-то буферизованы (например, используемой вами ОС).

from time import perf_counter as time

def write_test(file, block_size, blocks_count):
    f = os.open(file, os.O_CREAT|os.O_WRONLY, 0o777) # low-level I/O

    took = []
    for i in range(blocks_count):
        buff = os.urandom(block_size) # get random bytes
        start = time()
        os.write(f, buff)
        os.fsync(f) # force write to disk
        t = time() - start
        took.append(t)

    os.close(f)
    return took

Этот код является частью моего хобби-проекта — упрощенного инструмента на Python для тестирования жестких дисков и твердотельных накопителей. Он полностью с открытым исходным кодом и сейчас находится в стадии альфа-тестирования, хотя вы уже можете его использовать и, если интересно, поучаствовать в разработке. Надеюсь, вы найдете несколько хороших идей или, может быть, даже предложите свои. Вот ссылка: https://github.com/thodnev/MonkeyTest

person thodnev    schedule 29.01.2016