Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.12.17;
Скачать: CL | DM;

Вниз

Потоки TThread + быстродействие   Найти похожие ветки 

 
Darvin ©   (2006-11-22 16:44) [0]

Здравствуйте!
У меня в программе запускается четыре дополнительных потока, в которых осуществляется чтение данных от четырех внешних устройств. В потоках данные обрабатываются, а в основном потоке - отображаются. Загрузка процессора при этом достигает 97 - 99 %. Можно ли как-то уменьшить загрузку?

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

Поток данных от одного из устройств ~ 1300 байт / сек равномерно распределенных по времени.


 
Alexander Panov ©   (2006-11-22 16:53) [1]


> Darvin ©   (22.11.06 16:44) 


Надо смотреть реализацию.


 
Alexander Panov ©   (2006-11-22 16:53) [2]


> Darvin ©   (22.11.06 16:44) 


Надо смотреть реализацию.


 
Darvin ©   (2006-11-22 16:57) [3]

> Alexander Panov ©   (22.11.06 16:53) [2]
К сожалению, код в студию кинуть сложно, он разбросан по нескольку модулей предков - наследников, а также модули основного потока, тоже участвующие в процессе.
Могу добавить, что используется для обмена запросный протокол, я шлю команду устройству, в ответ на которую оно посылае данные.
Процессор - Sempron 3100, памяти -1 ГБ


 
RWolf ©   (2006-11-22 16:58) [4]


> Можно ли как-то уменьшить загрузку?

наверняка.


 
wal ©   (2006-11-22 16:59) [5]


> Можно ли как-то уменьшить загрузку?
Не крутить поток без толку, когда делать нечего, а ждать какого-либо события, которое покажет, что делать есть чего.


 
Darvin ©   (2006-11-22 17:01) [6]

>wal ©   (22.11.06 16:59) [5]
как остановить поток в цикле Execute?
я в нем вычитываю данные и, если вычитал, запускаю метод синхронизации


 
RWolf ©   (2006-11-22 17:02) [7]


> вычитываю данные

откуда и как?


 
DrPass ©   (2006-11-22 17:02) [8]


> я в нем вычитываю данные

Наверное ж вертишь бесконечный цикл? Без Sleep, и приоритет у него повыше, чем Idle, да?


 
Чапаев ©   (2006-11-22 17:03) [9]

> [0] Darvin ©   (22.11.06 16:44)
Небось, читаешь непрерывно? Или делай в цикле Sleep(), или разбирайся с асинхронным вводов-выводом.


 
Чапаев ©   (2006-11-22 17:03) [10]

> [8] DrPass ©   (22.11.06 17:02)
Без слипа и идл 100 процентов схавает... :-)


 
wal ©   (2006-11-22 17:06) [11]


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


 
Darvin ©   (2006-11-22 17:09) [12]

ясно, спасибо, буду разбираться


 
Darvin ©   (2006-11-23 11:35) [13]

Интересный эффект : Если фокус ввода на модальной форме, отображающей данные, то загрузка - 100%, а если переместить его на другую форму (создать по команде), то загрузка не более 20%.
Из-за чего такое может быть?


 
oxffff ©   (2006-11-23 11:40) [14]

Как ты считываешь данные с устройства.

Какой у тебя метод опроса устройства.

Poll или asynchronously?


 
Darvin ©   (2006-11-23 11:45) [15]

> oxffff ©   (23.11.06 11:40) [14]
Передается по Com-порту или USB (FTDI) команда запроса и после нее читаются данные из порта


 
oxffff ©   (2006-11-23 11:47) [16]


> Darvin ©   (23.11.06 11:45) [15]
> > oxffff ©   (23.11.06 11:40) [14]
> Передается по Com-порту или USB (FTDI) команда запроса и
> после нее читаются данные из порта


Хорошо. Спросим по другому.

Не мог бы ты привести код.


 
Darvin ©   (2006-11-23 11:56) [17]

