Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2006.12.17;
Скачать: [xml.tar.bz2];

Вниз

Потоки 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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.53 MB
Время: 0.051 c
2-1164798671
nali
2006-11-29 14:11
2006.12.17
Как спрятать форму при запуске программы?


2-1164758130
осеДЛаЛ
2006-11-29 02:55
2006.12.17
Как отлаживать dll ки ?


2-1164442220
Zlodey
2006-11-25 11:10
2006.12.17
HWND


9-1140506358
Древолаз
2006-02-21 10:19
2006.12.17
GLScene не найден Variants.dcu


3-1160466849
Dmitry_Chernov
2006-10-10 11:54
2006.12.17
Аналог периодического реквизита в Delphi





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский