fpc lines of code lazarus / 62-General ---------------------------------------------------------------------- airpas · 2015-03-04 22:11 the openhub.net said that fpc source has 300k lines of code , is that true? https://www.openhub.net/p/freepascal btw , i did't expect that gcc has 14.5 million lines of code , that's incredibly giant http://www.phoronix.com/scan.php?page=news_item&px=MTg3OTQ ---------------------------------------------------------------------- Nitorami · 2015-03-04 22:29 I don't know, but I still prefer pascal over C even if it lacks 14.2 million lines of code ---------------------------------------------------------------------- Laksen · 2015-03-04 22:44 The total count of lines in the FPC codebase is about 3 million. But that includes a lot of runtime, packages, headers, testsuites, etc.. It's a silly thing to compare Edit: I messed up my line counter, but I still only count about 3 million lines in total in whatever version of GCC I have locally. ---------------------------------------------------------------------- Leledumbo · 2015-03-05 06:57 Why don't you do it yourself? Just need wc -l + a bit bash scripting for loop over the files, perhaps bc for summing up. Note that the Makefiles are generated from Makefile.fpc but both are still counted. ---------------------------------------------------------------------- hinst · 2015-03-05 11:04 This picture illustrates that GCC has no more than 5 500 000 lines of code https://vmakarov.fedorapeople.org/spec/comparison.html But perhaps the standard library is not included? For FreePascal 3 CLOC code line counter program shows me 2 153 983 lines of code (with standard library); In fpc/compiler subdirectory: 284 873 lines of code PS: less is more if you know what I mean ---------------------------------------------------------------------- Nitorami · 2015-03-05 19:28 I reckon the number of bugs is also proportional to the number of code lines... ---------------------------------------------------------------------- airpas · 2015-03-05 20:49 thats true , but it also indicate that a lot of improvement has been added . the mandelbrot example built with gcc 4.9 without optimization -O0 is faster than fpc with -O4 switch ! ---------------------------------------------------------------------- Nitorami · 2015-03-06 20:29 For the massive floating point calculations in the mandelbrot, the benefit of optimisations is small in the first place. But with FPUTYPE SSE2 and a few other mods I can reduce the execution time from 2200ms to 1600ms on my machine (FPC 2.6.4) 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. ---------------------------------------------------------------------- engkin · 2015-03-06 21:47 Quote from: airpas on March 05, 2015, 09:49:55 pmthats true , but it also indicate that a lot of improvement has been added . the mandelbrot example built with gcc 4.9 without optimization -O0 is faster than fpc with -O4 switch ! @Airpas It would be nice if you share both Pascal, and C[++] code you used, and speed results. @Nitorami I did a few modifications. Would you mind trying this: Code: [Select]program project1; uses windows; {$FPUTYPE X87}//<---- 1 - using x87 { $FPUTYPE SSE2} 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;   real = double;//<----- 2 - using double instead of real 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;    dwcolor     : DWORD absolute color;//<---- 3 - never mind (not used)    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);    cx := cxmin - pixelwidth;//<---- 4 - to replace mutiplicaion in inner loop (see 5)    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;//<---- 5(a) - check next line          cx := cx + pixelwidth;//<---- 5(b) - Addition instead of mutiplication          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             //dwcolor := dwcolor and $FF000000;             color.red   := 0;             color.green := 0;             color.blue  := 0;//}          end          else          begin             //dwcolor := dwcolor or $00FFFFFF;             color.red   := 255;             color.green := 255;             color.blue  := 255;//}          end;          //write(outfile, chr(color.red), chr(color.green), chr(color.blue)); //<---- 6 - no strings       end;    end;    close(outfile);    writeln(GetTickCount() - tm,'ms');    readln; end. ---------------------------------------------------------------------- Cyrax · 2015-03-06 22:37 Just by curiosity, I did few runs at engkin's modified project. Quote157ms with {$FPUTYPE X87} 234ms with {$FPUTYPE SSE2} Mind you, test program was run under virtualized environment. FPC is trunk version (revision 30110) and was built with these options: QuoteOPT=-gw2 -godwarfsets -gl -O- -OoNO -Xs- -Si- -vb -XX -CX -dTEST_WIN32_SEH COMPILER_OPTIONS=-gw2 -godwarfsets -gl -O- -OoNO -Xs- -Si- -vb -XX -CX -dTEST_WIN32_SEH Project was built with these options:  Quote-MObjFPC -Scghi -gw2 -godwarfsets -gl -l -vewnhibq -Filib\i386-win32 -Fu. -FUlib\i386-win32 -FEbin\i386-win32-win32\ CPU :  QuoteAMD64 Family 16 Model 6 Stepping 2 AuthenticAMD ~2877 Mhz ---------------------------------------------------------------------- Cyrax · 2015-03-07 00:36 Code: [Select]program project1; {$mode objfpc}{$H+} {.$FPUTYPE X87} //<---- 1 - using x87 {$FPUTYPE SSE2} uses   Classes, SysUtils, StreamIO, 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;    real = double; 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;    AFileStream : TFileStream;    AMemoryStream : TMemoryStream;    APChar : PByte; begin    AFileStream := TFileStream.Create(filename, fmCreate);    AMemoryStream := TMemoryStream.Create;    AMemoryStream.Size := ixmax * iymax * 3;    AMemoryStream.Position := 0;    APChar := AMemoryStream.Memory; (*   {$I-}    assign(outfile, filename);    rewrite(outfile);    if ioresult <> 0 then    begin       writeln(stderr, 'unable to open output file: ', filename);       exit;    end;*)    AssignStream(outfile, AFileStream);    rewrite(outfile);    writeln(outfile, 'P6');    writeln(outfile, ' ', comment);    writeln(outfile, ' ', ixmax);    writeln(outfile, ' ', iymax);    writeln(outfile, ' ', maxcolorcomponentvalue);    tm := GetTickCount();    for iy := 1 to iymax do    begin       cy := cymin + (iy - 1)*pixelheight;       cx := cxmin - pixelwidth;       if abs(cy) < pixelheight / 2 then cy := 0.0;       for ix := 1 to ixmax do       begin          cx := cx + 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));        {  AMemoryStream.Write(color.red, SizeOf(color.red));          AMemoryStream.Write(color.green, SizeOf(color.green));          AMemoryStream.Write(color.blue, SizeOf(color.blue)); }          APChar^ := color.red;          Inc(APChar);          APChar^ := color.green;          Inc(APChar);          APChar^ := color.blue;          Inc(APChar);       end;    end;    writeln(GetTickCount() - tm,'ms');    close(outfile);    AFileStream.Seek(0, soEnd);    AFileStream.CopyFrom(AMemoryStream, 0);    FreeAndNil(AFileStream);    FreeAndNil(AMemoryStream);    readln; end. With this code and compiler option -O4, I can get between 998ms and 1029ms execution times in real hardware. EDIT : Same code with FPC 2.6.5 (fixes) with -O3 option, gives between 2511ms and 1592ms. ---------------------------------------------------------------------- Leledumbo · 2015-03-07 04:53 Quote from: Cyrax on March 07, 2015, 01:36:01 amWith this code and compiler option -O4, I can get between 998ms and 1029ms execution times in real hardware. EDIT : Same code with FPC 2.6.5 (fixes) with -O3 option, gives between 2511ms and 1592ms. x64 real hardware: - 2.6.4: -CX -XXs -O3 -OoREGVAR  -CpATHLON64 -CfSSE64 - 3.1.1: -CX -XXs -O4 -OoREGVAR  -CpCOREAVX2 -CfAVX2 Code: [Select]2.6.4 - 3.1.1 1530.000125058000000 ms - 576.9997369498014500 ms 1531.000295653940000 ms - 572.0001412555575400 ms 1526.000071316960000 ms - 575.0000244006514500 ms 1526.000071316960000 ms - 573.9998538047075300 ms 1524.999900721010000 ms - 575.0000244006514500 ms 1502.000377513470000 ms - 658.9998956769704800 ms 1414.000452496110000 ms - 587.9997275769710500 ms 1439.000316895540000 ms - 620.0001575052738200 ms 1526.000071316960000 ms - 671.0000569000840200 ms 1501.000206917520000 ms - 573.9998538047075300 ms ---------------------------------------------------------------------- airpas · 2015-03-07 06:36 nice results , well i retest on pentium-4  2.8mhz and now fpc 3.1.1 is faster than gcc . so as said befor its nearly impossible to get the fastest code over all CPU's in short it depend on lots of things . btw , the -Cfsse(x) is more effective now with fpc 3.1.1 , thats really promising , respect ---------------------------------------------------------------------- Nitorami · 2015-03-07 10:05 Wait a moment. Don't be carried away by the momentum. You should be suspicious when there is a factor 4 improvement. @Engkin: Your code runs in some 500ms here but it only generates a white picture, even when reinserting the write command. You should always check whether the code still generates the desired output. @Cyrax: What dou you mean by "real hardware" ? Execution time here is 3300ms with X87 and 1600 with SSE2. ---------------------------------------------------------------------- Cyrax · 2015-03-07 11:36 Quote from: Nitorami on March 07, 2015, 11:05:19 am... @Cyrax: What dou you mean by "real hardware" ? Execution time here is 3300ms with X87 and 1600 with SSE2. Not virtualized aka in the real thing. See attached image(s) for info what kind of CPU I'm on running. Did you try out my modified version of your program? ---------------------------------------------------------------------- Nitorami · 2015-03-07 11:49 Ah, alright. Now that's something I guess. Been stupid, associated "hardware" with some sort of FPGA or similar... The attached is the best I can achieve on my machine. Got another 150ms or so down by using fast buffered file write (using the oldstyle Turbopascal blockwrite routine) instead of writing three bytes at a time, which causes a lot of overhead. It is now 1280ms here with FPC 3.1.1. Code: [Select]{$mode objfpc} program mandelbrot; uses sysutils; {$FPUTYPE SSE3} const    ixmax = 2500;    iymax = 2000;    cxmin = -2.5;    cxmax =  1.5;    cymin = -2.0;    cymax =  2.0;    pixelwidth  = (cxmax - cxmin) / ixmax;    pixelheight = (cymax - cymin) / iymax;    maxcolorcomponentvalue = 255;    maxiteration = 200;    escaperadius = 2.0;    er2 = escaperadius * escaperadius;    ret = #13#10; type    colortype = object       red   : byte;       green : byte;       blue  : byte;       procedure SetColor (r,g,b: byte);    end;    procedure colortype.SetColor (r,g,b: byte);    begin      red := r; green := g; blue := b;    end; var    n, ix, iy   : dword;    cx, cy      : real;    filename    : string = 'new1.ppm';    outfile     : file;    color       : colortype;    tm          : TDateTime;    LineStr     : ansistring; function Iterate (const cx,cy,er2: real): dword; inline; var i: dword;     zx,zy,zx2,zy2: real; begin   i := 0; zx := 0; zy := 0; zx2 := 0; zy2 := 0;   while  (zx2 + zy2 < er2) and (i < maxiteration) do   begin      zy := cy + zx*zy*2;      zx := cx + zx2 - zy2;      zx2 := zx*zx;      zy2 := zy*zy;      inc (i);   end;   result := i; end; begin    tm := Now;    {$I-}    assign  (outfile, filename);    rewrite (outfile, 1);    if ioresult <> 0 then    begin       writeln(stderr, 'unable to open output file: ', filename);       exit;    end;    {$I+}    LineStr := 'P6'+ ret               +' # '+ret               +' '+IntToStr (ixmax)+ret               +' '+IntToStr (iymax)+ret               +' '+IntToStr (maxcolorcomponentvalue)+ret;    blockwrite (outfile,LineStr[1], length (LineStr));    SetLength (LineStr, sizeof (colortype) * ixmax);    for iy := 0 to iymax-1 do    begin       cy := cymin + iy*pixelheight;       if abs(cy) < pixelheight / 2 then cy := 0.0;       for ix := 0 to ixmax-1 do       begin          cx := cxmin + ix*pixelwidth;          if iterate (cx,cy,er2) = maxiteration          then Color.SetColor (0,0,0)          else Color.SetColor (255,255,255);          n := ix*3;          LineStr[n+1] := chr (color.red);          LineStr[n+2] := chr (color.green);          LineStr[n+3] := chr (color.blue);       end;       blockwrite(outfile, LineStr[1], length (LineStr));    end;    close(outfile);    writeln((Now-tm)*3600000*24:0:0,'ms');    readln; end. ---------------------------------------------------------------------- Cyrax · 2015-03-07 12:43 Some suggestions for your new code: Change Code: [Select]SetLength (LineStr, sizeof (colortype) * ixmax); to  Code: [Select]SetLength (LineStr, sizeof (colortype) * ixmax * iymax); Move Code: [Select]blockwrite(outfile, LineStr[1], length (LineStr)); out of for loop and to before Code: [Select]close(outfile); ---------------------------------------------------------------------- Cyrax · 2015-03-07 15:07 Code: [Select]project1.lpr:92                   LineStr[n+1] := chr (color.red); 00401953 b8c0c24100               mov    $0x41c2c0,%eax 00401958 e8a3100000               call   0x402a00 0040195D 8b1500c04100             mov    0x41c000,%edx 00401963 8d5201                   lea    0x1(%edx),%edx 00401966 8a0da0c24100             mov    0x41c2a0,%cl 0040196C 884c10ff                 mov    %cl,-0x1(%eax,%edx,1) project1.lpr:93                   LineStr[n+2] := chr (color.green); 00401970 b8c0c24100               mov    $0x41c2c0,%eax 00401975 e886100000               call   0x402a00 0040197A 8b1500c04100             mov    0x41c000,%edx 00401980 8d5202                   lea    0x2(%edx),%edx 00401983 8a0da1c24100             mov    0x41c2a1,%cl 00401989 884c10ff                 mov    %cl,-0x1(%eax,%edx,1) project1.lpr:94                   LineStr[n+3] := chr (color.blue); 0040198D b8c0c24100               mov    $0x41c2c0,%eax 00401992 e869100000               call   0x402a00 00401997 8b1500c04100             mov    0x41c000,%edx 0040199D 8d5203                   lea    0x3(%edx),%edx 004019A0 8a0da2c24100             mov    0x41c2a2,%cl 004019A6 884c10ff                 mov    %cl,-0x1(%eax,%edx,1) It seems to wise to drop using string variable as place to save results. ---------------------------------------------------------------------- airpas · 2015-03-07 15:49 visual test , based on Nitorami optimization , i got 577ms , with -O4 -XX -WG -XS -Cfsse2 Code: [Select]program mandelbrot; {$ifdef FPC}{$mode objfpc}{$h+}{$endif} uses windows; const    w = 800;    h = 600;    ixmax = 2000;    iymax = 2000;    cxmin = -2.5;    cxmax =  1.5;    cymin = -2.0;    cymax =  2.0;    pixelwidth  = (cxmax - cxmin) / ixmax;    pixelheight = (cymax - cymin) / iymax;    maxcolorcomponentvalue = 255;    maxiteration = 200;    escaperadius = 2.0;    er2 = escaperadius * escaperadius; var   wc : twndclassex;     wnd: hwnd;     msg: tmsg;     bmp: HBITMAP;     fnt : HFONT;     dc,back_dc : longword;     data : plongword;     ix, iy   : longword;     cx, cy      : real;     tm          : longword; function inttostr(i : integer):ansistring; begin   str(i,inttostr); end; procedure setup(win : longword); var   binfo : BITMAPINFO; begin   dc := GetDC(win);   back_dc := CreateCompatibleDC(dc);   fillchar(binfo,sizeof(BITMAPINFO),0);   binfo.bmiHeader.biSize   := sizeof(BITMAPINFOHEADER);   binfo.bmiHeader.biWidth  := ixmax;   binfo.bmiHeader.biHeight := -iymax;   binfo.bmiHeader.biPlanes      :=1;   binfo.bmiHeader.biBitCount    :=32;   binfo.bmiHeader.biCompression :=BI_RGB;   binfo.bmiHeader.biSizeImage   :=0;   binfo.bmiHeader.biClrUsed     :=256;   binfo.bmiHeader.biClrImportant:=256;   bmp := CreateDIBSection(back_dc,binfo,DIB_RGB_COLORS,data,0,0);   selectObject(back_dc,bmp);   fnt := CreateFont(14, 0, 0, 0, FW_LIGHT, 0, 0, 0,                     ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, 0,     FF_DONTCARE or DEFAULT_PITCH, 'tahoma');   SelectObject(dc,fnt);   end; procedure clean(); begin   deleteDC(back_dc);   deleteDC(dc);   deleteObject(bmp);   deleteObject(fnt); end; function Iterate (const cx,cy,er2: real): dword; inline; var i: dword;     zx,zy,zx2,zy2: real; begin   i := 0; zx := 0; zy := 0; zx2 := 0; zy2 := 0;   while  (zx2 + zy2 < er2) and (i < maxiteration) do   begin      zy := cy + zx*zy*2;      zx := cx + zx2 - zy2;      zx2 := zx*zx;      zy2 := zy*zy;      inc (i);   end;   result := i; end; procedure draw(); var s : ansistring; c : longword; begin    tm := GetTickCount;    for iy := 0 to iymax-1 do    begin       cy := cymin + iy*pixelheight;       if abs(cy) < pixelheight / 2 then cy := 0.0;       for ix := 0 to ixmax-1 do       begin          cx := cxmin + ix*pixelwidth;          if iterate (cx,cy,er2) = maxiteration          then c := 0          else c := $ffffff;          data[ (iymax * iy ) +  ix]  := c;       end;        end;    SetStretchBltMode(dc,HALFTONE);    StretchBlt(dc,0,0,w,h,back_dc,0,0,ixmax,iymax,SRCCOPY);      s := inttostr(GetTickCount()-tm) + 'ms';    SetBKMode(dc,TRANSPARENT);    TextoutA(dc,0,0,pchar(s),length(s));   end; function wndproc(wnd, message:longword;wParam,lParam: longint):longint; stdcall; begin     case (message) of      WM_CLOSE:            ExitProcess(0);     end;          wndproc := DefWindowProc (wnd, message, wParam, lParam); end; begin     FillChar(wc,sizeof(wc),0); wc.cbSize        := sizeof(twndclassex);     wc.style         := CS_HREDRAW or CS_VREDRAW;     wc.lpfnWndProc   := @wndproc;     wc.hbrBackground := 1;     wc.lpszClassName := 'wclass';     registerclassex (@wc); wnd := CreateWindowEx(WS_EX_TOOLWINDOW or WS_EX_APPWINDOW ,                   'wclass',                   'mandelbrot',                    WS_OVERLAPPEDWINDOW or WS_VISIBLE,                    GetSystemMetrics( SM_CXSCREEN ) div 2 -  w  div 2,                    GetSystemMetrics( SM_CYSCREEN ) div 2 -  h  div 2,                    w,                    h,                    0,                    0,                    0,                    nil);   setup(wnd);   draw(); while ( msg.message <> WM_QUIT ) do begin if( PeekMessage( @msg, 0, 0, 0, PM_REMOVE ) ) then begin TranslateMessage( @msg ); DispatchMessage( @msg ); end else begin                   end; end; clean();     unregisterclass(@wc,hinstance);     ExitProcess(wnd); end. ---------------------------------------------------------------------- Nitorami · 2015-03-07 16:37 @Cyrax: You mean buffer the whole image in memory instead of a scanline only. The drawback is, that the image has a size of 15MB, and the compiler needs to allocate memory and clear it by SetLength (). That adds so much overhead that in the end the overall execution time gets higher. As to the string variable, I only used it because we need to write the file header first ("P6" etc), and it was convenient to use a string to spare the hassle with type conversion. Otherwise, I would have used a dynamic array. The trick is that the access to string or array is fast, while a call to writeln () takes a while. Therefore better buffer a decent amount of bytes (more than a few kB is normally not necessary and has not further benefit), then call writeln and flush the whole string or array in one go. @airpas: Hey, you are cheating  Your original code had ixmax=2500, now it is 2000... ---------------------------------------------------------------------- Cyrax · 2015-03-07 17:52 You only need to allocate needed memory once during execution of the program and in this situation memory requirement wont change, either. So there is no overhead at all. Also you don't need time memory allocation or other unneeded things, only what matters is  performance of the algorithm. ---------------------------------------------------------------------- Nitorami · 2015-03-07 18:34 Hm, I understand that SetLength (AnsiString) does allocate memory, although this is different from a dynamic array, where SetLength allocates memory and clears it, which does take time (although not a lot for 15MB). Still, the whole takes distinctly longer when using a whole image buffer, maybe due to cache issues again (not sure whether the cache is used at all in such cases, but 15MB is a lot larger than my 2nd level cache on my CPU). The reason for using SetLength is that when adding characters to an Ansistring (or dynamic array) one by one e.g. by LineStr := LineStr + 'P', this may be getting really slow because new memory needs to be allocated on every call. When setting the required length at the start, this is not necessary. ---------------------------------------------------------------------- lagprogramming · 2015-03-07 19:35 Out of curiosity. Within "procedure draw();" Remove variable "c : longword;" and remove a branch by changing Code: [Select]      for ix := 0 to ixmax-1 do       begin          cx := cxmin + ix*pixelwidth;          if iterate (cx,cy,er2) = maxiteration          then c := 0          else c := $ffffff;          data[ (iymax * iy ) +  ix]  := c;       end; with Code: [Select]      for ix := 0 to ixmax-1 do       begin          cx := cxmin + ix*pixelwidth;          data[ (iymax * iy ) +  ix]  := longword(longbool(iterate (cx,cy,er2) <> maxiteration));       end;    How will it change the code execution speed on your CPU? ---------------------------------------------------------------------- BeniBela · 2015-03-07 22:25 Quote from: Nitorami on March 07, 2015, 05:37:38 pm   The trick is that the access to string or array is fast, while a call to writeln () takes a while. Therefore better buffer a decent amount of bytes (more than a few kB is normally not necessary and has not further benefit), then call writeln and flush the whole string or array in one go. Isn't there a write buffer whose size you can increase to make it fast? ---------------------------------------------------------------------- Nitorami · 2015-03-08 00:36 @lagprogramming: On my machine not at all. This is as expected, because the time is spent in interate which does a lot of floating point operations, and the time for the  branching does not matter at all in comparison. This is different than for tiny loops such as the example in your bug report (for which I can confirm the same behaviour on my machine) @BeniBela: write () has certainly its own buffer and it may be possible to change its size, but the issue is that to call write () character by character does entail some overhead, regardless of buffer size. Nowadays most would use memory/filestreams for that anyway, but I have no experience how they work. ---------------------------------------------------------------------- lagprogramming · 2015-03-08 11:30 I might be wrong here but changing Code: [Select]function Iterate (const cx,cy,er2: real): dword; inline; var i: dword;     zx,zy,zx2,zy2: real; begin   i := 0; zx := 0; zy := 0; zx2 := 0; zy2 := 0;   while  (zx2 + zy2 < er2) and (i < maxiteration) do   begin      zy := cy + zx*zy*2;      zx := cx + zx2 - zy2;      zx2 := zx*zx;      zy2 := zy*zy;      inc (i);   end;   result := i; end; with Code: [Select]function Iterate (const cx,cy,er2: real): dword; inline; var zx,zy,zx2,zy2: real; begin   Result := maxiteration; zy := 0; zx2 := 0; zy2 := 0;   while  (zx2 + zy2 < er2) and (Result <> 0) do   begin      zx := cx + zx2 - zy2;      zy := cy + zx*zy*2;      zx2 := zx*zx;      zy2 := zy*zy;      dec(Result);   end; end; and further modify Code: [Select]      for ix := 0 to ixmax-1 do       begin          cx := cxmin + ix*pixelwidth;          data[ (iymax * iy ) +  ix]  := longword(longbool(iterate (cx,cy,er2) <> maxiteration));       end; with Code: [Select]      for ix := 0 to ixmax-1 do       begin          cx := cxmin + ix*pixelwidth;          data[ (iymax * iy ) +  ix]  := longword(longbool(iterate (cx,cy,er2) <> 0));       end; might increase a bit the speed. I've removed local variable "i: dword;" by replacing it with function's result and replaced "maxiteration" comparisons with zero comparisons. The idea was that if a value that lies in CPU register has to be compared with zero, then instead of "cmp" the compiler generates a "test" instruction in the generated assembler code, which on many CPUs improves the speed a bit. I've also switched the order of zx,zy,zx2,zy2 computation because some CPUs might stall a little bit with the original code order. I've also removed "zx := 0;" because it seemed useless to me. I don't know what's the effect of the changes, there might not be a single one . ---------------------------------------------------------------------- airpas · 2015-03-08 11:56 your modification slow down the rendering x2 , and gave wrong shape . i think the code as is , is optimized anyways , in my machine gives me 577ms , rebuild it with gcc 4.9.2 with a lots of speed switches + see2 gives 490ms  , so fpc already done a great job ---------------------------------------------------------------------- Nitorami · 2015-03-08 17:28 If you want REAL speed for fractals, you should use the GPU, it is incredibly powerful. I learned this when playing with the free winamp media player which comes with a visualisation plugin called "milkdrop2". Milkdrop allows simple and wysiwig access to the GPU shaders via HLSL (high level shader language, sort of C-like but optimised for speed and massive parallel processing.) I was fascinated what can be done with shaders. See this link to a movie of a code I made, it is a mandelbox rendering in realtime (the Mandelbox is a 3D version of the Mandelbrot, and the code allows you to fly through the structure at fullscreen resolution and in realtime. This is not pre-rendered or something) https://www.youtube.com/watch?feature=player_embedded&v=HhPuI4QHR4s