Recent

Author Topic: IntToStr / StrToInt Perf issues VS Delphi?  (Read 15920 times)

dieselfan

  • New Member
  • *
  • Posts: 16
IntToStr / StrToInt Perf issues VS Delphi?
« on: August 13, 2015, 12:50:29 pm »
So I have this simple code with 3 tests
1.
******
  for x := 0 to StrToInt(edit1.Text) do begin
    s := IntToStr(x);
  end;
******
2.
******
  lMax := StrToInt(edit1.Text);
  for x := 0 to lMax do begin
    s := IntToStr(x);
  end; 
******
3.
******
  lMax := StrToInt(edit1.Text);
  repeat
    Inc(x)
  until x = lMax;   
******
Then I record time taken using GetTickCount.

I compiled with D7, XE2, XE7 and (FPC  2.6.4, Laz 1.4.2 - Fedora 22). The times for the EXE's under Win10 and Wine on Fedora 22 were negligible. The FPC was run native on Fedora.

In the order (D7, XE2, XE7, FPC + Laz) in seconds.
1)  10 000 000 loops
1.161, 0.287, 0.298, 1.424
2) 10 000 000 loops
1.464, 0.326, 0.315, 1.449

3) 1 000 000 000 loops
0.54, 0.539, 0.541, 1.865

Then I increased the loops for  code 1, 2 by one "0"

1) 100 000 000 loops
16.4, 2.81, 2.873, 15.007

The importance here is at the basic variable level ie string and integers. FPC appears to be significantly slower. When dealing with larger datasets and database access ie we have to convert EACH DB datatype to display in a grid or export as CSV, XML etc. as well as basic integer FOR and REPEAT loops. If the basic "low" level variables are upto 5x slower the resulting complex app should be too. Keep in mind a table might not have 100 000 000 records but you could deal with that amount of strings, when your tables have quite a few fields etc. and longer strings not just couple chars.

As you can see it appears as if D7 and FPC are similar in string handling but with straight integer loops D7 - > XE7 are almost 3x faster and XE2+ almost 5x faster with string conversion.

I can post the whole code if need be and DFM etc.

Anyways I'd appreciate some feedback / comments.
Specs are i7, 16GB 2000Mhz. Fedora 22 64bit OS. Windows 7/10 and Wine.
AMD 1800X
Manjaro KDE
Rarely Windows 10 Pro

eny

  • Hero Member
  • *****
  • Posts: 1634
Re: IntToStr / StrToInt Perf issues VS Delphi?
« Reply #1 on: August 13, 2015, 01:06:02 pm »
Is there any underlying problem?

I can post the whole code if need be and DFM
Please do so (the Lazarus code that is) so we can verify the results.
Maybe it's just a compiler setting...
All posts based on: Win10 (Win64); Lazarus 2.0.10 'stable' (x64) unless specified otherwise...

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11447
  • FPC developer.
Re: IntToStr / StrToInt Perf issues VS Delphi?
« Reply #2 on: August 13, 2015, 01:10:01 pm »
Your conclusions are based on weak benchmarks.

The problem is that your examples are very simple, and you don't specify any settings that you use (optimization etc). Also comparison with 3.x -O4 would be nice.

Sometimes compilers might detect that the result of "s" is never used and simply omit the whole inttostr step, or replace the whole repeat-until with "x=lmax".

That's why scaling such microbenchmarks to "real" performance is relatively useless for real world performance where hopefully the amount of code that does nothing is low.

Benchmarking and interpreting the results is an art, and it actually quite hard to get meaningful results.

I really would like to see an indepth Delphi vs FPC (with both several versions) benchmark, but I'm afraid that would be a truckload of work.

dieselfan

  • New Member
  • *
  • Posts: 16
Re: IntToStr / StrToInt Perf issues VS Delphi?
« Reply #3 on: August 13, 2015, 01:14:32 pm »
same code as Delphi
**********
procedure TForm1.Button1Click(Sender: TObject);
var x: integer;
  s: string;
  lT: cardinal;
begin
  lT := GetTickCount;
  for x := 0 to StrToInt(edit1.Text) do begin
    s := IntToStr(x);
  end;
  lT := GetTickCount - lT;
  label1.Caption := Format('%s, It took %.3f secs', [s, lT / 1000]);
  memo1.Lines.Add(label1.Caption);
end;

procedure TForm1.Button2Click(Sender: TObject);
var x, lMax: integer;
  s: string;
  lT: cardinal;
begin
  lT := GetTickCount;
  lMax := StrToInt(edit1.Text);
  for x := 0 to lMax do begin
    s := IntToStr(x);
  end;
  lT := GetTickCount - lT;
  label1.Caption := Format('%s, It took %.3f secs', [s, lT / 1000]);
  memo1.Lines.Add(label1.Caption);
end;

procedure TForm1.Button4Click(Sender: TObject);
var x, lMax: integer;
  s: string;
  lT: cardinal;
