FPC 3.1.1. vs 2.6.4 lazarus / 62-General ---------------------------------------------------------------------- Nitorami · 2015-03-04 20:52 Excuse me if this is a naive question - clueless as I am, I should possibly not try to build a compiler from the source, but, I was curious, and downloaded the fpc 3.1.1 source trunk a while ago (29.1.), after having read about new features and optimisations. I not familiar with makefiles etc. and consequently it took me a while to sucessfully build fpc including the IDE (for win32). But, I got it working after all. However I found that the code generated by 3.1.1 appears to be 10%...20% slower than that generated by 2.6.4. , and this is more or less independant of the programs tried, except for massive floating point operations where the performance appears to be just the same. I tried all combinations of optimisation switches including the new ones but it just does not matter - the code is slower altogether, and none of the new optimisations makes a noticeable difference.  Are there specific switches for the build process I should have activated ? ---------------------------------------------------------------------- airpas · 2015-03-04 21:01 did you try -O4 switch ? ---------------------------------------------------------------------- Nitorami · 2015-03-04 21:07 Not for building the compiler, anyway. For compiling my programs neither because I would have expected the code runs at the same speed when specifying the same "2.6.4" switches. But it does not... ---------------------------------------------------------------------- airpas · 2015-03-04 21:19 you can always pass -al to the compiler for generating assembler , so you can see what's going on . ---------------------------------------------------------------------- Nitorami · 2015-03-04 21:30 Yes, maybe, if you can read assembler - I don't. But that slightly misses the point - I am not talking about specific code - my impression is that 3.1.1 produces slower code regardless of the program I compile, and my suspicion is just that I should have built the compiler differently. ---------------------------------------------------------------------- airpas · 2015-03-04 21:50 there is no guarantee that every new release of the compiler will generate faster code in 100% of cases i did some benchmarks , as result  60% of cases fpc 3.1.1 is ~20% faster than 2.6  , where 40% is equal or less . this is normal , even with c++ , i tryed with gcc 4.7 and 4.9 and the results was varient . ---------------------------------------------------------------------- zamtmn · 2015-03-04 21:53 I also noticed the older versions generate faster code. For example in my case fpc-2.7.1-20130828 faster that trunk version ~15% ---------------------------------------------------------------------- Jonas Maebe · 2015-03-04 22:03 Quote from: Nitorami on March 04, 2015, 10:30:42 pmBut that slightly misses the point - I am not talking about specific code - my impression is that 3.1.1 produces slower code regardless of the program I compile, and my suspicion is just that I should have built the compiler differently. There is no way to build the compiler itself so that it generates either faster or slower code. ---------------------------------------------------------------------- Nitorami · 2015-03-04 22:09 @airpas: Alright, I can accept that. I have learned (from Jonas) that the speed of of superscalar CPU architectures is not predictable anyway. The times are gone when you could simply add up clock cycles to determine execution speed. The numerious attempts to optimise the code by the CPU itself - cache lookahead, uop cache, branch prediction, instruction fetch, retirement, memory cache, memory prefetch - whatever - make it virtually impossible to generate optimal code other than by trial and error, and then it will be CPU specific. This can be quite irritating, I remember a small mandelbrot benchmark program which I tried to optimise over and over and just hit a brick wall - then accidentally I declared an unused shortstring in the program body and the speed went up factor 2. Anyway, the results on a specific CPU probably don't say a lot about the performance of the compiler, but I'll try to install 3.1.1. to a different machine to see whether it makes a difference. I agree that the speed of the generated code may vary with compiler versions on a specific machine, but this should equal out over different CPUs. If a compiler version produces slower code on several CPUs or platform, I would think it has a bug. @Jonas - thanks. Thought I had missed something. ---------------------------------------------------------------------- trayres · 2015-03-05 05:18 I believe there's talk of a LLVM backend for FPC - if this is true, we should be able to get the same performance/optimizations that are available to an industry standard C++ implementation. ---------------------------------------------------------------------- Leledumbo · 2015-03-05 07:14 From my own benchmark, 3.1.1 produces faster code in most cases. Well, logically, if there are more (generic) optimizations, how can it slow down existing code? Could you put some examples that's slower when compiled by 3.1.1? Quote from: trayres on March 05, 2015, 06:18:41 amI believe there's talk of a LLVM backend for FPC - if this is true, we should be able to get the same performance/optimizations that are available to an industry standard C++ implementation. The backend is far from complete or even usable to my knowledge. I believe we could get the same level of performance without it, we need their knowledgeable and skilled developers, not their code ---------------------------------------------------------------------- FPK · 2015-03-05 07:27 Quote from: Leledumbo on March 05, 2015, 08:14:04 amFrom my own benchmark, 3.1.1 produces faster code in most cases. Well, logically, if there are more (generic) optimizations, how can it slow down existing code? Could you put some examples that's slower when compiled by 3.1.1? Indeed, 3.x should generate better code than previous versions. But - 3.x has new features which might slow down programs: most notably the new string mechanisms and the windows exception handling or generating PIC by default - there might be indeed bugs which slow down certain example So please submit examples which clearly show what kind of code is slower (and on which platform). ---------------------------------------------------------------------- airpas · 2015-03-05 10:45 in this example fpc 2.6.4 is faster than 3.1.1 (fpc 2.6.4 show 1482ms , fpc 3.1.1 show 1684ms) both example compiled with -O3 , in win7 32bits. Code: [Select]program mandelbrot;  uses windows; const    ixmax = 2500;    iymax = 2000;    cxmin = -2.5;    cxmax =  1.5;    cymin = -2.0;    cymax =  2.0;    maxcolorcomponentvalue = 255;    maxiteration = 200;    escaperadius = 2; type    colortype = record       red   : byte;       green : byte;       blue  : byte;    end; var    ix, iy      : integer;    cx, cy      : real;    pixelwidth  : real = (cxmax - cxmin) / ixmax;    pixelheight : real = (cymax - cymin) / iymax;    filename    : string = 'new1.ppm';    comment     : string = '# ';    outfile     : textfile;    color       : colortype;    zx, zy      : real;    zx2, zy2    : real;    iteration   : integer;    er2         : real = (escaperadius * escaperadius);    tm : longword; begin    tm := GetTickCount();    {$I-}    assign(outfile, filename);    rewrite(outfile);    if ioresult <> 0 then    begin       writeln(stderr, 'unable to open output file: ', filename);       exit;    end;    writeln(outfile, 'P6');    writeln(outfile, ' ', comment);    writeln(outfile, ' ', ixmax);    writeln(outfile, ' ', iymax);    writeln(outfile, ' ', maxcolorcomponentvalue);    for iy := 1 to iymax do    begin       cy := cymin + (iy - 1)*pixelheight;       if abs(cy) < pixelheight / 2 then cy := 0.0;       for ix := 1 to ixmax do       begin          cx := cxmin + (ix - 1)*pixelwidth;          zx := 0.0;          zy := 0.0;          zx2 := zx*zx;          zy2 := zy*zy;          iteration := 0;          while (iteration < maxiteration) and (zx2 + zy2 < er2) do          begin             zy := 2*zx*zy + cy;             zx := zx2 - zy2 + cx;             zx2 := zx*zx;             zy2 := zy*zy;             iteration := iteration + 1;          end;          if iteration = maxiteration then          begin             color.red   := 0;             color.green := 0;             color.blue  := 0;          end          else          begin             color.red   := 255;             color.green := 255;             color.blue  := 255;          end;          write(outfile, chr(color.red), chr(color.green), chr(color.blue));       end;    end;    close(outfile);    writeln(GetTickCount() - tm,'ms');    readln; end. ---------------------------------------------------------------------- Leledumbo · 2015-03-05 12:08 Quote from: airpas on March 05, 2015, 11:45:49 amin this example fpc 2.6.4 is faster than 3.1.1 (fpc 2.6.4 show 1482ms , fpc 3.1.1 show 1684ms) Unless you're running a single tasking OS, milliseconds differences or even several seconds are negligible in a multitasking environment. Below is the result from my machine, executed 10 times in a row using bash for loop: Code: [Select]2.6.4 - 3.1.1 1760.00038628 ms - 1493.99964139 ms 2843.00032072 ms - 2430.00027258 ms 2800.99944212 ms - 3722.00002894 ms 3038.00026886 ms - 2577.99974643 ms 2724.99967832 ms - 2460.99990327 ms 3045.00020575 ms - 2432.99952708 ms 2713.00014574 ms - 2427.00038943 ms 2739.99972269 ms - 2781.00043070 ms 2783.00014324 ms - 2688.00028134 ms 2759.99999139 ms - 2790.99962208 ms As you can see, even the execution time can differ up to 2+ seconds between the same binary. Between the different binary, it's similar. If you can show consistent (i.e. executed at least 10 times in a row) 5 seconds difference, that's what you can call as slower. ---------------------------------------------------------------------- airpas · 2015-03-05 12:38 in the example the difference is integer , how you get this in single? , you're in linux maybe i retest > 10 times , always 2.6.4 <= 1450ms  / 3.1.1 >= ~1600ms try to increase ixmax and iymax ---------------------------------------------------------------------- marcov · 2015-03-05 13:14 Do the same benchmark, but comment out the writeln. Maybe it is simply the unicode changes there that are different, not the generated code. ---------------------------------------------------------------------- Leledumbo · 2015-03-05 13:19 Quote from: airpas on March 05, 2015, 01:38:08 pmin the example the difference is integer , how you get this in single? , you're in linux maybe i retest > 10 times , always 2.6.4 <= 1450ms  / 3.1.1 >= ~1600ms try to increase ixmax and iymax Yes, I am. FPC has its own timing facility, why use windows one? Code: [Select]program mandelbrot;  uses SysUtils,DateUtils; const    ixmax = 2500;    iymax = 2000;    cxmin = -2.5;    cxmax =  1.5;    cymin = -2.0;    cymax =  2.0;    maxcolorcomponentvalue = 255;    maxiteration = 200;    escaperadius = 2; type    colortype = record       red   : byte;       green : byte;       blue  : byte;    end; var    ix, iy      : integer;    cx, cy      : real;    pixelwidth  : real = (cxmax - cxmin) / ixmax;    pixelheight : real = (cymax - cymin) / iymax;    filename    : string = 'new1.ppm';    comment     : string = '# ';    outfile     : textfile;    color       : colortype;    zx, zy      : real;    zx2, zy2    : real;    iteration   : integer;    er2         : real = (escaperadius * escaperadius);    tm : TDateTime; begin    tm := Now;    {$I-}    assign(outfile, filename);    rewrite(outfile);    if ioresult <> 0 then    begin       writeln(stderr, 'unable to open output file: ', filename);       exit;    end;    writeln(outfile, 'P6');    writeln(outfile, ' ', comment);    writeln(outfile, ' ', ixmax);    writeln(outfile, ' ', iymax);    writeln(outfile, ' ', maxcolorcomponentvalue);    for iy := 1 to iymax do    begin       cy := cymin + (iy - 1)*pixelheight;       if abs(cy) < pixelheight / 2 then cy := 0.0;       for ix := 1 to ixmax do       begin          cx := cxmin + (ix - 1)*pixelwidth;          zx := 0.0;          zy := 0.0;          zx2 := zx*zx;          zy2 := zy*zy;          iteration := 0;          while (iteration < maxiteration) and (zx2 + zy2 < er2) do          begin             zy := 2*zx*zy + cy;             zx := zx2 - zy2 + cx;             zx2 := zx*zx;             zy2 := zy*zy;             iteration := iteration + 1;          end;          if iteration = maxiteration then          begin             color.red   := 0;             color.green := 0;             color.blue  := 0;          end          else          begin             color.red   := 255;             color.green := 255;             color.blue  := 255;          end;          write(outfile, chr(color.red), chr(color.green), chr(color.blue));       end;    end;    close(outfile);    writeln(MilliSecondSpan(tm,Now):1:8,' ms'); end. ---------------------------------------------------------------------- Leledumbo · 2015-03-05 13:25 Quote from: marcov on March 05, 2015, 02:14:30 pmDo the same benchmark, but comment out the writeln. Maybe it is simply the unicode changes there that are different, not the generated code. Either I did it wrong or what, but without write[ln] the result now becomes: Code: [Select]2.6.4 - 3.1.1 1534.00017880 ms - 742.99976695 ms 1517.99996383 ms - 743.99993755 ms 1401.00012068 ms - 717.99990255 ms 1508.99968576 ms - 691.99986756 ms 1513.99991009 ms - 684.99993067 ms 1427.99969763 ms - 710.99996567 ms 1505.00026066 ms - 719.99961510 ms 1391.00030065 ms - 698.00026249 ms 1388.99995945 ms - 730.99960573 ms 1519.00013443 ms - 742.00022500 ms Now the difference is consistent EDIT: looks like I did some mistakes in the previous benchmark (with write[ln]). The correct result should be: Code: [Select]2.6.4 - 3.1.1 1874.00034629 ms - 1562.99946830 ms 1826.00033004 ms - 1597.00023942 ms 2867.00001452 ms - 2565.00004325 ms 1858.00013132 ms - 1613.99999633 ms 3324.99956712 ms - 3702.99993083 ms 1835.00060812 ms - 1531.00029565 ms 2891.99987892 ms - 2737.00046819 ms 1861.00001447 ms - 1552.99964827 ms 2882.00005889 ms - 2677.99983267 ms 1837.99986262 ms - 1587.99996134 ms The difference is also more consistent. ---------------------------------------------------------------------- FPK · 2015-03-05 18:37 Quote from: Leledumbo on March 05, 2015, 02:25:04 pmQuote from: marcov on March 05, 2015, 02:14:30 pmDo the same benchmark, but comment out the writeln. Maybe it is simply the unicode changes there that are different, not the generated code. Either I did it wrong or what, but without write[ln] the result now becomes: Code: [Select]2.6.4 - 3.1.1 1534.00017880 ms - 742.99976695 ms 1517.99996383 ms - 743.99993755 ms 1401.00012068 ms - 717.99990255 ms 1508.99968576 ms - 691.99986756 ms 1513.99991009 ms - 684.99993067 ms 1427.99969763 ms - 710.99996567 ms 1505.00026066 ms - 719.99961510 ms 1391.00030065 ms - 698.00026249 ms 1388.99995945 ms - 730.99960573 ms 1519.00013443 ms - 742.00022500 ms Now the difference is consistent EDIT: looks like I did some mistakes in the previous benchmark (with write[ln]). The correct result should be: Code: [Select]2.6.4 - 3.1.1 1874.00034629 ms - 1562.99946830 ms 1826.00033004 ms - 1597.00023942 ms 2867.00001452 ms - 2565.00004325 ms 1858.00013132 ms - 1613.99999633 ms 3324.99956712 ms - 3702.99993083 ms 1835.00060812 ms - 1531.00029565 ms 2891.99987892 ms - 2737.00046819 ms 1861.00001447 ms - 1552.99964827 ms 2882.00005889 ms - 2677.99983267 ms 1837.99986262 ms - 1587.99996134 ms The difference is also more consistent. This proves exactly the point: unicode in 3.x is an issue but we cannot do anything against this. On modern CPUs -Cfsse2, -Cfsse3 or -Cfavx help also a lot with 3.x. -Cfsse2 and -Cfsse3 work with 2.6.x too but are less effective. ---------------------------------------------------------------------- airpas · 2015-03-05 18:58 QuoteThis proves exactly the point: unicode in 3.x is an issue but we cannot do anything against this. On modern CPUs -Cfsse2, -Cfsse3 or -Cfavx help also a lot with 3.x. -Cfsse2 and -Cfsse3 work with 2.6.x too but are less effective. thanks for the info . i hope to see in the future a document about optimization strategies with free pascal , just like c++ does http://www.agner.org/optimize/ ---------------------------------------------------------------------- Nitorami · 2015-03-05 19:26 @airpas: I have read agner yesterday. I understand approximately 0.1% of it but it seems obvious that generating the fastest possible code is almost impossible. For instance unrolling a loop may be a benefit but if the code does not fit into the cache anymore, this will prove detrimental. The various CPU optimisations partly seem to battle each other and the fastest code can only be found by trial and error, and it will be CPU specific. I'd like to also contribute a few surprising benchmarks. I am NOT using UNICODE, and I do not use writeln other than on program termination to display the result. I am using the sysutils timer. The timings are on a simple mandelbrot program. I can't be bothered to exactly specify which settings I use for debug / normal mode, suffice to say that the usual checks Range, Stack, Overflow, are ON for debug mode and optimisations are OFF. In normal mode, it's the other way round, checks off, O1, O2, O3 ON. The values are the average of three runs each, unless they differed by more than the timer resolution - otherwise something is wrong and I'll fix it. "sqr" means we replace the Zi*Zi, Zr*Zi in the mandelbrot code by the sqr operator sqr (Zi), sqr (Zr). First round FPC 2.6.4: normal mode: 1.75 sec normal mode + {$FPUTYPE SSE2}: 1.25 sec -> BEST result normal mode + sqr: 1.73 sec normal mode + {$FPUTYPE SSE2} + sqr: 4.81 sec  -> WORST result by far. sqr seems to be a problem for SSE2. FPC 3.1.1 normal mode: 3.19 sec -> very bad and in fact slower than 2.6.4 in debug mode !!! But: debug mode: 1.82 sec -> still a bit slower than 2.6.4 but faster than normal mode ! normal mode + {$FPUTYPE SSE2}: 1.45 sec normal mode + sqr: 3.21 sec normal mode + {$FPUTYPE SSE2} + sqr: 1.45 sec  -> surprise, sqr is no problem for SSE2 in 3.1.1 Second round, having done something else, ran a few other programs and came back: FPC 2.6.4: normal mode: 1.59 sec normal mode + {$FPUTYPE SSE2}: 1.11 sec -> BEST result normal mode + sqr: 1.56 sec normal mode + {$FPUTYPE SSE2} + sqr: 4.38 sec  -> WORST result by far FPC 3.1.1 normal mode: 2.88 sec debug mode: 1.61 sec normal mode + {$FPUTYPE SSE2}: 1.25 sec normal mode + sqr: 2.88 sec normal mode + {$FPUTYPE SSE2} + sqr: 1.24 sec So the machine has become faster in the meantime. Well maybe the virus scanner did something I did not notice, but at least the change to the better is consistent. Now there are a few surprises such that SSE2 fares rather poorly with the sqr operator in 2.6.4, and 3.1.1 may generate faster code in debug mode than in normal mode... would anyone have expected that ? I should say I find microbenchmarks rather pointless. Measuring the speed of a whole application normally delivers more stable results (@FPK: I cannot submit my whole code of course). Microbenchmarks may yield wildly changing values, which is just not so much the case for a full application. But coming back to the thread's topis: Again, I find that 3.1.1 is a bit slower than 2.6.4. At least on this machine (AMD Athlon 3500+, single core, win32). ---------------------------------------------------------------------- FPK · 2015-03-05 20:03 I guess the differences on the Athlon are simply caused by alignment issues. Older CPUs were very sensitive to this. Quote from: Nitorami on March 05, 2015, 08:26:11 pmBut coming back to the thread's topis: Again, I find that 3.1.1 is a bit slower than 2.6.4. At least on this machine (AMD Athlon 3500+, single core, win32).  As said, this is not unlikely for certain applications. The stuff mentioned above like the unicode changes cause additional bloat and we can try to improve this only if users tell us exactly what the problem is. ---------------------------------------------------------------------- lagprogramming · 2015-03-06 13:20 @Nitorami    I think you should double check your preliminary conclusions by reading the bug(id 26089) at: http://bugs.freepascal.org/view.php?id=26089    Many code execution speed measurements are completely useless for the combination between FPC and your CPU series. The funny thing is you haven't noticed that regarding the very same function/procedure, if it's moved within the pascal code then it may run slower or faster. For example, you take a function and you nest it within a calling function. Even if you call the nested function only once(you have a loop inside the function), that function may run a lot slower(or faster) compared to when the function is not nested. In fact, you may have the surprise to see that the same program might run faster or slower when you restart the computer ). All of these happen with the same FPC version.    If you don't want to follow Florian's suggestion to restart that bug report, then you have the following choices:    - insert "nop"s within assembler code;    - carefully remove some CPU branches. Their simple existence might decrease speed, due to improper code alignment.    - use another compiler.    All the best! ---------------------------------------------------------------------- Leledumbo · 2015-03-06 17:51 Quote from: FPK on March 05, 2015, 07:37:04 pmThis proves exactly the point: unicode in 3.x is an issue but we cannot do anything against this. How far has unicode integrate into the language? I mean when we just plainly declare a variable of type String (with {$H+}), does it automatically map to unicodestring? What if one just wants to have plain ansistring or shortstring? Will it be faster? ---------------------------------------------------------------------- Jonas Maebe · 2015-03-06 18:24 Quote from: Leledumbo on March 06, 2015, 06:51:30 pmI mean when we just plainly declare a variable of type String (with {$H+}), does it automatically map to unicodestring? Only if {$modeswitch unicodestrings} is active, which by default is only the case in {$mode delphiunicode}. QuoteWhat if one just wants to have plain ansistring or shortstring? Will it be faster? I think the main slowdown comes from the fact that the RTL now is correctly aware of the fact that on Windows the ansi codepage (i.e., the codepage of default ansistrings and shortstrings, aka CP_ACP) is different from the console codepage (the code page that must be used by writeln, aka CP_OEM). As a result, on Windows every single write(ln) of any string is going to result in a code page conversion with new FPC versions, while with old FPC versions that was not the case (which probably also meant that some characters could be output wrongly). I don't think console I/O will be (noticeably) slower on non-Windows platforms going from 2.6.4 to 3.1.1, even with a widestring manager installed. ---------------------------------------------------------------------- FPK · 2015-03-06 18:26 Quote from: Leledumbo on March 06, 2015, 06:51:30 pmQuote from: FPK on March 05, 2015, 07:37:04 pmThis proves exactly the point: unicode in 3.x is an issue but we cannot do anything against this. How far has unicode integrate into the language? I mean when we just plainly declare a variable of type String (with {$H+}), does it automatically map to unicodestring? What if one just wants to have plain ansistring or shortstring? Will it be faster? No, not really. The helper routines contain checks for code pages, the text and file variables take now unicode chars etc. This makes a program simply slower. ---------------------------------------------------------------------- Leledumbo · 2015-03-07 04:32 Quote from: Jonas Maebe on March 06, 2015, 07:24:15 pmI don't think console I/O will be (noticeably) slower on non-Windows platforms going from 2.6.4 to 3.1.1, even with a widestring manager installed. The test above is on a Linux x64 machine. 3.1.1 is still faster than 2.6.4 even with I/O, but the gap is rather small. When no I/O is used, the gap is big. Quote from: FPK on March 06, 2015, 07:26:20 pmNo, not really. The helper routines contain checks for code pages, the text and file variables take now unicode chars etc. This makes a program simply slower. So there's nothing we can do about it for now? Since the bottleneck is string operations, will buffering the string and reducing I/O calls still help? ---------------------------------------------------------------------- FPK · 2015-03-07 09:20 Quote from: Leledumbo on March 07, 2015, 05:32:06 amQuote from: Jonas Maebe on March 06, 2015, 07:24:15 pmI don't think console I/O will be (noticeably) slower on non-Windows platforms going from 2.6.4 to 3.1.1, even with a widestring manager installed. The test above is on a Linux x64 machine. 3.1.1 is still faster than 2.6.4 even with I/O, but the gap is rather small. When no I/O is used, the gap is big. Quote from: FPK on March 06, 2015, 07:26:20 pmNo, not really. The helper routines contain checks for code pages, the text and file variables take now unicode chars etc. This makes a program simply slower. So there's nothing we can do about it for now? Since the bottleneck is string operations, will buffering the string and reducing I/O calls still help? Buffering requires also string operations. If you want to get the topic forward, use kcachegrind and investigate where the time goes. Maybe there is a real bottleneck. ---------------------------------------------------------------------- Jonas Maebe · 2015-03-07 17:26 I think it has nothing to do at all with the speed of writeln, and it's again a case of micro benchmarking gone awry. Here were my initial results with ppc386 on OS X with plain -O2 (with the "time" command, so background activity is eliminated): Code: [Select]2.6.4, with writeln   user 0m5.572s   sys  0m0.293s 2.6.4, no writeln   user 0m4.648s   sys  0m0.005s 3.1.1, with writeln   user 0m2.243s   sys  0m0.266s 3.1.1, no writeln   user 0m2.038s   sys  0m0.004s So for me, writeln actually seems to have less overhead in 2.6.4 than on 3.1.1. Then I figured to test the overhead with cwstring included, and it seemed to get really weird: Code: [Select]2.6.4, with writeln, with cwstring   user 0m4.216s   sys  0m0.269s 2.6.4, no writeln, with cwstring   user 0m4.020s   sys  0m0.006s 3.1.1, with writeln, with cwstring   user 0m1.427s   sys  0m0.254s 3.1.1, no writeln, with cwstring   user 0m1.275s   sys  0m0.004s Look at that: including cwstring makes the program a lot faster both on 2.6.4 and 3.1.1, even when there's no input/output at all! If you see something like that, you can be virtually certain it's a case of memory alignment. And indeed: if I move all of the code of the program into a subroutine (so all variables become local variables) and then play with the maximum alignment for local variables (all cases without writeln, with/without cwstring stays the same): Code: [Select]3.1.1, -Oalocalmax=4   user 0m1.233s   sys  0m0.004s 3.1.1, -Oalocalmax=8 (and anything else > 4, doesn't change generated code compared to 8)   user 0m3.843s   sys  0m0.014s So as soon as the maximum alignment for locals is increased above 8, you get a huge increase in run time here. So it's clear that there's a cache effect playing somewhere, because forcing the alignment to 4 bytes means that several doubles are now only aligned at 4 bytes (which in theory should reduce performance). In the original code, all variables were global variables and hence including another unit will affect their alignment/placement too. Now, all of the above is without -Cfsse2. If I add -Cfsse2, then the speed is the same with 4 and 8 byte alignment. Reason: all values are kept in SSE2 registers, so the stack alignment is irrelevant. Now, if you add writeln, then the impact will again become potentially bigger because then the sse values will have to be spilled to the stack and hence cache effects come back into play. Another thing that may be relevant is that if FPC is able to better optimise the register-based code in 3.1.1 than in 2.6.4 (or is better able to put global variables into registers), then logically if values need to be spilled the performance degredation will be relatively larger in 3.1.1 than in 2.6.4, but that could just be because 2.6.4 generated worse code to start with. And now I've spent way more time on this already than I ever planned to. ---------------------------------------------------------------------- BeniBela · 2015-03-07 22:30 Quote from: Jonas Maebe on March 06, 2015, 07:24:15 pm I think the main slowdown comes from the fact that the RTL now is correctly aware of the fact that on Windows the ansi codepage (i.e., the codepage of default ansistrings and shortstrings, aka CP_ACP) is different from the console codepage (the code page that must be used by writeln, aka CP_OEM). As a result, on Windows every single write(ln) of any string is going to result in a code page conversion with new FPC versions, while with old FPC versions that was not the case (which probably also meant that some characters could be output wrongly). Is there an option to change that? E.g. if you want to output UTF-8, if the output is redirected to a file ---------------------------------------------------------------------- Jonas Maebe · 2015-03-08 17:48 Quote from: BeniBela on March 07, 2015, 11:30:16 pmQuote from: Jonas Maebe on March 06, 2015, 07:24:15 pm I think the main slowdown comes from the fact that the RTL now is correctly aware of the fact that on Windows the ansi codepage (i.e., the codepage of default ansistrings and shortstrings, aka CP_ACP) is different from the console codepage (the code page that must be used by writeln, aka CP_OEM). As a result, on Windows every single write(ln) of any string is going to result in a code page conversion with new FPC versions, while with old FPC versions that was not the case (which probably also meant that some characters could be output wrongly). Note that when I wrote the above, I hadn't looked at the program's source code and thought it was writing to the console. Since it's writing to a file, the above is not applicable (by default, the output to the file will be in the ansi code page as well, so no code page conversions will occur). QuoteIs there an option to change that? E.g. if you want to output UTF-8, if the output is redirected to a file I don't think the RTL exports a routine to query whether or not the output is redirected. Getting/setting the encoding of any textfile (including input, output and stderr) can be done via system.GetTextCodePage(text):TSystemCodePage and system.SetTextCodePage(text,TSystemCodePage) though. ---------------------------------------------------------------------- zeljko · 2015-03-15 08:48 Last night I've installed trunk fpc + trunk lazarus via script from getlazarus.org and then build my erp application, and was pretty impressed release binary size is reduced cca 20% in compare to 2.6.4. Both are compiled with -Mdelphi -O2 and then stripped. Fedora 19 32bit. Nice ---------------------------------------------------------------------- airpas · 2015-03-15 11:40 also when you build lazarus with "optimized ide" profile  , this will reduce the exe size . on linux with optimized ide profile an empty window is only 1.8mb , with normal profile the size is ~4mb ---------------------------------------------------------------------- Leledumbo · 2015-03-15 12:56 Quote from: airpas on March 15, 2015, 12:40:25 pmon linux with optimized ide profile an empty window is only 1.8mb , with normal profile the size is ~4mb To be precise: i386-linux-qt = 1,617,100 bytes ~= 1,5 MBi386-linux-gtk2 = 1,886,124 bytes ~= 1,8 MBx86_64-linux-qt = 2,122,584 bytes ~= 2,0 MBx86_64-linux-gtk2 = 2,492,256 bytes ~= 2,4 MB ---------------------------------------------------------------------- BeniBela · 2016-06-04 13:17 Quote from: Jonas Maebe on March 08, 2015, 06:48:08 pmI don't think the RTL exports a routine to query whether or not the output is redirected. Getting/setting the encoding of any textfile (including input, output and stderr) can be done via system.GetTextCodePage(text):TSystemCodePage and system.SetTextCodePage(text,TSystemCodePage) though. That is quite an unreliable function Code: [Select] -----------Windows--|---Linux default---|--Linux cwstrings CP_ACP   |   ok     |        ok         |        ok          |          |                   | 1252     |   ok     |       FAILS       |        ok          |          |                   | CP_UTF16 |  FAILS   |       FAILS       |        ok          |          |                   | CP_UTF32 |  FAILS   |       FAILS       |        ok (12000) ---------------------------------------------------------------------- Jonas Maebe · 2016-06-04 13:25 The "Linux default" case is irrelevant: no codepage conversion can work with that, also with previous FPC versions. Please file bug reports for the failing Windows cases, along with an example that demonstrates the problem (for example, it is important to know whether you are testing this with writing to a text file, or to the console -- in the latter case, on Windows you probably also have to configure your cmd windows in a way that supports arbitrary unicode codepoints, because afaik by default it only supports the OEM codepage charset). ---------------------------------------------------------------------- Jonas Maebe · 2016-06-04 13:28 Additionally, do you mean that it works/doesn't work when you write UTF16/UTF32 strings to the text file, or that it works/doesn't work when you configure the text file itself for UTF16/UTF32? The latter is completely unsupported on any platform (if it works on Linux, that's purely coincidence). Unfortunately, the SetTextCodePage() function is modelled on Delphi's API and has no way to report errors to the caller (other than possibly triggering a run time error). ---------------------------------------------------------------------- BeniBela · 2016-06-04 14:21 Quote from: Jonas Maebe on June 04, 2016, 03:28:50 pmr that it works/doesn't work when you configure the text file itself for UTF16/UTF32? The latter is completely unsupported on any platform (if it works on Linux, that's purely coincidence). This It would make it much simpler to create a file in any encoding ---------------------------------------------------------------------- BeniBela · 2016-09-03 22:38 Quote from: Jonas Maebe on March 06, 2015, 07:24:15 pm I think the main slowdown comes from the fact that the RTL now is correctly aware of the fact that on Windows the ansi codepage (i.e., the codepage of default ansistrings and shortstrings, aka CP_ACP) is different from the console codepage (the code page that must be used by writeln, aka CP_OEM). As a result, on Windows every single write(ln) of any string is going to result in a code page conversion with new FPC versions, while with old FPC versions that was not the case (which probably also meant that some characters could be output wrongly). And readln, too! Another trap to consider. Call otherprogram | fpcprogram  and fpc assumes otherprogram outputs  the console codepage and wants to convert it. There rarely is a need to convert anything ---------------------------------------------------------------------- Thaddy · 2016-09-04 05:24 If you use shortstrings you'll get fast code. Has always been the case. Shortstrings have also been always limited compared to the later string types. In actual fact the current compiler generates much faster code then all the previous compilers. In effect, that makes the new features acceptible to me. As is the case with many languages and frameworks. Also note that code that does not rely on the advanced string manager is just as fast as ever. Moaning about the speed of new features is not warranted if you did not know you can revert back to the old behavior and in this case the new features aren't even enabled by default. You have to install a string manager.