Модераторы: Poseidon, Snowy, bems, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Текстовые файлы, скорость обработки, Текстовые файлы, скорость обработки 
:(
    Опции темы
alexpotemkin
  Дата 9.9.2008, 13:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 76
Регистрация: 21.11.2006

Репутация: нет
Всего: нет



Господа посоветуйте как максимально ускорить следующий процесс (на данный момент простой цикл, сборка списка файлов, потом обработка по списку): есть энное количество текстовых файлов (может и тысяча быть, а может и всего десяток), мне нужно их открыть (сейчас читаю в tstringlist), далее выполнить операции (замены, удаления), после сохранить файл.
Уместно ли использование потоков для ускорения процесса обработки? Уменьшит ли это время обработки? Что еще можно сделать для ощутимомго ускорения операций. При работе со строками (замены, удаления)  использую функции из QStrings.

Это сообщение отредактировал(а) alexpotemkin - 9.9.2008, 13:20
PM MAIL   Вверх
Poseidon
Дата 9.9.2008, 13:25 (ссылка) |    (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

Репутация: 53
Всего: 133



Ты бы не описал принцип работы, а код показал. А мы тебе его бы "ускорили" smile На вскидку, поток с завышенным приорететом в любом случае будет быстрее  smile 


--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
alexpotemkin
  Дата 9.9.2008, 14:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 76
Регистрация: 21.11.2006

Репутация: нет
Всего: нет



дабы не приводить весь код, примерно так все выглядит (обрежу для упрощения, обработчиков исключительных ситуаций тоже обрежу):

Код

function GetFileList(path: String): TStrings;
...
var i: Integer; 
    txt: String;
    filelist,list: TStringList;
begin
  filelist := TStringList.Create;
  list := TStringList.Create;
  filelist.Assign(GetFileList('какой то путь'));
  for i := 0 to filelist.Count - 1 do begin
     txt := '';
     list.Clear;
     list.LoadFromFile(filelist.strings[i]);
     txt := list.Text;
     // тут рэплейсим чего нибудь например
     txt := QReplace_Str(txt,'шыло','мыло');
     // тут рэплейсим чего нибудь например
     list.Text := txt;
  end; 
  filelist.Free;
  list.Free;
end;
...



Это сообщение отредактировал(а) alexpotemkin - 9.9.2008, 14:21
PM MAIL   Вверх
Alexeis
Дата 9.9.2008, 14:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



Грамотное использование потоков ускоряет работу, если разделить по потокам загрузку из файла и текстовую обработку. Т.е. полезным будет создание еще 2х потоков. 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
alexpotemkin
Дата 9.9.2008, 14:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 76
Регистрация: 21.11.2006

Репутация: нет
Всего: нет



Алексис, а можно чуть подробней?
PM MAIL   Вверх
Poseidon
Дата 9.9.2008, 14:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

Репутация: 53
Всего: 133



alexpotemkin, конкретно по приведенному коду:
  • list.Clear ни к чему там. Там заведомо известно что list чиста
  • я бы отказался от переменной txt
    Код
    list.Text:= QReplace_Str(list.Text, 'шыло', 'мыло');
  • Alexeis дело говорит smile В то время пока один поток загружал бы список файлов, второй (или вторые) мог бы уже эти файлы обрабатывать. Так же можно весь список файлов разбить, допустим, пополам и уже двумя потоками обрабатывать одновременно.



--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
alexpotemkin
  Дата 9.9.2008, 15:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 76
Регистрация: 21.11.2006

Репутация: нет
Всего: нет



txt вводил только ради ускорения работы с переменной, т.к. думал что обращение к переменной по определению будет быстрей чем обращение к list.Text.
По поводу рекомендаций: т.е. мне стоит в одном потоке собрать список, далее этот список разделить на двое и двумя потоками обработать замены. Правильно понял?
Напомните линку на стутью по поводу потоков, здесь была, не могу найти.
PM MAIL   Вверх
Poseidon
Дата 9.9.2008, 15:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

Репутация: 53
Всего: 133



Цитата(alexpotemkin @  9.9.2008,  15:29 Найти цитируемый пост)
По поводу рекомендаций: т.е. мне стоит в одном потоке собрать список, далее этот список разделить на двое и двумя потоками обработать замены. Правильно понял?
Не совсем. Я бы сделал так: в то время пока один поток собирает данные о файлах, другие уже начинают работать с этим списком.



Цитата(alexpotemkin @  9.9.2008,  15:29 Найти цитируемый пост)
Напомните линку на стутью по поводу потоков, здесь была, не могу найти.
http://forum.vingrad.ru/forum/topic-60076.html



--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
alexpotemkin
  Дата 9.9.2008, 15:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 76
Регистрация: 21.11.2006

Репутация: нет
Всего: нет



Цитата

другие уже начинают работать с этим списком

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

PM MAIL   Вверх
Poseidon
Дата 9.9.2008, 15:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

Репутация: 53
Всего: 133



Цитата(alexpotemkin @  9.9.2008,  15:45 Найти цитируемый пост)
как тогда делить список между потоками, если еще первый находится в процессе работы, т.е. список еще не готов?
А как захочешь. Можешь - четные одному потоку, не четные - другому. Можешь - первые 100 одному, следующие 100 второму, следующие 100 третьему, следующие 100 опять первому и т.п. Тут уже решать тебе. Идея в том, что бы обрабатывающие потоки работали одновременно.



--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
Alexeis
Дата 9.9.2008, 16:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



Финт в том, что во время загрузки с винта, работает винт, а проц немного простаивает, в это время его можно пригрузить. Нужно делать что-то типа буферного массива файлов и создать 2 семафора. Как только файл прочитался первый семафор инкриметировался, а второй поток ждет семафора. Пока первый семафор не в нулевом состоянии WaitForSingleObject будет выполняться без задержки, если файлов нет то второй поток уснет. Еще понадобиться второй семафор, который изначально будет инициализирован числом элементов буферного массива. По мере заполнения массива 1й поток будет проходить через WaitForSingleObject и ждать второго семафора, с каждым проходом будет проходить декремент второго семафора, второй же поток по окончанию обработки своего текста будет сигнализировать второй семафор тем самым освобождая ячейку буферного массива.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
CodeMonkey
Дата 9.9.2008, 16:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 38
Всего: 89



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

С алгоритмом:
Цитата(alexpotemkin @  9.9.2008,  14:17 Найти цитируемый пост)
 filelist.Assign(GetFileList('какой то путь'));

Уверены, что здесь нет утечки?

Далее:
Цитата(alexpotemkin @  9.9.2008,  14:17 Найти цитируемый пост)
 
Код
    list.Clear;
     list.LoadFromFile(filelist.strings[i]);
     txt := list.Text;     
     // тут рэплейсим чего нибудь например     
     txt := QReplace_Str(txt,'шыло','мыло');     
     // тут рэплейсим чего нибудь например     
     list.Text := txt;


Зачем вы гоняете данные из списка в переменную и обратно? Выбросите список, грузите сразу в txt, а ещё лучше - используйте проекции файлов. Правда, в последнем случае вам понадобятся ещё и соответствующие варианты функций QReplace_Str, которые вместо String на вход принимают указатель + размер. Но если ваши искомые и заменяемые строки не соответствуют друг другу по длине, то от проекции придётся отказаться.



--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Alexeis
Дата 9.9.2008, 17:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



CodeMonkey, прав тут оптимизировать и оптимизировать. Нужно заменять построчно, чтобы не гонять большие куски данных в памяти. Операция  txt := list.Text;  и list.Text := txt; занимает огромную кучу времени, а txt := QReplace_Str(txt,'шыло','мыло');  еще больше.

Добавлено через 5 минут и 36 секунд
А вообще быстрее всего будет сразу загрузить текст в одну длинную строку, подсчитать число замен, выделить новую строку нужной длинны, затем копировать последовательно, сначала неизменный фрагмент, потом слово которое нужно заменить, потом опять неизменный и т.д. Каждое выделение памяти медленная операция.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Riply
Дата 9.9.2008, 17:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Комодератор
Сообщений: 572
Регистрация: 27.3.2007
Где: St. Petersburg

Репутация: 3
Всего: 32



Я бы вообще выкинула все list`ы к чертовой бабушке и работала с файлом как с цельным блоком данных.  smile 
Конечно придется повозиться, но
1. В этом нет ничего сложного - стандартные алгоритмы.
2. Выигрыш в быстродействии реален не в разы а на порядки.
PM MAIL   Вверх
Matematik
Дата 9.9.2008, 22:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1027
Регистрация: 11.3.2006

Репутация: 17
Всего: 50



> вообще быстрее всего будет сразу загрузить текст в одну длинную строку,
Ага
Будет чуть быстрее

Код

function LoadStringFromFile(const AFileName:AnsiString):AnsiString;
var f : TFileStream;
begin
  f := TFileStream.Create(AFileName, fmOpenRead); // открыть файл   
  try
    SetLength(Result, f.Size); // взять память под стринг
    f.Read(Pointer(result)^, f.Size); // читать из файла в стринг
  finally
    f.Free // мало ли что случится, файл закроется
  end;
end;
procedure SaveStringToFile(const AFileName,ABuffer:AnsiString);
var f : TFileStream;
begin
  f := TFileStream.Create(AFileName, fmCreate); // создать файл
  try
    f.Write(Pointer(ABuffer)^, Length(ABuffer)); // записать стринг
  finally
    f.Free; // закрыть файл
  end;
end;
{...}
  for i := 0 to filelist.Count - 1 do begin
    txt := LoadStringFromFile(filelist.strings[i]);
    txt := QReplace_Str(txt, 'шыло', 'мыло');
    SaveStringToFile(filelist.strings[i], txt);
  end; 




PM MAIL WWW ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0735 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.