В настоящее время я пишу программу, которая должна загружать более 13 000 файлов «*.json» разных размеров от нескольких строк до 100 000 строк. Чтение выглядит так:
[read_one_JSON(p) for p in filenames]
def read_one_JSON(path: str):
with open(path, encoding='utf-8') as fh:
data = json.load(fh)
return File(data["_File__name"], data['_File__statements'], data['_File__matches'])
Я загружаю файл, передаю его в класс File и читаю другой файл. В настоящее время это занимает около 2 минут 20 секунд. Я обнаружил, что когда я убираю обработку данных в класс и делаю просто:
[read_one_JSON(p) for p in filenames]
def read_one_JSON(path: str):
with open(path, encoding='utf-8') as fh:
data = json.load(fh)
Это сокращает время всего на 10 секунд до 2 минут и 10 секунд. Итак, затем я также удалил json.load, чтобы увидеть, что вызывает время чтения. Итак, при выезде просто:
[read_one_JSON(p) for p in filenames]
def read_one_JSON(path: str):
with open(path, encoding='utf-8') as fh:
и не считывая данные, он все еще длится 1 минуту 45 секунд. Это означает, что открытие файлов происходит медленно. Есть ли способ ускорить начальную часть процесса, не помещая все в один файл или распараллеливая? Это вариант, но я хотел бы знать, можно ли с этим что-то еще сделать.
Раньше я осознавал такое узкое место, я пробовал библиотеки, такие как ujson, orjson, msgpec, но, поскольку фаза открытия медленная, это имело лишь небольшие различия.
Это так, и я подаю заявку multiprocessing
в другой части программы. Сейчас мне просто интересно, существует ли что-то еще, о чем я еще не слышал, возможно, нет, так как я ничего не мог найти об этом. Если не будет ничего другого, я буду использовать многопроцессорность (возможно, даже когда я найду другое решение), я студент CS, поэтому каждое новое знание ценно.
Посмотрите, какая именно операция выполняется медленно — если это проблема с файловой системой, f/e, ее следует решать на уровне файловой системы, а не путем изменения кода Python вообще.
13K файлов за 105 секунд соответствует примерно 0,008 секунды на файл. Одна десятитысячная секунды не кажется особенно медленной.
Если вам нужен инструмент, который может выполнять трассировку с минимальными затратами для соответствующего анализа, я настоятельно рекомендую sysdig; он имеет встроенные «резцы» — Lua-скрипты, способные выполнять различные виды анализа, включая выявление операций с высокой задержкой.
Кстати, в зависимости от особенностей проводимого вами анализа вы можете подумать о переключении с набора отдельных файлов на индексированную базу данных. Существуют хранилища документов, хорошо оптимизированные для запросов к большим коллекциям документов с аналогичной структурой.
Создание 13000 файлов в текущем каталоге:
import json
from tqdm import tqdm # pip install tqdm
for i in tqdm(range(13_000)):
filename = f"data_{i}.json"
data = {"filename": filename}
with open(filename, "w") as file:
json.dump(data, file)
100%|██████████| 13000/13000 [00:01<00:00, 8183.74it/s]
Это означает, что на моем компьютере он работал менее 2 секунд. tqdm — это очень простой способ увидеть пропускную способность. Скрипт создал такие файлы, как:
{"filename": "data_0.json"}
Затем читаем их:
import json
from tqdm import tqdm # pip install tqdm
for i in tqdm(range(13_000)):
filename = f"data_{i}.json"
with open(filename, "rt") as file:
data = json.load(file)
print(data)
100%|██████████| 13000/13000 [00:00<00:00, 16472.00it/s]
{'filename': 'data_12999.json'}
Это означает, что все они были прочитаны менее чем за одну секунду.
Возможно, это происходит из-за размера файлов, которые вы читаете. Если у вас много больших файлов, действительно это займет больше времени. Но ваш диск не кажется единственной причиной медлительности.
Это может быть хорошим случаем для
multiprocessing
. Почему нет распараллеливания?