Как ускорить чтение из пакетов файлов - PullRequest
1 голос
/ 06 октября 2010

Я читаю много файлов из моей системы.Я хочу читать их быстрее, может быть так:

results=[]
for file in open("filenames.txt").readlines():
    results.append(open(file,"r").read())

Я не хочу использовать многопоточность.Любой совет приветствуется.

причина, по которой я не хочу использовать потоки, заключается в том, что это сделает мой код нечитаемым, я хочу найти такой хитрый способ сделать скорость быстрее, а код меньше, проще - 100*

вчера я тестировал другое решение с мультипроцессором, оно работает плохо, я не знаю почему, вот код следующим образом:

def xml2db(file):
    s=pq(open(file,"r").read())
    dict={}
    for field in g_fields:
        dict[field]=s("field[@name='%s']"%field).text()
    p=Product()
    for k,v in dict.iteritems():
        if v is None or v.strip()=="":
            pass
        else:
            if hasattr(p,k):
                setattr(p,k,v)
    session.commit()
@cost_time
@statistics_db
def batch_xml2db():
    from multiprocessing import Pool,Queue
    p=Pool(5)
    #q=Queue()
    files=glob.glob(g_filter)
    #for file in files:
    #    q.put(file)

    def P():
        while q.qsize()<>0:
            xml2db(q.get())
    p.map(xml2db,files)
    p.join()

Ответы [ 4 ]

1 голос
/ 06 октября 2010
results = [open(f.strip()).read() for f in open("filenames.txt").readlines()]

Это может быть незначительно быстрее, но, вероятно, менее читабельно (в зависимости от того, знакомы ли читатели со списком).

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

0 голосов
/ 10 октября 2010

Не уверен, что это тот код, который вы используете. Пара поправок, которые я хотел бы сделать.

Оригинал:

def xml2db(file):
    s=pq(open(file,"r").read())
    dict={}
    for field in g_fields:
        dict[field]=s("field[@name='%s']"%field).text()
    p=Product()
    for k,v in dict.iteritems():
        if v is None or v.strip()=="":
            pass
        else:
            if hasattr(p,k):
                setattr(p,k,v)
    session.commit()

Обновлено: удалите использование dict, это создание дополнительных объектов, итерация и сбор.

def xml2db(file):
    s=pq(open(file,"r").read())

    p=Product()
    for k in g_fields:
        v=s("field[@name='%s']"%field).text()
        if v is None or v.strip()=="":
            pass
        else:
            if hasattr(p,k):
                setattr(p,k,v)
    session.commit()

Вы можете профилировать код с помощью профилировщика Python.

Это может сказать вам, где проходит время. Это может быть в session.Commit () это может потребоваться уменьшить до каждой пары файлов.

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

Если вы можете разделить ваш код на чтение, обработку и запись. A) Вы можете видеть, сколько времени занимает чтение всех файлов.

Затем, загрузив один файл в память, достаточно времени для представления всей работы без дополнительного чтения IO. Б) Стоимость обработки

Затем сохраните целую кучу сессий, представляющих размер вашей работы. В) Стоимость продукции

Проверка стоимости каждого этапа в отдельности. Это должно показать вам, что занимает больше всего времени, и если какие-либо улучшения могут быть сделаны в любой области.

0 голосов
/ 07 октября 2010

Это разовое требование или что-то, что вам нужно делать регулярно? Если вы часто будете этим заниматься, рассмотрите возможность использования MySQL или другой базы данных вместо файловой системы.

0 голосов
/ 06 октября 2010

Ну, если вы хотите улучшить производительность, то улучшите алгоритм, верно? Что вы делаете со всеми этими данными? Вам действительно нужно все это в памяти одновременно, что может привести к OOM, если filenames.txt указывает на слишком большое или слишком большое количество файлов?

Если вы делаете это с большим количеством файлов, я подозреваю, что вы бьете, следовательно, ваше время 700 с + (1 час +). Даже мой бедный маленький HD может выдержать 42 МБ / с записи (42 * 714 с = 30 ГБ). Возьмите это зерно соли, зная, что вы должны читать и писать, но я предполагаю, что у вас нет более 8 ГБ ОЗУ для этого приложения. Соответствующий вопрос / ответ SO предложил вам использовать mmap, а ответ выше, который предложил итеративное / ленивое чтение, как то, что вы получаете в Haskell бесплатно. Вероятно, это стоит рассмотреть, если у вас действительно есть десятки гигабайт для взлома.

...