Максимальное разумное количество работающих потоков .

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Re: Максимальное разумное количество работающих потоков .

Сообщение Alex2013 » 15.05.2025 02:35:34

Возился с улучшением сетевой загрузки и пришел к "парадоксальному" выводу что "нафига козе баян" ...
Сильно упрощенная версия (Слегка быстрее и намного надежнее)...
Основная идея та же самая : "толстые" нити но в малом количестве.
Код: Выделить всё
TLoadableFileThread = class(TThread)
private
AName,  MSG: String;
fFileNames: TStringList;
AData : TMemoryStream;
FWork: Boolean;
procedure GetNext;
protected
  procedure Execute; override;
public
Procedure  SLog;
Procedure  SyncLog(M:String);
Procedure  SyncLoad;
Procedure  Load;
constructor Create(FileNames: TStringList);
destructor Destroy; override;
end;

Procedure  TLoadableFileThread.SLog;
begin
LSIForm.Memo3.Lines.Add(MSG);
end;
Procedure   TLoadableFileThread.SyncLoad;
begin
Application.ProcessMessages;
OneDraw(AName,AData);
end;
Procedure   TLoadableFileThread.Load;
var
  F:Integer;
  HTTPClient :TFPHttpClient;
begin
if (Pos('http://', LowerCase(AName)) > 0) or
   (Pos('https://', LowerCase(AName)) > 0)
then begin
  F :=  2; //2 попытки прочитать, если нужно.
  while F > 0 do begin
  HTTPClient := TFPHttpClient.Create(nil);
  AData := TMemoryStream.Create;
  try
    HTTPClient.Get(AName, AData);
    AData.Position := 0; //!! Сброс позиции в потоке  !!!
                        // (Без него ничего не работает )
    F:=-1;
  except
  Sleep(20);
   F:=F-1;
  end ;
  HTTPClient.Free;
end;
if F = 0 then FreeAndNil(AData);
Synchronize(SyncLoad);
AData.Free;
end
else
  begin
AData:=nil;
if  FileExists(Aname) then
  begin
    AData:=TMemoryStream.Create;
     try
       AData.LoadFromFile(AName);
       AData.Position := 0;
      except
       FreeAndNil( AData)
     end;
  end;
Synchronize(SyncLoad);
AData.Free;
end
end;

Procedure  TLoadableFileThread.SyncLog(M:String);
begin
MSG:=M;
Synchronize(Slog);
end;

constructor TLoadableFileThread.Create(FileNames: TStringList);
begin
inherited Create(True);
FreeOnTerminate := False;
AName := '';
fFileNames:=FileNames;
ind:=0;
FWork := False;
end;

destructor TLoadableFileThread.Destroy;
begin
FreeOnTerminate:=True;
if not Terminated then Terminate;
inherited Destroy;
tLoadders.Delete(tLoadders.IndexOf(Self));
//Для лучшего контроля завершения работы потока 
end;

procedure TLoadableFileThread.GetNext;
begin
FWork := False;

If  (fFileNames<>Nil) and
    (fFileNames.Count >0 )
then begin

EnterCriticalSection(x);
  AName:= fFileNames[0];
  fFileNames.Delete(0);
  FWork := fFileNames.Count>=0;

LeaveCriticalSection(x);
end else
begin
SyncLog(' Поток ' + IntToStr(ThreadID) + ' завершает работу');
FreeOnTerminate := True;
Terminate;

end;

end;
procedure TLoadableFileThread.Execute;
var
i: LongInt;
S:String;
FromInternet:Boolean;
begin
SyncLog('Запуск ...');
while not Terminated do begin
GetNext;
  if FWork then Load else sleep(iThreadWaitTimeout);
end;
end;

Почему надежнее ? Потому что обработка происходит сразу (точнее по мере поступления данных) что заметно экономит память .
А быстрее за счет уменьшения синхронизированного участка кода (по сути синхронизируется только непосредственно "внешняя обработка" в процедуре OneDraw ).