Выполняется в доп. потоке:
   TSeat_02(Owner).DataRequest;   // Запрос данных

   // Чтение признака готовности данных
   if Read ( aBufInp, 1 ) then begin
     if aBufInp[0] = iCodeDataReady then begin
       // Чтение пакета
       if Read ( aBufInp, TSeat_02(Owner).PartLength - 1 ) then begin  
         Count := aBufInp[0];          // Кол-во байт в пакете
         Move ( aBufInp[0], aBuf[0], Count - 1 );
         Result := drdOK;
       end
       else
         Result := drdError;
     end
     else   // Прочли код "Нет данных"
     if aBufInp[0] = iCodeNoData then begin
       FNoDataTimeOut := GetTickCount;
       Result := drdNoData
     end
     else
       Result := drdUnknown;
   end
   else
     Result := drdError;

Используемые процедуры:

procedure TSeat_02.DataRequest;
var
 aCmd : TReadBuffer;
begin
 aCmd[0] := iCodeCmdPrefix;
 aCmd[1] := iCodeRequest;
 Write ( aCmd, 2 );
end;  // of TSeat_02.DataRequest

function TInputData_B.Read ( var aBuf : TReadBuffer; aSizeBuf : Integer ) : Boolean;
begin
 Result := false;

 // Через COM порт
 if FOwner.FCPoint in [cpCOM1, cpCOM2, cpCOM3, cpCOM4] then begin    
   if FOwner.FComm <> nil then begin
     Result := FOwner.FComm.Read ( aBuf, aSizeBuf );
     {$IFDEF LOG_INPUT}
     for I:=0 to aSizeBuf - 1 do
       Writeln(Owner.F, IntToStr(aBuf[I]));
     {$ENDIF}
   end;
 end
 else
 if FOwner.FCPoint = cpUSB then begin                                // Через USB
   if FOwner.FUSB <> nil then
     Result := FOwner.FUSB.ReadFromDevice ( @aBuf, aSizeBuf, 100 );
 end
end;  // of TInputData_B.Read

procedure TDriverExt_B.Write ( aBuf : TReadBuffer; aSizeBuf : Integer );
begin
 // Через COM порт
 if FCPoint in [cpCOM1, cpCOM2, cpCOM3, cpCOM4] then begin    
   if FComm <> NIL then
     FComm.Write ( aBuf, aSizeBuf );
 end
 else
 if FCPoint = cpUSB then begin                                // Через USB
   if FUSB <> NIL then
     FUSB.WriteToDevice ( @aBuf, aSizeBuf );
 end
end;  // TDriverExt_B.Write


 
oxffff ©   (2006-11-23 12:11) [18]

Где, и как у тебя используется  FNoDataTimeOut := GetTickCount;


 
oxffff ©   (2006-11-23 12:21) [19]

Как ты опрашиваешь устройство?
Раз в секунду?
Или постоянно?


 
Darvin ©   (2006-11-23 12:36) [20]

> Где, и как у тебя используется  FNoDataTimeOut := GetTickCount;

 FCurTickCount := GetTickCount;
 FCurTickCount := FCurTickCount - FNoDataTimeOut;

 if FCurTickCount > iDelayRead then begin
   Первфй кусок из  Darvin ©   (23.11.06 11:56) [17]
 end
 else begin
   Sleep(3);   // Для исключения загрузки процессора
   Result := drdNoData;
 end;

> Как ты опрашиваешь устройство? Раз в секунду? Или постоянно?
Постоянно. Приведенный выше код работае в методе Execute потока


 
oxffff ©   (2006-11-23 12:57) [21]

Что типа этого

while true do
 FCurTickCount := GetTickCount;
 FCurTickCount := FCurTickCount - FNoDataTimeOut;
 if FCurTickCount > iDelayRead then begin
  Первфй кусок из  Darvin ©   (23.11.06 11:56) [17]
end
else begin
  Sleep(3);   // Для исключения загрузки процессора
  Result := drdNoData;
end;
end;

чему равен  iDelayRead?

Sleep(3)?
Даже указав 3, поток уснет больше, чем на 3 миллисекунды,
где-то на 15-80 миллисекунд.


 
Darvin ©   (2006-11-23 13:06) [22]

iDelayRead = 10


 
oxffff ©   (2006-11-23 13:20) [23]

function ThreadFunc(d:pointer):DWORD;stdcall;
var a,b:DWORD;
   tid:DWORD;
begin
a:=GetTickCount;
while true do
begin
b:=GetTickCount;
if (b-a)>10 then a:=b else sleep(3);
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var tid:DWORD;
begin
CreateThread(nil,0,@ThreadFunc,nil,0,tid);
end;

