IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Free Pascal Discussion :

Optimisation, performance et poids d'un exécutable


Sujet :

Free Pascal

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 24
    Points : 13
    Points
    13
    Par défaut Optimisation, performance et poids d'un exécutable
    Bonjour à tous,

    Je reviens vers vous pour un souci "d'obésité compilatoire".
    En effet j'utilise plein de modules dans mon code, certains que j'utilise (en passant par uses), d'autres non, en fonction des programmes que je construis.
    Je me suis aperçu que, à l'inverse de ce que j'avais compris dans certains messages sur le forum, que le compilateur ne fait pas de base le ménage des modules non utilisés.

    Par exemple en laissant traîner quelques modules :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    (* Insertion des librairies MADLib Communes
    * -----------------------------------------
    *)
     
        MadLib_xml in CHEMIN_MADLIB + '/commun/madlib_xml.pas',
        MadLib_ini in CHEMIN_MADLIB + '/commun/madlib_ini.pas',
        MadLib_FileSystem in CHEMIN_MADLIB + '/commun/madlib_filesystem.pas',
        MadLib_CmdLine in CHEMIN_MADLIB + '/commun/madlib_cmdline.pas',
        MadLib_SystemEnvironment in CHEMIN_MADLIB + '/commun/madlib_systemenvironment.pas',
        MadLib_String in CHEMIN_MADLIB + '/commun/madlib_string.pas',
        MadLib_Numeric in CHEMIN_MADLIB + '/commun/madlib_numeric.pas',
        MadLib_Convert in CHEMIN_MADLIB + '/commun/madlib_convert.pas',
        MadLib_TinyLog in CHEMIN_MADLIB + '/commun/madlib_tinylog.pas',    
     
        (* MadLib_dhcpd in CHEMIN_MADLIB + '/linux/madlib_dhcpd.pas', *)
     
        (* En fonction de la plate-forme de compilation insertion des UNITES LIBRAIRIE MODULE spécifiques
        * -----------------------------------------
        *)
     
        {$IFDEF linux}
                    MadLib_dhcpd in CHEMIN_MADLIB + '/linux/madlib_dhcpd.pas',
                    MadLib_dnsmasq in CHEMIN_MADLIB + '/linux/madlib_dnsmasq.pas',
     
        {$ENDIF}
    l’exécutable fait : 1.2Mo

    En supprimant un module (XML) que je n'utilise pas dans mon code (c'est-à-dire pas de déclaration via USES), l’exécutable fait lui 800Ko.

    Bien sûr, me direz-vous, il faut enlever ce que l'on n'utilise pas, mais dans mon cas le fichier qui est utilisé est un "include" standardisé. Il n'est pas propre au programme compilé mais propre à un ensemble de sources qui utilisent les mêmes références.
    Il n'est donc pas possible de modifier ce fichier et il faut que je l'utilise puisque c'est le montage commun des modules d'un projet.

    Je me suis donc orienté vers l'optimisation avec FPC, dans le but de supprimer les modules qui ne sont pas "uses", car m'avait-on dit, que cela s'effectuait automatiquement. M'aurait-on menti ??

    Malheureusement, je ne pense pas avoir essayé les bons commutateurs, car l’exécutable fait toujours le même poids.

    Connaissez-vous donc les commutateurs qui indiquent à FPC de supprimer, par exemple, les unités non utilisées ?

    Merci d'avance de vos réponses.
    [MAD]

  2. #2
    Membre éclairé

    Homme Profil pro
    Rédacteur technique (retraité)
    Inscrit en
    Octobre 2009
    Messages
    168
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 81
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Rédacteur technique (retraité)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 168
    Points : 807
    Points
    807
    Par défaut
    Bonjour,

    Tu devrais trouver ton bonheur ici, dans le Free Pascal Programmer's Guide, Chapitre 11 Optimisations. Et peut-être plus particulièrement les sections 11.6 et 11.7 sur WPO.

    Joyeux Noël !

  3. #3
    Membre confirmé

    Homme Profil pro
    Autre
    Inscrit en
    Novembre 2015
    Messages
    145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Novembre 2015
    Messages : 145
    Points : 625
    Points
    625
    Par défaut
    De manière générale, les procédures/fonctions (donc tout le code) non utilisées dans un module ne sont en effet pas incluses si elles ne sont pas utilisées. Donc l'affirmation concernant l'optimisation à propos du code non utilisé est vraie.

    Mais un module peut -notamment- inclure des sections "Initialization" et/ou "Finalization". Ces sections peuvent contenir du code, utiliser des classes, d'autres modules, avoir des ressources, etc ...

    Dans ce cas l'optimisation n'a pas lieu concernant tout ce qui touche à ces sections (ainsi que tous les autres modules que ces sections pourraient utiliser). Si vous n'utilisez vraiment pas ces modules, j'ai bien peur que la seule solution soit alors de ne pas les déclarer dans vos clauses 'Uses'.


    Exemple avec un petit programme Free Pascal déclarant une unité non utilisée.


    Premier cas: unité non utilisée "standard"

    Unité principale:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    program project1;
     
    uses
      UnusedUnit;
     
    begin
      WriteLn('Hello World !');
    end.
    Unité non utilisée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    unit UnusedUnit;
     
    interface
     
    var
      MyUnusedVar: integer;
     
    procedure MyProc();
     
    implementation
     
    const
      MyString = '1234567890';
     
    procedure MyProc();
    begin
      MyUnusedVar := Length(MyString);
    end;
     
    end.
    Dans ce cas, le compilateur détecte bien que l'unité n'est pas utilisée et il n'inclut pas les éléments de cette unité:
    Hint: (11030) Start of reading config file C:\lazarus\fpc\3.0.4\bin\x86_64-win64\fpc.cfg
    Hint: (11031) End of reading config file C:\lazarus\fpc\3.0.4\bin\x86_64-win64\fpc.cfg
    Free Pascal Compiler version 3.0.4 [2017/12/03] for x86_64
    Copyright (c) 1993-2017 by Florian Klaempfl and others
    (1002) Target OS: Win64 for x64
    (3104) Compiling project1.lpr
    (3104) Compiling unusedunit.pas
    C:\.......\project1.lpr(4,3) Hint: (5023) Unit "UnusedUnit" not used in project1
    (9015) Linking project1.exe
    (1008) 30 lines compiled, 0.2 sec, 41504 bytes code, 1380 bytes data
    (1022) 3 hint(s) issued
    Notez bien le message du compilateur concernant la non utilisation de l'unité, et la taille du code et des données pour le programme.



    Second cas: unité non utilisée avec une clause "Initialization"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    unit UnusedUnit;
     
    interface
     
    var
      MyUnusedVar: integer;
     
    implementation
     
    const
      MyString = '1234567890';
     
    Initialization
      MyUnusedVar := Length(MyString);
     
    end.
    Le programme n'utilise pas plus l'unité concernée mais le compilateur inclut automatiquement tout ce qui est relatif à la clause 'Initialization" (qui est déclenchée automatiquement). C'est ce qu'indique la compilation:

    Hint: (11030) Start of reading config file C:\lazarus\fpc\3.0.4\bin\x86_64-win64\fpc.cfg
    Hint: (11031) End of reading config file C:\lazarus\fpc\3.0.4\bin\x86_64-win64\fpc.cfg
    Free Pascal Compiler version 3.0.4 [2017/12/03] for x86_64
    Copyright (c) 1993-2017 by Florian Klaempfl and others
    (1002) Target OS: Win64 for x64
    (3104) Compiling project1.lpr
    (3104) Compiling unusedunit.pas
    (9015) Linking project1.exe
    (1008) 26 lines compiled, 0.2 sec, 41536 bytes code, 1396 bytes data
    (1022) 2 hint(s) issued
    Plus de message du compilateur, et la taille du code et des données ont été augmentées.

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 24
    Points : 13
    Points
    13
    Par défaut
    Bonjour FChrisF,

    Je viens de tester l'exemple. Que l'on place de l'initialisation ou non dans l'unité, le poids fait toujours le même 176Ko.

    De mon côté je n'arrive pas à comprendre pourquoi il indique que le module n'est pas utilisé, mais qu'il recherche le fichier objet pour le lier par la suite.



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    [0.668] erelios.pas(230,22) Hint: Variable "MyAppInfo" of a managed type does not seem to be initialized
    [0.672] erelios.pas(127,12) Hint: Local type "MyType" is not used
    [0.672] MADLib-all.inc(36,2) Hint: Unit "MadLib_xml" not used in Erelios
    [0.672] MADLib-all.inc(38,2) Hint: Unit "MadLib_FileSystem" not used in Erelios
    [0.672] MADLib-all.inc(41,5) Hint: Unit "MadLib_String" not used in Erelios
    [0.672] MADLib-all.inc(42,5) Hint: Unit "MadLib_Numeric" not used in Erelios
    [0.672] MADLib-all.inc(43,2) Hint: Unit "MadLib_Convert" not used in Erelios
    [0.672] (ERELIOS)  Unloading resource unit FPINTRES (not needed)
    [0.672] Searching file erelios.o... found
    [0.672] Searching file /usr/lib/fpc/3.0.0/units/x86_64-linux/rtl/system.o... found
    [0.680] Searching file /usr/lib/fpc/3.0.0/units/x86_64-linux/rtl/objpas.o... found
    [0.680] Searching file ./MADLib/commun/madlib_xml.o... found
    [0.680] Searching file ./MADLib/commun/madlib_ini.o... found
    [0.680] Searching file ./MADLib/commun/madlib_filesystem.o... found
    [0.680] Searching file ./MADLib/commun/madlib_cmdline.o... found
    [0.680] Searching file ./MADLib/commun/madlib_systemenvironment.o... found
    [0.680] Searching file ./MADLib/commun/madlib_string.o... found
    [0.680] Searching file ./MADLib/commun/madlib_numeric.o... found
    [0.680] Searching file ./MADLib/commun/madlib_convert.o... found
    [0.680] Searching file ./MADLib/commun/madlib_tinylog.o... found
    [0.680] Searching file ./MADLib/linux/madlib_dhcpd.o... found
    [0.680] Searching file ./MADLib/linux/madlib_dnsmasq.o... found
    [0.680] Searching file /usr/lib/fpc/3.0.0/units/x86_64-linux/rtl/sysutils.o... found
    [0.684] Searching file /usr/lib/fpc/3.0.0/units/x86_64-linux/rtl/fgl.o... found
    [0.684] Searching file /usr/lib/fpc/3.0.0/units/x86_64-linux/rtl-console/crt.o... found
    [0.684] Searching file /usr/lib/fpc/3.0.0/units/x86_64-linux/fv/dialogs.o... found
    [0.688] Searching file /usr/lib/fpc/3.0.0/units/x86_64-linux/fcl-xml/xmlread.o... found
    [0.688] Searching file /usr/lib/fpc/3.0.0/units/x86_64-linux/fcl-xml/xmlwrite.o... found
    [0.688] Searching file /usr/lib/fpc/3.0.0/units/x86_64-linux/fcl-xml/xmlutils.o... found
    [0.688] Searching file /usr/lib/fpc/3.0.0/units/x86_64-linux/fcl-xml/xmlstreaming.o... found
    [0.688] Searching file /usr/lib/fpc/3.0.0/units/x86_64-linux/fcl-xml/dom.o... found
    Quand je supprime les fichiers qu'il trouve et que je relance la compilation ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    Warning: Object madlib_xml.o not found, Linking may fail !
    Warning: Object madlib_ini.o not found, Linking may fail !
    Warning: Object madlib_filesystem.o not found, Linking may fail !
    Warning: Object madlib_cmdline.o not found, Linking may fail !
    Warning: Object madlib_systemenvironment.o not found, Linking may fail !
    Warning: Object madlib_string.o not found, Linking may fail !
    Warning: Object madlib_numeric.o not found, Linking may fail !
    Warning: Object madlib_convert.o not found, Linking may fail !
    Warning: Object madlib_tinylog.o not found, Linking may fail !
    Linking erelios
    /usr/bin/ld.bfd*: avertissement*: link.res contient des sections de sortie; avez-vous oublié -T?
    /usr/bin/ld.bfd*: ne peut trouver madlib_xml.o
    /usr/bin/ld.bfd*: ne peut trouver madlib_ini.o
    /usr/bin/ld.bfd*: ne peut trouver madlib_filesystem.o
    /usr/bin/ld.bfd*: ne peut trouver madlib_cmdline.o
    /usr/bin/ld.bfd*: ne peut trouver madlib_systemenvironment.o
    /usr/bin/ld.bfd*: ne peut trouver madlib_string.o
    /usr/bin/ld.bfd*: ne peut trouver madlib_numeric.o
    /usr/bin/ld.bfd*: ne peut trouver madlib_convert.o
    /usr/bin/ld.bfd*: ne peut trouver madlib_tinylog.o
    Error: Error while linking
    Fatal: There were 1 errors compiling module, stopping

  5. #5
    Membre confirmé

    Homme Profil pro
    Autre
    Inscrit en
    Novembre 2015
    Messages
    145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Novembre 2015
    Messages : 145
    Points : 625
    Points
    625
    Par défaut
    Si vous parlez de mon petit exemple précédent (même taille d'exécutable de 176 Ko), c'est tout à fait normal: il n'y a en effet pas assez de code et/ou de données concernés pour que cela impacte la taille de l'exécutable final (32 octets de code et 16 octets de données en 64 bits seulement !).

    Il faut bien sûr projeter cet exemple dans le cas ou beaucoup de code, de données, de ressources, etc... sont utilisés; et je ne parle pas du code présent uniquement dans les sections Initialization/Finalization du module, mais de aussi tout le code qu'il peut appeler dans d'autre modules, ainsi que des éventuelles propres sections Initialization/Finalization des "sous-modules" utilisés par le module concerné (et ainsi de suite en cascade).

    Voici donc un autre petit exemple, qui induit une -légère- différence de taille dans l'exécutable cette fois: même unité principale mais unité non utilisée suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    unit UnusedUnit;
     
    {$mode objfpc}{$H+}
     
    interface
     
    uses
      PasZlib;
     
    function TestZlib(): boolean;
     
    implementation
     
    function TestZlib(): boolean;
    var Data1: array [0..pred(256)] of byte;
    var Data2: array [0..pred(1024)] of byte;
    var DataLen1, DataLen2: cardinal;
    begin
      result := false;
      Data1[0] := 0; Data2[0] := 0;   // avoid hint
      FillChar(Data1, SizeOf(Data1), $A5);
      FillChar(Data2, SizeOf(Data2), 0);
      DataLen1 := SizeOf(Data1);
      DataLen2 := SizeOf(Data2);
      if compress(@Data2[0], DataLen2, @Data1[0], DataLen1) = Z_OK then
        begin
          FillChar(Data1, SizeOf(Data1), 0);
          if uncompress(@Data1[0], DataLen1, @Data2[0], DataLen2) = Z_OK then
            if (Data1[0] = $A5) and (Data1[pred(256)] = $A5) then
              result := true;
        end;
    end;
     
    Initialization
      TestZlib();
     
    end.
    Avec la section Initialization :
    Hint: (11030) Start of reading config file C:\lazarus\fpc\3.0.4\bin\x86_64-win64\fpc.cfg
    Hint: (11031) End of reading config file C:\lazarus\fpc\3.0.4\bin\x86_64-win64\fpc.cfg
    Free Pascal Compiler version 3.0.4 [2017/12/03] for x86_64
    Copyright (c) 1993-2017 by Florian Klaempfl and others
    (1002) Target OS: Win64 for x64
    (3104) Compiling project1.lpr
    (3104) Compiling unusedunit.pas
    (9015) Linking project1.exe
    (1008) 45 lines compiled, 0.2 sec, 74224 bytes code, 5076 bytes data
    (1022) 2 hint(s) issued
    Soit au total pour moi 152 Ko pour l'exécutable (Windows FPC 64 bits 3.0.4, O1, avec debug).


    Même chose, mais en commentant cette fois la section Initialization:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    //Initialization
    //  TestZlib();
    Hint: (11030) Start of reading config file C:\lazarus\fpc\3.0.4\bin\x86_64-win64\fpc.cfg
    Hint: (11031) End of reading config file C:\lazarus\fpc\3.0.4\bin\x86_64-win64\fpc.cfg
    Free Pascal Compiler version 3.0.4 [2017/12/03] for x86_64
    Copyright (c) 1993-2017 by Florian Klaempfl and others
    (1002) Target OS: Win64 for x64
    (3104) Compiling project1.lpr
    (3104) Compiling unusedunit.pas
    C:\.....\project1.lpr(4,3) Hint: (5023) Unit "UnusedUnit" not used in project1
    (9015) Linking project1.exe
    (1008) 45 lines compiled, 0.2 sec, 41600 bytes code, 1492 bytes data
    (1022) 3 hint(s) issued
    Soit au total 104 Ko (Windows FPC 64 bits 3.0.4, O1, avec debug).



    Concernant la seconde partie de votre message, c'est difficile à dire sans avoir le code sous les yeux. Ceci étant je note que le compilateur indique 5 unités "MadLib_..." non utilisées, alors que vous en supprimez ensuite 9: il y en aurait (conditionnel) donc 4 de nécessaires ...

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 24
    Points : 13
    Points
    13
    Par défaut
    Oui tout à fait j'ai fait exprès de supprimer 9 objets, afin de savoir s'il faisait le tri. Pour l'instant je peux m'apercevoir, qu'il ne fait pas le tri, entre ceux dont j'ai besoin ou non.
    Il prend tout sans se soucier de l'étape effectuée plus haut où il indique que n'ai pas besoin du XML par exemple.

    Bien sûr, en supprimant les PPU il reconstruit l’ensemble. Mais avec les modules dont il n'a pas besoin.


    [0.730] Stack frame is omitted
    [0.730] Stack frame is omitted
    [0.730] erelios.pas(127,12) Hint: Local type "MyType" is not used
    [0.730] MADLib-all.inc(36,2) Hint: Unit "MadLib_xml" not used in Erelios
    [0.730] MADLib-all.inc(38,2) Hint: Unit "MadLib_FileSystem" not used in Erelios
    [0.730] MADLib-all.inc(41,5) Hint: Unit "MadLib_String" not used in Erelios
    [0.730] MADLib-all.inc(42,5) Hint: Unit "MadLib_Numeric" not used in Erelios
    [0.730] MADLib-all.inc(43,2) Hint: Unit "MadLib_Convert" not used in Erelios
    [0.730] (ERELIOS) Unloading resource unit FPINTRES (not needed)
    [0.730] Assembling erelios
    [0.730] Searching file /usr/lib/fpc/3.0.0/bin/x86_64-linux/as... not found
    [0.730] Searching file /usr/lib/fpc/3.0.0/bin/x86_64-linux/AS... not found
    [0.730] Searching file /usr/lib/fpc/3.0.0/as... not found
    [0.730] Searching file /usr/lib/fpc/3.0.0/AS... not found
    [0.730] Searching file /usr/local/bin/as... not found
    [0.730] Searching file /usr/local/bin/AS... not found
    [0.730] Searching file /usr/bin/as... found
    [0.730] Using assembler: /usr/bin/as
    [0.730] Executing "/usr/bin/as" with command line "--64 -o erelios.o erelios.s"
    [0.750] Searching file erelios.o... found
    [0.750] Searching file /usr/lib/fpc/3.0.0/units/x86_64-linux/rtl/system.o... found
    [0.758] Searching file /usr/lib/fpc/3.0.0/units/x86_64-linux/rtl/objpas.o... found
    [0.758] Searching file ./MADLib/commun/madlib_xml.o... found
    [0.758] Searching file ./MADLib/commun/madlib_ini.o... found
    [0.758] Searching file ./MADLib/commun/madlib_filesystem.o... found
    [0.758] Searching file ./MADLib/commun/madlib_cmdline.o... found
    [0.758] Searching file ./MADLib/commun/madlib_systemenvironment.o... found
    [0.758] Searching file ./MADLib/commun/madlib_string.o... found
    [0.758] Searching file ./MADLib/commun/madlib_numeric.o... found
    [0.758] Searching file ./MADLib/commun/madlib_convert.o... found
    [0.758] Searching file ./MADLib/commun/madlib_tinylog.o... found
    [0.758] Searching file ./MADLib/linux/madlib_dhcpd.o... found
    [0.758] Searching file ./MADLib/linux/madlib_dnsmasq.o... found

  7. #7
    Membre confirmé

    Homme Profil pro
    Autre
    Inscrit en
    Novembre 2015
    Messages
    145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Novembre 2015
    Messages : 145
    Points : 625
    Points
    625
    Par défaut
    Les sections Initialization/Finalization ne sont qu'une des raisons possibles.

    Il pourrait aussi -par exemple- y avoir des ressources externes déclarées dans les unités concernées.

    Ainsi, toujours avec mon exemple précédent,
    - créer une image bitmap de taille conséquente appelée 'MyImg.bmp',
    - créer un fichier de ressource type Windows qui l'utilise (cf. ci-après)
    - utiliser ce fichier ressource dans l'unité 'UnusedUnit'.

    Unité 'UnusedUnit.pas':

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    unit UnusedUnit;
     
    interface
     
    implementation
     
    {$R UnusedUnit.rc}
     
    end.

    Fichier ressource Windows UnusedUnit.rc (mettre également un fichier de type image bitmap nommé "MyImg.bmp" dans le même répertoire):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MyImg BITMAP "MyImg.bmp"

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 24
    Points : 13
    Points
    13
    Par défaut Exemple
    Bonjour FChrisF et merci des réponses.

    J'ai compris le côté initialisation. Je pensais que si l'unitée n'était pas utilisée, elle était tout simplement écartée de la compilation.
    Du coup, si une unité n'est pas utilisée et qu'elle n'aie rien dans initialization, alors elle ne sera pas utilisée lors de la compilation, sauf si, celle-ci utilise elle même d'autres unitées.

    J'ai effectué deux tests très simple pour voir si FPC supprimait les modules complètement.

    1. Programme vide avec insertion d'une unité "sysutils"
    2. Insertion d'une unité perso ou on inclue l'unité sysutils



    1 - Inclure une unité que l'on utilise pas.

    J'ai pris un fichier vide et écris ce ceci dedans ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    program InToStr;
     
     
    begin
    // Y'a pas grand chose
    end.
    J'ai lancé la compilation d'une manière simple :
    fpc MonFichier.pas
    J'ai fait plusieurs tests sous Linux et Windows. L'exemple montré est sous Windows.

    J'obtient donc le poids de 31Ko.


    Je recommence l'opération mais cette fois si je rajoute un module intercalaire lui non plus ne sera pas utilisé ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    program InToStr;
     
    Uses sysutils;
     
    begin
    // Y'a pas grand chose
    end.
    J'obtient le poid de 84Ko.

    Voici le détail qui est intéressant :

    [1.947] [1.822] Number of unresolved externals in objects 161
    [1.823] Number of unresolved externals after static libraries 161
    [1.825] Number of unresolved externals after defining symbols provided by link script 161
    [1.827] Number of unresolved externals after defining COMMON symbols 161
    [1.828] Number of unresolved externals after DLL imports 0
    [1.834] Disabling empty section .pdata
    [1.835] Disabling empty section .tls
    [1.836] Disabling empty section .edata
    [1.837] Disabling empty section .rsrc
    [1.838] Disabling empty section .reloc
    [1.839] Disabling empty section .gnu_debuglink
    [1.840] Disabling empty section .debug_aranges
    [1.842] Disabling empty section .debug_pubnames
    [1.843] Disabling empty section .debug_info
    [1.844] Disabling empty section .debug_abbrev
    [1.845] Disabling empty section .debug_line
    [1.846] Disabling empty section .debug_frame
    [1.847] Disabling empty section .debug_str
    [1.852] Disabling empty section .debug_loc
    [1.853] Disabling empty section .debug_macinfo
    [1.854] Disabling empty section .debug_weaknames
    [1.855] Disabling empty section .debug_funcnames
    [1.856] Disabling empty section .debug_typenames
    [1.857] Disabling empty section .debug_varnames
    [1.858] Disabling empty section .debug_ranges
    [1.859] Disabling empty section .stab
    [1.860] Disabling empty section .stabstr
    [1.947] Size of Code: 64144 bytes
    [1.948] Size of initialized data: 4068 bytes
    [1.949] Size of uninitialized data: 7700 bytes
    [1.950] Stack space reserved: 16777216 bytes
    [1.955] 22 lines compiled, 2.0 sec, 64144 bytes code, 4068 bytes data
    [1.956] 2 hint(s) issued
    [1.957] 1 note(s) issued
    En effet si cela est bien dû à la section initalization du module, c'est l'explication.

    2 - Inclure une unité dans une autre unité que l'on utilise pas non plus !

    Deuxième essai cette fois-ci avec un module (unité)

    Voici donc le corps de mon module :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    UNIT MyModule;
     
    INTERFACE
     
     
    	USES sysutils;			
     
     
     
    	IMPLEMENTATION
     
    		// Y'a pas foule !!
    END.
    Puis celui de mon corps principal :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    program InToStr;
     
    Uses MyModule;
     
     
    begin
    	// Y'a pas grand chose
    end.
    Résultat pareil que le premier dès que le programme principal ou un module même non appelé insère des modules avec section initialization
    on retombe sur le même poids.

    J'ai testé plusieurs paramètre de FPC pour créer des liens statitiques, faire du smartlink, etc ...

    {$OPTIMIZATION REGVAR,SIZE,LEVEL2,REMOVEEMPTYPROCS,CSE}
    {$SMARTLINK ON}
    et
    fpc -va -a -O4 -XX -Xs -XS MonFichier.pas
    Rien ... le poids est toujours pareil au total 84 Ko ... FPC même si il m'indique que je n'ai pas utilisé un module m'effectue le côté "Initialization" et même d'un sous module...

    Dans l'exemple il ne devrait pas (je crois) m'inclure l'unité sysutils se trouvant dans l'unité mymodule laquelle n'est pas utilisée.

    Du coup que faire quand un module inutilisé doit être écarté automatiquement ? Y a-t-il un paramètre spécifique que j'aurais oublié ?

    J'ai remarqué que dans l'exemple avec UnusedUnit il était utilisé LAZARUS ... et non FPC seul.

    Y'a donc un fichier de configuration passé au compilateur C:\lazarus\fpc\3.0.4\bin\x86_64-win64\fpc.cfg
    Je serai curieux de voir ce qu'il y a dedans.

    Merci d'avance de vos réponses.
    [MAD]

  9. #9
    Membre confirmé

    Homme Profil pro
    Autre
    Inscrit en
    Novembre 2015
    Messages
    145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Novembre 2015
    Messages : 145
    Points : 625
    Points
    625
    Par défaut
    Le compilateur/linker parcourt récursivement toutes les unités appelées dans votre projet: il est donc normal que votre second test ne change en effet rien par rapport au premier.

    Il n'y a, à ma connaissance, aucun moyen de "supprimer" l'intégration du code/des données des sections Initialization et Finalization concernées dans votre exécutable.

    Si cela se passe de cette façon, c'est parce que le linker ne peut pas déterminer à votre place si le code/les données utilisées dans ces sections sont "nécessaires" ou pas à votre projet. Il faut comprendre que même si vous n'appelez pas directement le code concerné, ou même si vous pensez ne pas l'utiliser, bien souvent ces sections contiennent des parties intrinsèquement "utiles" à votre projet (de manière plus ou moins sous-jacente).

    Par exemple, dans le cas de votre test ces sections de l'unité SysUtils intègrent, notamment, la mise en place d'un gestionnaire d'exceptions/d'erreurs pour tout votre projet.

    Extrait de SysUtils.pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Initialization
      InitWin32Widestrings;
      InitExceptions;       { Initialize exceptions. OS independent }
    {$ifdef mswindows}      { Keeps exe size down for systems that do not use SEH }
      ExceptObjProc:=@WinExceptionObject;
      ExceptClsProc:=@WinExceptionClass;
    {$endif mswindows}
      InitInternational;    { Initialize internationalization settings }
      LoadVersionInfo;
      InitSysConfigDir;
      OnBeep:=@SysBeep;
    Finalization
      DoneExceptions;
    end.

    Si vous testez un petit programme qui provoque une erreur (une division par zéro, par exemple), avec et sans cette unité SysUtils, vous verrez alors la différence lors du plantage.



    J'ai en effet utilisé le compilateur Free Pascal de Lazarus pour mes exemples, parce que j'utilise Lazarus. Mais le fichier fpc.cfg ne contient, à ma connaissance, que les infos utiles au compilateur/linker pour son travail, notamment tous les chemins nécessaires pour retrouver ses "petits".

    Il n'est pas impossible qu'il y ait des différences avec celui venant en standard avec Free Pascal uniquement, mais aucune n'aura de toute façon d'influence en ce qui concerne votre problème.

    #
    # Config file generated by fpcmkcfg on 08/12/2017 - 20:13:30
    # Example fpc.cfg for Free Pascal Compiler
    #

    # ----------------------
    # Defines (preprocessor)
    # ----------------------

    #
    # nested #IFNDEF, #IFDEF, #ENDIF, #ELSE, #DEFINE, #UNDEF are allowed
    #
    # -d is the same as #DEFINE
    # -u is the same as #UNDEF
    #

    #
    # Some examples (for switches see below, and the -? helppages)
    #
    # Try compiling with the -dRELEASE or -dDEBUG on the commandline
    #

    # For a release compile with optimizes and strip debuginfo
    #IFDEF RELEASE
    -O2
    -Xs
    #WRITE Compiling Release Version
    #ENDIF

    # For a debug version compile with debuginfo and all codegeneration checks on
    #IFDEF DEBUG
    -gl
    -Crtoi
    #WRITE Compiling Debug Version
    #ENDIF

    # assembling
    #ifdef darwin
    # use pipes instead of temporary files for assembling
    -ap
    # path to Xcode 4.3+ utilities (no problem if it doesn't exist)
    -FD/Applications/Xcode.app/Contents/Developer/usr/bin
    #endif

    # ----------------
    # Parsing switches
    # ----------------

    # Pascal language mode
    # -Mfpc free pascal dialect (default)
    # -Mobjfpc switch some Delphi 2 extensions on
    # -Mdelphi tries to be Delphi compatible
    # -Mtp tries to be TP/BP 7.0 compatible
    # -Mgpc tries to be gpc compatible
    # -Mmacpas tries to be compatible to the macintosh pascal dialects
    #
    # Turn on Object Pascal extensions by default
    #-Mobjfpc

    # Assembler reader mode
    # -Rdefault use default assembler
    # -Ratt read AT&T style assembler
    # -Rintel read Intel style assembler
    #
    # All assembler blocks are AT&T styled by default
    #-Ratt

    # Semantic checking
    # -S2 same as -Mobjfpc
    # -Sc supports operators like C (*=,+=,/= and -=)
    # -Sa include assertion code.
    # -Sd same as -Mdelphi
    # -Se<x> error options. <x> is a combination of the following:
    # <n> : compiler stops after <n> errors (default is 1)
    # w : compiler stops also after warnings
    # n : compiler stops also after notes
    # h : compiler stops also after hints
    # -Sg allow LABEL and GOTO
    # -Sh Use ansistrings
    # -Si support C++ styled INLINE
    # -Sk load fpcylix unit
    # -SI<x> set interface style to <x>
    # -SIcom COM compatible interface (default)
    # -SIcorba CORBA compatible interface
    # -Sm support macros like C (global)
    # -So same as -Mtp
    # -Sp same as -Mgpc
    # -Ss constructor name must be init (destructor must be done)
    # -Sx enable exception keywords (default in Delphi/ObjFPC modes)
    #
    # Allow goto, inline, C-operators, C-vars
    -Sgic

    # ---------------
    # Code generation
    # ---------------

    # Uncomment the next line if you always want static/dynamic units by default
    # (can be overruled with -CD, -CS at the commandline)
    #-CS
    #-CD

    # Set the default heapsize to 8Mb
    #-Ch8000000

    # Set default codegeneration checks (iocheck, overflow, range, stack)
    #-Ci
    #-Co
    #-Cr
    #-Ct

    # Optimizer switches
    # -Os generate smaller code
    # -Oa=N set alignment to N
    # -O1 level 1 optimizations (quick optimizations, debuggable)
    # -O2 level 2 optimizations (-O1 + optimizations which make debugging more difficult)
    # -O3 level 3 optimizations (-O2 + optimizations which also may make the program slower rather than faster)
    # -Oo<x> switch on optimalization x. See fpc -i for possible values
    # -OoNO<x> switch off optimalization x. See fpc -i for possible values
    # -Op<x> set target cpu for optimizing, see fpc -i for possible values

    #ifdef darwin
    #ifdef cpui386
    -Cppentiumm
    -Oppentiumm
    #endif
    #endif

    # -----------------------
    # Set Filenames and Paths
    # -----------------------

    # Both slashes and backslashes are allowed in paths

    # path to the messagefile, not necessary anymore but can be used to override
    # the default language
    #-FrC:\lazarus\fpc\$FPCVERSION/msg/errore.msg
    #-FrC:\lazarus\fpc\$FPCVERSION/msg/errorn.msg
    #-FrC:\lazarus\fpc\$FPCVERSION/msg/errores.msg
    #-FrC:\lazarus\fpc\$FPCVERSION/msg/errord.msg
    #-FrC:\lazarus\fpc\$FPCVERSION/msg/errorr.msg

    # search path for unicode binary files (FPC 2.x does not know this switch)
    #ifndef VER2
    -FM/unicode/
    #endif

    # searchpath for units and other system dependent things
    -FuC:\lazarus\fpc\$FPCVERSION/units/$fpctarget
    -FuC:\lazarus\fpc\$FPCVERSION/units/$fpctarget/*
    -FuC:\lazarus\fpc\$FPCVERSION/units/$fpctarget/rtl

    #ifdef cpui8086
    -FuC:\lazarus\fpc\$FPCVERSION/units/$fpctarget/$fpcsubarch-$fpcmemorymodel
    -FuC:\lazarus\fpc\$FPCVERSION/units/$fpctarget/$fpcsubarch-$fpcmemorymodel/*
    -FuC:\lazarus\fpc\$FPCVERSION/units/$fpctarget/$fpcsubarch-$fpcmemorymodel/rtl
    #endif

    #IFDEF FPCAPACHE_1_3
    -FuC:\lazarus\fpc\$FPCVERSION/units/$fpctarget/httpd13/
    #ELSE
    #IFDEF FPCAPACHE_2_0
    -FuC:\lazarus\fpc\$FPCVERSION/units/$fpctarget/httpd20
    #ELSE
    -FuC:\lazarus\fpc\$FPCVERSION/units/$fpctarget/httpd22
    #ENDIF
    #ENDIF

    # searchpath for fppkg user-specific packages
    -Fu$LOCAL_APPDATA\FreePascal\fppkg/units/$FPCTARGET/*

    # path to the gcclib


    # searchpath for libraries
    #-FlC:\lazarus\fpc\$FPCVERSION/lib
    #-Fl/lib;/usr/lib
    -FlC:\lazarus\fpc\$FPCVERSION/lib/$FPCTARGET

    # searchpath for tools
    -FDC:\lazarus\fpc\$FPCVERSION/bin/$FPCTARGET

    #IFNDEF CPUI386
    #IFNDEF CPUAMD64
    #DEFINE NEEDCROSSBINUTILS
    #ENDIF
    #ENDIF

    #IFNDEF Win64
    #DEFINE NEEDCROSSBINUTILS
    #ENDIF

    # never need cross-prefix when targeting the JVM
    # (no native compiler, always cross-compiling)
    #ifdef cpujvm
    #undef NEEDCROSSBINUTILS
    #endif

    # for android cross-prefix is set by compiler
    #ifdef android
    #undef NEEDCROSSBINUTILS
    #endif

    # never need cross-prefix when targeting the i8086
    # (no native compiler, always cross-compiling)
    #ifdef cpui8086
    #undef NEEDCROSSBINUTILS
    #endif

    # never need cross-prefix when targeting the i8086
    # (no native compiler, always cross-compiling)
    #ifdef cpujvm
    #undef NEEDCROSSBINUTILS
    #endif

    # binutils prefix for cross compiling
    #IFDEF FPC_CROSSCOMPILING
    #IFDEF NEEDCROSSBINUTILS
    -XP$FPCTARGET-
    #ENDIF
    #ENDIF


    # -------------
    # Linking
    # -------------

    # generate always debugging information for GDB (slows down the compiling
    # process)
    # -gc generate checks for pointers
    # -gd use dbx
    # -gg use gsym
    # -gh use heap trace unit (for memory leak debugging)
    # -gl use line info unit to show more info for backtraces
    # -gv generates programs tracable with valgrind
    # -gw generate dwarf debugging info
    #
    # Enable debuginfo and use the line info unit by default
    #-gl

    # always pass an option to the linker
    #-k-s

    # Always strip debuginfo from the executable
    -Xs

    # Always use smartlinking on i8086, because the system unit exceeds the 64kb
    # code limit
    #ifdef cpui8086
    -CX
    -XX
    #endif


    # -------------
    # Miscellaneous
    # -------------

    # Write always a nice FPC logo ;)
    -l

    # Verbosity
    # e : Show errors (default) d : Show debug info
    # w : Show warnings u : Show unit info
    # n : Show notes t : Show tried/used files
    # h : Show hints s : Show time stamps
    # i : Show general info q : Show message numbers
    # l : Show linenumbers c : Show conditionals
    # a : Show everything 0 : Show nothing (except errors)
    # b : Write file names messages r : Rhide/GCC compatibility mode
    # with full path x : Executable info (Win32 only)
    # v : write fpcdebug.txt with p : Write tree.log with parse tree
    # lots of debugging info
    #
    # Display Info, Warnings and Notes
    -viwn
    # If you don't want so much verbosity use
    #-vw

  10. #10
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 24
    Points : 13
    Points
    13
    Par défaut
    Bonjour FChrisF,

    Je reviens sur ce sujet pour mon problème du poids. Comme je ne trouvais pas, j'ai dû refaire mes implantations de modules avec des détections de macro-variables pour que le compilateur prenne ou non mon fichier.
    Le souci c'est qu'il faut systématiquement ne pas oublier d'inclure et/ou de mettre le variable genre {$DEFINE LIBLOG}, qui fera insérer le fichier en relation.

    Bref très lourd.
    Et puis...

    Un jour dans la ligne de commande de compilation, j'ai oublié de mettre -XS et -Xs, je n'ai mis que -XX...

    Eh bien je n'en croyais pas mes yeux. Le binaire était plusieurs fois plus léger.

    Je suis passé de 1,5 Mo à 450 Ko ...

    J'ai retenté l'opération sur mon ancienne implémentation de module. À savoir qu'on inclut tout et le compilateur se débrouille pour faire le tri des modules ou sous-modules que je n'utilise pas. Et là miracle...

    Là encore mon binaire exécutable devenait raisonnable en poids.

    Depuis je ne mets plus que -XX. Visiblement les deux enssembles (-XX -Xs ou -XS) c'est pas super. Mais pourquoi ?

    Voilà pour les news

Discussions similaires

  1. Optimisation performance MYSQL
    Par adapt dans le forum Requêtes
    Réponses: 1
    Dernier message: 29/09/2009, 15h10
  2. Optimisation requête pour cause de Maximum execution time
    Par cans38 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 01/09/2008, 15h36
  3. Optimisation performance accès BD pour appli Web
    Par killysui dans le forum ASP.NET
    Réponses: 10
    Dernier message: 23/06/2008, 14h23
  4. Réponses: 3
    Dernier message: 05/04/2006, 15h13
  5. [Access] Optimisation performance requête - Index
    Par fdraven dans le forum Access
    Réponses: 11
    Dernier message: 12/08/2005, 14h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo