FPC-Kompiler sehr schnell

Für sonstige Unterhaltungen, welche nicht direkt mit Lazarus zu tun haben
Horst_h
Beiträge: 72
Registriert: Mi 20. Mär 2013, 08:57

Re: FPC-Kompiler sehr schnell

Beitrag von Horst_h »

Hallo,

Ich habe mal versucht, x- Units in ein Programm einzubinden.
Beipielhaft mit l= 4.

Code: Alles auswählen

//Unit 1
unit p000001;
 
interface
  procedure go;
implementation
  procedure go();
  Begin
  writeln(1);
  writeln(2);
  writeln(3);
  writeln(4);
  End;
End.
// und das Programm:
program test;
 
uses
  p000001,
  p000002,
  p000003,
  p000004;
BEGIN
  p000001.go;
  p000002.go;
  p000003.go;
  p000004.go;
END.
 

Leider musste ich feststellen, dass Freepascal die Units nicht parallel compiliert.
Der große Vorteil ist der erheblich geringe Bedarf an Hauptspeicher während des kompilierens.

Code: Alles auswählen

{$MODE objFPC}
 
const
  l = 1000;
  StrLen = 7;
type
  tStr7 = string[StrLen]
  tNameLst = array[1..l] of tStr7; 
 
procedure StringInc(var s:tStr7);// Spielerei ;-)
var
  i : integer;
  ch : pChar;
Begin
  i := Length(s)-1;
  ch := @s[1];
  repeat
    ch[i] := chr(Ord(ch[i])+1);
    IF Ord(ch[i])<=Ord('9') then
      BREAK
    else
    Begin
      ch[i] := '0';
      dec(i);
      IF i < 1 then
        BREAK;
    end;
  until false;
end;
 
procedure BuildUnit(var name:tStr7;ofs,cnt:integer);
var
  f: Text;
Begin
  Assign(f, name+'.pas');
  Rewrite(f);
  WriteLn(f, 'unit '+name+';',#13#10);
  WriteLn(f, 'interface ',#13#10,'  procedure go;',#13#10,'implementation');
  WriteLn(f, '  procedure go();',#13#10,'  Begin');
  For cnt := cnt downto 1 do
  Begin
    writeln(f,'  writeln(',ofs,');');
    inc(ofs);
  end
  WriteLn(f, '  End;',#13#10,'End.');
  Close(f);
end;
 
procedure BuildProgram(NameLst:tNameLst);
var
  f: Text;
  i : integer;
begin
  Assign(f, 'pascaltest.pas');
  Rewrite(f);
  WriteLn(f, 'program test;' + #13#10);
  Writeln(f, 'uses');
  for i := 1 to l-1 do
    Writeln(f,'  ',NameLst[i],',');
  Writeln(f,'  ',NameLst[l],';');
  Writeln(f,'BEGIN');
  for i := 1 to l do
    Writeln(f,'  ',NameLst[i],'.go;');
  Writeln(f,'END.');   
  Close(f);
end;
 
procedure Button1Click;
var
  name : tStr7;
  NameLst : tNameLst;
  i, j: LongInt;
begin
  setlength(name,StrLen);
  fillchar(name[1],StrLen,'0');
  name[1] := 'p';
  j := 1;
  for i := 1 to l do
  Begin
    StringInc(name);
    writeln(Name);
    NameLst[i] := name;
    BuildUnit(name,j,l);
    inc(j,l);
  end
  BuildProgram(NameLst);
end;
 
procedure Button2Click;
var
  f: Text;
  i, j: integer;
begin
  Assign(f, 'ctest.c');
  Rewrite(f);
  WriteLn(f, '#include <stdio.h>   ');
  WriteLn(f, 'void Ausgabe(int i) {printf("%d\n", i);}',#13#10);
  for i := 1 to l do begin
    WriteLn(f, 'void p', i, '()');
    WriteLn(f, '{');
    for j := 1 to l do begin
      WriteLn(f, ' Ausgabe(', l * (i-1) + j, ');');
    end;
    WriteLn(f, '};' + #13#10);
  end;
 
  WriteLn(f, 'int main()');
  WriteLn(f, '{');
  for i := 1 to l do begin
    WriteLn(f, '  p', i, '();');
  end;
  WriteLn(f, '}');
 
  Close(f);
end;
 
Begin
  Button1Click;
//  Button2Click;
end.
 

Erstellt 1000 Units p00001 bis p001000. Das geht relativ fix:

Code: Alles auswählen

...
p000999
p001000
 
real   0m2.113s
user   0m0.160s
sys   0m0.300s

Das Kompilieren dauert aber länger, es wird auch nur eine Unit nach der anderen kompiliert.
l=707 dauerte zuvor 36.? jetzt 40.6 Sekunden .
Aber jetzt kann ich auch l=1000 auf Linux 32-Bit testen :!:

Code: Alles auswählen

...
Compiling p000999.pas
Compiling p001000.pas
Linking pascaltest
/usr/bin/ld: warning: link.res contains output sections; did you forget -T?
1011005 lines compiled, 94.10 sec
 
real   1m34.998s
user   1m30.347s
sys   0m3.053s

Aber nochmaliges kompilieren bei Änderung an einer Unit dauert nur 1,8 s, ohne Änderung 1,6 s.

Code: Alles auswählen

 time fpc pascaltest.pas
Free Pascal Compiler version 2.6.4 [2014/03/03] for i386
Copyright (c) 1993-2014 by Florian Klaempfl and others
Target OS: Linux for i386
Compiling pascaltest.pas
Compiling p001000.pas
Linking pascaltest
/usr/bin/ld: warning: link.res contains output sections; did you forget -T?
3013 lines compiled, 1.8 sec
 
real   0m1.757s
user   0m0.843s
sys   0m0.250s
 

Man bräuchte ein Hilfsprogramm, was alle genutzten units rausfischt und dann parallel compiliert und erst zum Schluss alles zusammenführt.
Lazarus kann das wohl,

Gruß Horst
EDIT: Beim Text umkopiren entstehen merkwürdige Sätze.
Mal 4096 Units mit 4096 Zeilen erzeugt.->Die ausführbare Datei hat 688.163,980 Byte und funktioniert sogar.xterm ist so schnell...

Code: Alles auswählen

Compiling p004095.pas
Compiling p004096.pas
Linking pascaltest
/usr/bin/ld: warning: link.res contains output sections; did you forget -T?
16822277 lines compiled, 3724.0 sec
 
real   62m4.489s
user   53m58.993s
sys   0m51.983s
 

Ich gehe davon aus das ein i7 bei single Thread nicht wirklich viel schneller ist als ein i3 -4330 mit 3,5 Ghz.
EIne ntfs Festplatte ist sicher nicht optimal, aber die Dateien sind ja zum Teil in dem 8 Gb Hauptspeicher als Cache zu finden.

Edit2:
Nochmaliges Kompilieren dauerte 4min 20 Sekunden, also praktisch nur das linken.
Der maximale Speicherbedarf war dann 2649 Mb.

Antworten