Хотя этот код вообще не вызывает нагрузку на процессор.
Загрузка 0

Видимо придется искать в другом месте


 
oxffff ©   (2006-11-23 13:26) [24]

Только при 50 потоках.
Загрузка 5%.


 
Darvin ©   (2006-11-23 13:35) [25]

Повторю пост : Darvin ©   (23.11.06 11:35) [13]
Интересный эффект : Если фокус ввода на модальной форме, отображающей данные, то загрузка - 100%, а если переместить его на другую форму (создать по команде), то загрузка не более 20%.
Из-за чего такое может быть?


 
ANB ©   (2006-11-23 13:58) [26]


> Из-за чего такое может быть?

винда приоритет твоему процессу понизила, т.к. считает, что он не активный, а фоновый.


 
ANB ©   (2006-11-23 13:59) [27]

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


 
SlymRO   (2006-11-24 04:44) [28]

Darvin ©   (23.11.06 13:35) [25]
Если фокус ввода на модальной форме, отображающей данные, то загрузка

WM_PAINT :)
в окно как часто унфу обновляешь? если раз 100 в сек и 5 контролов - репаинтить будет 500 раз в сек:)
Обновляй реже, 1-5 раз в сек.
Вырезка из моего:
procedure TDefaultProgressForm.SetPosition(const Value: Int64);
var CurTick,DeltaTick:Longword;
begin
 FPosition:=Value;
 CurTick:=GetTickCount;
 if (FPosition<>FMax) and (Abs(CurTick-LastUpdTick)<UpdateTime) then exit;
 LastUpdTick:=CurTick;
 Progress.Position:=Trunc(FPosition/FMax*Progress.Max);
 CurrentVal.Caption:=IntToStr(FPosition);
 if FPosition>0 then
 begin
   DeltaTick:=CurTick-StartTick;
   PassedTime.Caption:=MsecToTime(DeltaTick);
   TotalTime.Caption:=MsecToTime(Trunc(FMax/FPosition*DeltaTick));
 end else
 begin
   StartTick:=CurTick;
   FCanceled:=false;
   PassedTime.Caption:=MsecToTime(0);
   TotalTime.Caption:=MsecToTime(0);
 end;
end;


 
SlymRO   (2006-11-24 04:47) [29]

Анатолич может мировую... Через аноним посты режет :(
Retry...
Darvin ©   (23.11.06 13:35) [25]
Если фокус ввода на модальной форме, отображающей данные, то загрузка
WM_PAINT :)
в окно как часто унфу обновляешь? если раз 100 в сек и 5 контролов - репаинтить будет 500 раз в сек:)
Обновляй реже, 1-5 раз в сек.
Вырезка из моего:
procedure TDefaultProgressForm.SetPosition(const Value: Int64);
var CurTick,DeltaTick:Longword;
begin
 FPosition:=Value;
 CurTick:=GetTickCount;
 if (FPosition<>FMax) and (Abs(CurTick-LastUpdTick)<UpdateTime) then exit;
 LastUpdTick:=CurTick;
 Progress.Position:=Trunc(FPosition/FMax*Progress.Max);
 CurrentVal.Caption:=IntToStr(FPosition);
 if FPosition>0 then
 begin
   DeltaTick:=CurTick-StartTick;
   PassedTime.Caption:=MsecToTime(DeltaTick);
   TotalTime.Caption:=MsecToTime(Trunc(FMax/FPosition*DeltaTick));
 end else
 begin
   StartTick:=CurTick;
   FCanceled:=false;
   PassedTime.Caption:=MsecToTime(0);
   TotalTime.Caption:=MsecToTime(0);
 end;
end;



Страницы: 1 вся ветка

Текущий архив: 2006.12.17;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.054 c
2-1164686543
DROWSY
2006-11-28 07:02
2006.12.17
Delphyi 6: delphi32.exe- Точка входа не найдена.


15-1164606305
Тульский
2006-11-27 08:45
2006.12.17
Кидалово с жильем


15-1164391910
Колдун
2006-11-24 21:11
2006.12.17
К555РУ2


15-1164629045
Cyrax
2006-11-27 15:04
2006.12.17
Какой антивирус наиболее удобен ?


6-1153812560
Kacnep
2006-07-25 11:29
2006.12.17
Динамическая привязка OnConnect в КОНСОЛЬНОМ приложении