Страница 1 из 1
Очень медленный try
Добавлено: 29.11.2012 12:33:14
soulner
Добрый день. Очень нужна помощь. Недавно перешел с Delphi на Lazarus и столкнулся с непонятной ситуацией:
данные из одной базы нужно перегрузить в другую, перед этим данные надо проверить, проверяю так
Код: Выделить всё
try
float_val := strtofloat(str_val);
except
float_val := 0;
end;
вроде все логично, но проверок таких у меня очень много и все жутко тормозит.
Для того, чтобы удостовериться сделал так:
Код: Выделить всё
for i:=1 to 100 do
begin
try
float_val := strtofloat('AAA');
except
float_val := 0;
end;
end;
ответа вообще не дождаться. Подскажите, что я не так делаю. Может в FPC блоки try...except...end обрабатываются не так, как в Delphi?
Пробовал на Lazarus 1.0.2 x64, FPC 2.6.0
Re: Очень медленный try
Добавлено: 29.11.2012 12:43:18
Brainenjii
Код: Выделить всё
program Project1;
uses sysutils;
Var
i: Integer;
float_val: Extended;
begin
WriteLn('Hello world');
for i:=1 to 100 do
begin
try
float_val := strtofloat('AAA');
except
float_val := 0;
end;
end;
end.
bworkplace:~ # time /tmp/project
Hello world
real 0m0.002s
user 0m0.000s
sys 0m0.000s
как вариант можете попробовать воспользоваться StrToFloatDef
Re: Очень медленный try
Добавлено: 29.11.2012 13:35:24
svk12
TryStrToFloat не пробовали?
Обработку исключений делаю так:
Код: Выделить всё
try
//Код, могущий вызвать исключение;
except on E:Exception do
begin
//Код реакции на исключение;
end;
end;
Re: Очень медленный try
Добавлено: 29.11.2012 17:13:56
soulner
Спасибо за ответы. Только ситуация не в том, что я не умею обрабатывать исключительные ситуации в блоках try ... except, а в том, что при возникновении исключительной ситуации в блоке try ... except, работа программы затормаживается, причем весьма заметно, в Delphi такого не замечал, там, что было исключение, что не было скорость не менялась. Вот и вопрос: почему так происходит? Либо это особенности обработки исключительных ситуаций у FPC, тогда проще написать свои процедуры проверки чисел и дат на валидность, или это баг конкретной версии компилятора, тогда просто ждем новую версию.
Re: Очень медленный try
Добавлено: 30.11.2012 08:26:53
Sergei I. Gorelkin
В FPC вход в блок try несколько медленнее чем в Дельфи (независимо от факта исключения), но собственно обработка программных исключений быстрее, т.к. все происходит в пределах программы, не задействуя ядро ОС.
Re: Очень медленный try
Добавлено: 30.11.2012 22:50:33
stikriz
soulner писал(а):Спасибо за ответы.
Лучше парсить. Просто идеологически лучше.
Код: Выделить всё
...
UnNumberChars = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'];
TUnTypeConstantValue = (untnv_IntegerNumber, untnv_FloatNumber, untnv_String, untnv_Boolean);
UnConstValueChars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '-', '+', 'e', 'E'];
...
function CheckNumber(const AKeyWord: WideString; var ATypeValue: TUnTypeConstantValue; var AIntValue: Int64; var AFloatValue: Extended): boolean;
var I: Integer;
Step: Integer;
TempChar: WideChar;
IntString: WideString;
FracString: WideString;
ExponentString: WideString;
FracLength: Integer;
Negative: boolean;
NegativeExponent: boolean;
TmpValue: Extended;
begin
Result:=false;
if AKeyWord[1] = '$' then
begin
AIntValue:=ConvertToHex(AKeyWord);
ATypeValue:=untnv_IntegerNumber;
Result:=true;
Exit;
end;
Step:=0;
IntString:='0';
FracString:='0';
ExponentString:='0';
Negative:=false;
NegativeExponent:=false;
FracLength:=0;
for I:=1 to Length(AKeyWord) do
begin
TempChar:=AKeyWord[I];
Case Step of
0: begin
case TempChar of
'-': Negative:=true;
'+': ;
'.': begin
FracString:='';
Step:=2;
end;
else begin if TempChar in UnNumberChars then
begin
IntString:=TempChar;
Step:=1;
end
else // Неправильное число
Exit;
end;
end;
end;
1: begin // Набираем целую часть
if TempChar in UnNumberChars then
IntString:=IntString+TempChar
else
begin
case TempChar of
'.': begin
FracString:='';
Step:=2;
end;
'E', 'e': Step:=3;
else // Неправильное число
Exit;
end;
end;
end;
2: begin // Набираем дробную часть
if TempChar in UnNumberChars then
begin
FracString:=FracString+TempChar;
FracLength:=FracLength+1;
end
else
begin
case TempChar of
'E', 'e': Step:=3;
else // Неправильное число
Exit;
end;
end;
end;
3: begin // Набираем степень KeyWord: TypeKeyWord;
case TempChar of
'-': NegativeExponent:=true;
'+': ;
else begin if TempChar in UnNumberChars then
begin
ExponentString:=TempChar;
Step:=4;
end
else // Неправильное число
Exit;
end;
end;
end;
4: begin
if TempChar in UnNumberChars then
ExponentString:=ExponentString+TempChar
else // Неправильное число
Exit;
end;
end;
end;
AIntValue:=StrToInt(IntString);
AFloatValue:=StrToFloat(FracString)/Power(10, FracLength);
TmpValue:=StrToInt(ExponentString);
if TmpValue <> 0 then
begin
if NegativeExponent then
TmpValue:=power(10, - TmpValue)
else
TmpValue:=power(10, TmpValue);
TmpValue:=(AIntValue+AFloatValue)*TmpValue;
end
else
TmpValue:=(AIntValue+AFloatValue);
if Negative then
TmpValue:=-TmpValue;
if frac(TmpValue) <> 0 then
begin
ATypeValue:=untnv_FloatNumber;
AFloatValue:=TmpValue;
end
else
begin
ATypeValue:=untnv_IntegerNumber;
AIntValue:=trunc(TmpValue);
end;
Result:=true;
end;
function ConvertToHex(const AText: WideString): Int64;
var I, Q: Integer;
begin
Result:=0;
Q:=0;
for I:=Length(AText) downto 1 do
begin
case UpperCase(AText[I])[1] of
'0': Result:=Result;
'1': Result:=Result+Trunc(Power(16, Q))*1;
'2': Result:=Result+Trunc(Power(16, Q))*2;
'3': Result:=Result+Trunc(Power(16, Q))*3;
'4': Result:=Result+Trunc(Power(16, Q))*4;
'5': Result:=Result+Trunc(Power(16, Q))*5;
'6': Result:=Result+Trunc(Power(16, Q))*6;
'7': Result:=Result+Trunc(Power(16, Q))*7;
'8': Result:=Result+Trunc(Power(16, Q))*8;
'9': Result:=Result+Trunc(Power(16, Q))*9;
'A': Result:=Result+Trunc(Power(16, Q))*10;
'B': Result:=Result+Trunc(Power(16, Q))*11;
'C': Result:=Result+Trunc(Power(16, Q))*12;
'D': Result:=Result+Trunc(Power(16, Q))*13;
'E': Result:=Result+Trunc(Power(16, Q))*14;
'F': Result:=Result+Trunc(Power(16, Q))*15;
'$': begin
if I = 1 then
Exit
else
raise Exception.CreateFmt(Err_ConvertHex, [AText]);
end;
else raise Exception.CreateFmt(Err_ConvertHex, [AText]);
end;
Inc(Q);
end;
end;
Re: Очень медленный try
Добавлено: 01.12.2012 18:46:00
alexs
soulner
Воспользуйтесь процедурой VAL
Самы простой вариант и быстрый.
Re: Очень медленный try
Добавлено: 05.12.2012 13:10:57
soulner
Ок, спасибо. В общем, чем меньше исключений, тем быстрее прога. Буду учить матчасть.
Re: Очень медленный try
Добавлено: 06.03.2013 10:04:23
yurix
очень странно, подобный try-except код у меня выполняется очень быстро.
Код: Выделить всё
procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
f: Double;
t: tdatetime;
begin
t := now;
for i := 0 to 10000000 do
begin
try
f := strtofloat('aaa');
except
f := 111;
end;
end;
Button1.Caption := formatdatetime('nn:ss:zzz', now - t);
end;
Время выполнения чуть меньше 8 секунд. При том что без try-except, чисто f := strtofloat('111') выполняется около 1,5 сек. по-моему, неплохой результат. Это при запуске готового exe. По-моему это неплохо.
Правда если запускать выполнение из самого лазаруса (с галочкой "игнорировать этот тип исключений"), то реально недождаться, видимо сама отладка долгая.
_____________________
Lazarus 1.0.6, FPC 2.6, Windows 7 32bit