begin
  lT := GetTickCount;
  x := 0;
  lMax := StrToInt(edit1.Text);
  s := edit1.text;
  repeat
    Inc(x)
  until x = lMax;
  lT := GetTickCount - lT;
  label1.Caption := Format('%s, It took %.3f secs', [s, lT / 1000]);
  memo1.Lines.Add(label1.Caption);
end;
**********
It's a proof of concept problem. I consult to a firm using Delphi with some pretty big DB's. I am investigating Laz, FPC as an option. The above code while not optimal, demonstrates how I would think many people code. The problem if sorted out now will prevent an issue later. 3-5x slower is a hard sell. I fully appreciate the work done here and on FPC, but hopefully it will be seen as constructive feedback or perhaps a compiler option missing ;).
AMD 1800X
Manjaro KDE
Rarely Windows 10 Pro

dieselfan

  • New Member
  • *
  • Posts: 16
Re: IntToStr / StrToInt Perf issues VS Delphi?
« Reply #4 on: August 13, 2015, 01:16:54 pm »
Your conclusions are based on weak benchmarks.

The problem is that your examples are very simple, and you don't specify any settings that you use (optimization etc). Also comparison with 3.x -O4 would be nice.

Sometimes compilers might detect that the result of "s" is never used and simply omit the whole inttostr step, or replace the whole repeat-until with "x=lmax".

That's why scaling such microbenchmarks to "real" performance is relatively useless for real world performance where hopefully the amount of code that does nothing is low.

Benchmarking and interpreting the results is an art, and it actually quite hard to get meaningful results.

I really would like to see an indepth Delphi vs FPC (with both several versions) benchmark, but I'm afraid that would be a truckload of work.
My experience with FPC and Laz is limited. I would welcome suggestions.

"Sometimes compilers might detect that the result of "s" is never used and simply omit the whole inttostr step, or replace the whole repeat-until with "x=lmax"."

I agree, compilers *might* but it still showed consistent results. FWIW, I ran each at default ide settings
« Last Edit: August 13, 2015, 01:20:02 pm by dieselfan »
AMD 1800X
Manjaro KDE
Rarely Windows 10 Pro

Handoko

  • Hero Member
  • *****
  • Posts: 5151
  • My goal: build my own game engine using Lazarus
Re: IntToStr / StrToInt Perf issues VS Delphi?
« Reply #5 on: August 13, 2015, 01:43:05 pm »
Interesting to know that FPC/Lazarus is slower than Delphi/XE..

Can you please share the Lazarus file rather than the code? There are many configurable settings can be adjusted to make the result code run faster. The default Lazarus settings are not optimize for speed.

eny

  • Hero Member
  • *****
  • Posts: 1634
Re: IntToStr / StrToInt Perf issues VS Delphi?
« Reply #6 on: August 13, 2015, 01:52:23 pm »
More fruit: your three scenario's for 100.000.000:
100000000, It took 5,985 secs
100000000, It took 5,921 secs
100000000, It took 0,031 secs

It's a proof of concept problem. I consult to a firm using Delphi with some pretty big DB's
DB access and data handling/processing are (almost) always the bottleneck.
Not the way data is handled internally by Lazarus/FPC.
« Last Edit: August 13, 2015, 01:55:04 pm by eny »
All posts based on: Win10 (Win64); Lazarus 2.0.10 'stable' (x64) unless specified otherwise...

dieselfan

  • New Member
  • *
  • Posts: 16
Re: IntToStr / StrToInt Perf issues VS Delphi?
« Reply #7 on: August 13, 2015, 02:50:16 pm »
More fruit: your three scenario's for 100.000.000:
100000000, It took 5,985 secs
100000000, It took 5,921 secs
100 000 000, It took 0,031 secs

It's a proof of concept problem. I consult to a firm using Delphi with some pretty big DB's
DB access and data handling/processing are (almost) always the bottleneck.
Not the way data is handled internally by Lazarus/FPC.
Can you run those on Delphi? What specs / versions you using for above results?

If #3 was that quick then your compiler is def doing a "lMax =" Vs actually running the loop. You could fool it with a "dosomething;"

Put it this way. I wrote a DB migration tool for them. Using IBPump it takes around 19 hours+. Using my code in Delphi it takes 17Mins. I make extensive use of conversions and loops. As it's for HiCare clients they can't afford to be without their DB for long. Obviously my code is more complex but the IO overhead is actually minscule compared. A large percentage is spent converting.
AMD 1800X
Manjaro KDE
Rarely Windows 10 Pro

dieselfan

  • New Member
  • *
  • Posts: 16
Re: IntToStr / StrToInt Perf issues VS Delphi?
« Reply #8 on: August 13, 2015, 02:59:06 pm »
More fruit: your three scenario's for 100.000.000:
100000000, It took 5,985 secs
100000000, It took 5,921 secs
100000000, It took 0,031 secs

It's a proof of concept problem. I consult to a firm using Delphi with some pretty big DB's
DB access and data handling/processing are (almost) always the bottleneck.
Not the way data is handled internally by Lazarus/FPC.
You can also see vs the original post
if you take 5.985, 5.921. You can reasonably expect D7 to be 5.3 and XE2 > around 2 seconds. Which irrespective of DB overhead etc is still 1/3. Can you confirm in any Delphi V?
AMD 1800X
Manjaro KDE
Rarely Windows 10 Pro

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11447
  • FPC developer.
