Форум: "Прочее";
Текущий архив: 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