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

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

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

Ответить
soulner
незнакомец
Сообщения: 3
Зарегистрирован: 29.11.2012 12:16:16
Откуда: г. Санкт-Петербург

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

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

Сообщение 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
svk12
постоялец
Сообщения: 411
Зарегистрирован: 09.06.2008 18:42:47

Сообщение svk12 »

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

Обработку исключений делаю так:

Код: Выделить всё

try
//Код, могущий вызвать исключение;
except on E:Exception do
  begin
  //Код реакции на исключение;
  end;
end;
soulner
незнакомец
Сообщения: 3
Зарегистрирован: 29.11.2012 12:16:16
Откуда: г. Санкт-Петербург

Сообщение soulner »

Спасибо за ответы. Только ситуация не в том, что я не умею обрабатывать исключительные ситуации в блоках try ... except, а в том, что при возникновении исключительной ситуации в блоке try ... except, работа программы затормаживается, причем весьма заметно, в Delphi такого не замечал, там, что было исключение, что не было скорость не менялась. Вот и вопрос: почему так происходит? Либо это особенности обработки исключительных ситуаций у FPC, тогда проще написать свои процедуры проверки чисел и дат на валидность, или это баг конкретной версии компилятора, тогда просто ждем новую версию.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
Сообщения: 1409
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Сообщение Sergei I. Gorelkin »

В FPC вход в блок try несколько медленнее чем в Дельфи (независимо от факта исключения), но собственно обработка программных исключений быстрее, т.к. все происходит в пределах программы, не задействуя ядро ОС.
Аватара пользователя
stikriz
энтузиаст
Сообщения: 612
Зарегистрирован: 15.03.2006 08:37:47

Сообщение 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;

Аватара пользователя
alexs
долгожитель
Сообщения: 4066
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь
Контактная информация:

Сообщение alexs »

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

Сообщение soulner »

Ок, спасибо. В общем, чем меньше исключений, тем быстрее прога. Буду учить матчасть.
yurix
незнакомец
Сообщения: 3
Зарегистрирован: 12.01.2013 02:44:53

Сообщение 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
Ответить