Очень медленный try

Общие вопросы программирования, алгоритмы и т.п.

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

Очень медленный try

Сообщение soulner » 29.11.2012 12:33:14

Добрый день. Очень нужна помощь. Недавно перешел с 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
soulner
незнакомец
 
Сообщения: 3
Зарегистрирован: 29.11.2012 12:16:16
Откуда: г. Санкт-Петербург

Re: Очень медленный try

Сообщение Brainenjii » 29.11.2012 12:43:18

Код: Выделить всё
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
Аватара пользователя
Brainenjii
энтузиаст
 
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Re: Очень медленный try

Сообщение svk12 » 29.11.2012 13:35:24

TryStrToFloat не пробовали?

Обработку исключений делаю так:
Код: Выделить всё
try
//Код, могущий вызвать исключение;
except on E:Exception do
  begin
  //Код реакции на исключение;
  end;
end;
svk12
постоялец
 
Сообщения: 408
Зарегистрирован: 09.06.2008 18:42:47

Re: Очень медленный try

Сообщение soulner » 29.11.2012 17:13:56

Спасибо за ответы. Только ситуация не в том, что я не умею обрабатывать исключительные ситуации в блоках try ... except, а в том, что при возникновении исключительной ситуации в блоке try ... except, работа программы затормаживается, причем весьма заметно, в Delphi такого не замечал, там, что было исключение, что не было скорость не менялась. Вот и вопрос: почему так происходит? Либо это особенности обработки исключительных ситуаций у FPC, тогда проще написать свои процедуры проверки чисел и дат на валидность, или это баг конкретной версии компилятора, тогда просто ждем новую версию.
soulner
незнакомец
 
Сообщения: 3
Зарегистрирован: 29.11.2012 12:16:16
Откуда: г. Санкт-Петербург

Re: Очень медленный try

Сообщение Sergei I. Gorelkin » 30.11.2012 08:26:53

В FPC вход в блок try несколько медленнее чем в Дельфи (независимо от факта исключения), но собственно обработка программных исключений быстрее, т.к. все происходит в пределах программы, не задействуя ядро ОС.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Очень медленный try

Сообщение stikriz » 30.11.2012 22:50:33

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;

Аватара пользователя
stikriz
энтузиаст
 
Сообщения: 612
Зарегистрирован: 15.03.2006 09:37:47

Re: Очень медленный try

Сообщение alexs » 01.12.2012 18:46:00

soulner
Воспользуйтесь процедурой VAL
Самы простой вариант и быстрый.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Очень медленный try

Сообщение soulner » 05.12.2012 13:10:57

Ок, спасибо. В общем, чем меньше исключений, тем быстрее прога. Буду учить матчасть.
soulner
незнакомец
 
Сообщения: 3
Зарегистрирован: 29.11.2012 12:16:16
Откуда: г. Санкт-Петербург

Re: Очень медленный try

Сообщение yurix » 06.03.2013 10:04:23

очень странно, подобный 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
yurix
незнакомец
 
Сообщения: 3
Зарегистрирован: 12.01.2013 02:44:53


Вернуться в Общее

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

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

Рейтинг@Mail.ru