Еще добавил список потоков tLoadders удобная штука для контроля процесса загрузки (можно сделать прогресс бар ),аварийного завершения работы загрузчика, контроля завершения загрузки (так как элементы списка удаляются непосредственно в деструкторе никаких накладок быть не может ) и возможно своевременного уничтожения повисших нитей-потоков . (но там нужно хорошенько подумать как это можно сделать максимально надежно без ложного срабатывания если поток просто замедлился но не повис )
Alex2013
долгожитель
 
Сообщения: 3140
Зарегистрирован: 03.04.2013 11:59:44

Re: Максимальное разумное количество работающих потоков .

Сообщение Seenkao » 21.05.2025 15:48:23

Я вот занимаюсь эмулятором и портировал его на Android. Всё бы ни чего, но производительность желает лучшего (и первое подозрение пало именно на потоки). Я смотрел всё и всюду, чтоб убрать все недостатки с моей стороны, перелопатил код, который хотел переделать позже, изменил работу процессора. Ни чего не помогло, разница возможно в погрешности.

Дальше, смотря реализацию прорисовки данных на Android в ZenGL, я увидел эмуляцию инструкций для OpenGL (видел это давно, но руки не доходили переделать). В общем сейчас переделываю рендеринг на независимый от ZenGL, для получения ускорения и для того чтоб понять прав я или не прав.

К чему я это всё? Возможно где-то в коде у тебя нагрузка проявляется, которую ты не хочешь видеть или просто не видишь. Попробуй профилировщик, может он поможет выявить лишнюю нагрузку. И потоки могут оказаться не при чём. )))
Seenkao
энтузиаст
 
Сообщения: 560
Зарегистрирован: 01.04.2020 03:37:12

Re: Максимальное разумное количество работающих потоков .

Сообщение Alex2013 » 27.05.2025 13:07:31

Seenkao писал(а):К чему я это всё? Возможно где-то в коде у тебя нагрузка проявляется, которую ты не хочешь видеть или просто не видишь. Попробуй профилировщик, может он поможет выявить лишнюю нагрузку. И потоки могут оказаться не при чём. )))

К дождю! :wink: В принципе верно я уже неплохо оптимизировал однопоточный код так что он идет "ноздря к ноздре" к монгопоточному . :idea:
Alex2013
долгожитель
 
Сообщения: 3140
Зарегистрирован: 03.04.2013 11:59:44

Re: Максимальное разумное количество работающих потоков .

Сообщение Сквозняк » 28.05.2025 15:55:13

Alex2013 писал(а):однопоточный код так что он идет "ноздря к ноздре" к монгопоточному

А у процессора сколько потоков?
Сквозняк
энтузиаст
 
Сообщения: 1129
Зарегистрирован: 29.06.2006 22:08:32

Re: Максимальное разумное количество работающих потоков .

Сообщение Alex2013 » 29.05.2025 11:36:56

Сквозняк писал(а):А у процессора сколько потоков?

На одной железке 4 -е на другой 8-мь . (Но как я писал ускорение заметно лучше ощущается, при использовании на порядок большего количества "программных" потоков причем все работает без потери стабильности) Да, можно вместо "большего количества "программных" потоков " немного поднять приоритет исполнения потока, но это уже может заметно подтормаживать "внешнюю ОС". ( Хотя нужно проверить как это сказывается на новых версиях кода)

ЗЫ
Ускорение от использования "многопоточного режима" разумеется все рано есть но после оптимизации однопоточной загрузки оно уже скажем так "не сильно впечатляет".
Alex2013
долгожитель
 
Сообщения: 3140
Зарегистрирован: 03.04.2013 11:59:44

Re: Максимальное разумное количество работающих потоков .

Сообщение Seenkao » 29.05.2025 18:02:33

Alex2013 писал(а):после оптимизации однопоточной загрузки оно уже скажем так "не сильно впечатляет".

тут уже многопоточную работу надо оптимизировать. Производить загрузку данных -> отправлять данные на обработку + производить загрузку данных -> отправлять данные на обработку + производить загрузку данных -> ...

Точнее загрузку данных надо правильно распределить, чтоб они обрабатывались, пока грузятся следующие данные.
Seenkao
энтузиаст
 
Сообщения: 560
Зарегистрирован: 01.04.2020 03:37:12

Пред.

Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 254

Рейтинг@Mail.ru