Как написать большое количество маленьких файлов быстрее с потоками Python - PullRequest
1 голос
/ 05 июня 2019

Я хотел бы создать около 50000 файлов с использованием python, и это очень простые файлы с каждым файлом, содержащим менее 20 строк.

Сначала я попытался добавить потоки только ради этого, и потребовалось220 секунд на моем аппарате i7 8-го поколения.

С РЕЗЬБОЙ


def random_files(i):
    filepath = path+"/content/%s.html" %(str(i))
    fileobj = open(filepath,"w+")
    l1 = "---\n"
    l2 = 'title: "test"\n'
    l3 = "date: 2019-05-01T18:37:07+05:30"+"\n"
    l4 = "draft: false"+"\n"
    l5 = 'type: "statecity"'+"\n"
    l6 = "---"+"\n"
    data = l1+l2+l3+l4+l5+l6
    fileobj.writelines(data)
    fileobj.close()

if __name__ == "__main__":
    start_time = time.time()
    for i in range(0, 50000):
        i = str(i)
        threading.Thread(name='random_files', target=random_files, args=(i,)).start()
    print("--- %s seconds ---" % (time.time() - start_time))

БЕЗ РЕЗЬБЫ

Выполнение без нитиМаршрут занимает 55 секунд.

def random_files():
    for i in range(0, 50000):
        filepath = path+"/content/%s.html" %(str(i))
        fileobj = open(filepath,"w+")
        l1 = "---\n"
        l2 = 'title: "test"\n'
        l3 = "date: 2019-05-01T18:37:07+05:30"+"\n"
        l4 = "draft: false"+"\n"
        l5 = 'type: "statecity"'+"\n"
        l6 = "---"+"\n"
        data = l1+l2+l3+l4+l5+l6
        fileobj.writelines(data)
        fileobj.close()

if __name__ == "__main__":
    start_time = time.time()
    random_files()
    print("--- %s seconds ---" % (time.time() - start_time))

Загрузка ЦП составляет 10% для задачи Python. Использование ОЗУ - 50 МБ. Среднее использование диска - 4,5 МБ / с.

. Может ли скорость быть резко увеличена?

1 Ответ

1 голос
/ 05 июня 2019

Попробуйте распределить нагрузку с равным распределением нагрузки между всеми потоками в вашей системе.

Это обеспечивает почти линейное увеличение количества потоков, на которые распределяется нагрузка:

Без потоков:

~ 11% ЦП ~ 5 МБ / с. Диск

--- 69.15089249610901 секунд ---


С потоками: 4 потока

22% CPU 13MB / s Диск

--- 29.21335482597351 секунд ---


С Threading:8 потоков

27% ЦП 15 МБ / с Диск

--- 20,8521249294281 секунд ---


Например:

import time
from threading import Thread

def random_files(i):
    filepath = path+"/content/%s.html" %(str(i))
    fileobj = open(filepath,"w+")
    l1 = "---\n"
    l2 = 'title: "test"\n'
    l3 = "date: 2019-05-01T18:37:07+05:30"+"\n"
    l4 = "draft: false"+"\n"
    l5 = 'type: "statecity"'+"\n"
    l6 = "---"+"\n"
    data = l1+l2+l3+l4+l5+l6
    fileobj.writelines(data)
    fileobj.close()

def pool(start,number):
    for i in range(int(start),int(start+number)):
        random_files(i)

if __name__ == "__main__":
    start_time = time.time()
    num_files = 50000
    threads = 8
    batch_size = num_files/threads
    thread_list = [Thread(name='random_files', target=pool, args=(batch_size * thread_index ,batch_size)) for thread_index  in range(threads)]
    [t.start() for t in thread_list]
    [t.join() for t in thread_list] // simply required to wait for each of the threads to finish before stopping the timer

    print("--- %s seconds ---" % (time.time() - start_time))

Решение, предоставленное здесь, однако, является лишь примером, показывающим увеличение скорости, которое может быть достигнуто.Метод разделения файлов на пакеты работает только потому, что 50 000 файлов можно равномерно разделить на 8 пакетов (по одному для каждого потока), потребуется более надежное решение с функцией pool() для разделения нагрузки на пакеты.

Попробуйте взглянуть на этот пример SO разделения неравномерной нагрузки на потоки для примера.

Надеюсь, это поможет!

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