Re: IntToStr / StrToInt Perf issues VS Delphi?
« Reply #9 on: August 13, 2015, 03:01:38 pm »
FWIW, I ran each at default ide settings

TNWM. (That's Not Worth Much)

dieselfan

  • New Member
  • *
  • Posts: 16
Re: IntToStr / StrToInt Perf issues VS Delphi?
« Reply #10 on: August 13, 2015, 03:11:23 pm »
Code...then for any delphi versions it's literally a copy and paste...and comment out the one uses clause for GetTickCount.
« Last Edit: August 13, 2015, 03:14:31 pm by dieselfan »
AMD 1800X
Manjaro KDE
Rarely Windows 10 Pro

eny

  • Hero Member
  • *****
  • Posts: 1634
Re: IntToStr / StrToInt Perf issues VS Delphi?
« Reply #11 on: August 13, 2015, 03:14:48 pm »
Can you run those on Delphi? What specs / versions you using for above results?
Sorry I don't have Delphi.
Quote
If #3 was that quick then your compiler is def doing a "lMax =" Vs actually running the loop. You could fool it with a "dosomething;"
The point is that these 'benchmarks' are not meaningful in any way.
If I were to 'dosomething' it becomes a different 'test'.
And no, the compiler did not skip the loop.

** edit **
See pic.
Of course no diff with previous results, except that I enabled the optimization flag in my previous tests.
Apparently these optimizations are enabled by default in the Delphi derivates.
Second pic is with optimization level O3.
« Last Edit: August 13, 2015, 03:23:54 pm by eny »
All posts based on: Win10 (Win64); Lazarus 2.0.10 'stable' (x64) unless specified otherwise...

rvk

  • Hero Member
  • *****
  • Posts: 6163
Re: IntToStr / StrToInt Perf issues VS Delphi?
« Reply #12 on: August 13, 2015, 03:59:12 pm »
Okay, I have a question.

When I trace in trunk into the IntToStr-function I end up in the int_str() of fpc\rtl\inc\generics.inc. It has this around the function.
Code: [Select]
{$ifndef FPC_SYSTEM_HAS_INT_STR_LONGINT}
procedure int_str(l:longint;out s:shortstring);
...
{$endif}
The function itself is in pure pascal and NOT assembler.

If I look in fpc\rtl\i386\i386.inc it HAS an assembler function for int_str(). Why is that one not used????
Code: [Select]
{$define FPC_SYSTEM_HAS_INT_STR_LONGWORD}
{$define FPC_SYSTEM_HAS_INT_STR_LONGINT}
...
procedure int_str(l:longword;out s:string);assembler;nostackframe;

When using this in your own code you can see by the grayed out portion the FPC_SYSTEM_HAS_INT_STR_LONGINT is not defined but the cpui386 IS defined. I don't think that's quite correct. Shouldn't the i386.inc be compiled on a Windows PC ???
Code: [Select]
  for x := 0 to lMax do begin
    {$ifdef FPC_SYSTEM_HAS_INT_STR_LONGINT}
    s := IntToStr(x);
    {$endif}
    {$ifdef cpui386}
    s := IntToStr(x);
    {$endif}
  end;

As it stands now the IntToStr() is pure pascal from the fpc\rtl\inc\generics.inc and can never reach the speed of pure assembler (like in Delphi).

B.T.W. This is also in Lazarus 1.4.2 FPC 2.6.4.

derek.john.evans

  • Guest
Re: IntToStr / StrToInt Perf issues VS Delphi?
« Reply #13 on: August 13, 2015, 04:09:48 pm »
I don't understand this bench marking topic.

Anyone that wants to convert 100,000,000 Integers to Strings or Strings to Integers would not be using StrToInt() and IntToStr().

And inside the context of database read/writes, that conversion would amount to a small fraction of the overall process.

ie: Where are these numbers coming from or going to?

IMO, the only way this topic makes sence is if you had a large dataset which you wanted to convert to a flat binary file or memory for faster lookups.

And even then, the conversion would only be a small part of the process.

rvk

  • Hero Member
  • *****
  • Posts: 6163
Re: IntToStr / StrToInt Perf issues VS Delphi?
« Reply #14 on: August 13, 2015, 04:15:11 pm »
IMO, the only way this topic makes sence is if you had a large dataset which you wanted to convert to a flat binary file or memory for faster lookups.

And even then, the conversion would only be a small part of the process.
Okay... let's go with a conversion-scenario. You would be correct, it's only a small part... But either way... If Lazarus/FPC is not using the assembler function for int_str (in i386.inc) while it is in code, it's a major design-flow in FPC itself. So that would need to be fixed, regardless. And this test-case just brings it to the surface.


Mmm, forcing the assembler (with recompile of FPC) still gives me 38 seconds for (2).
« Last Edit: August 13, 2015, 04:21:41 pm by rvk »

 

TinyPortal © 2005-2018