forked from menault/2026_TD3_DEV51_Qualite_Algo
rapport début
This commit is contained in:
@@ -0,0 +1,84 @@
|
|||||||
|
# Compte rendu — TD 3 : complexité algorithmique
|
||||||
|
Nathan COUCHOT et Lucas POT
|
||||||
|
|
||||||
|
## 1. Mesurer le programme
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gcc -O2 banque.c -o banque
|
||||||
|
time ./banque
|
||||||
|
```
|
||||||
|
|
||||||
|
La version initiale s'exécute en environ **2,26 s**.
|
||||||
|
|
||||||
|
| Mesure initiale | Résultat |
|
||||||
|
| --- | ---: |
|
||||||
|
| Temps réel (`real`) | 2,26 s |
|
||||||
|
| Temps CPU utilisateur (`user`) | 2,23 s |
|
||||||
|
| Temps CPU système (`sys`) | 0,00 s |
|
||||||
|
| Empreinte | `ff68d260a7a58441` |
|
||||||
|
|
||||||
|
L'empreinte attendue est **`ff68d260a7a58441`**.
|
||||||
|
|
||||||
|
## 2. Profiler et analyser le programme initial
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gcc -O0 -g -pg banque.c -o banque_pg
|
||||||
|
./banque_pg
|
||||||
|
gprof ./banque_pg gmon.out > profil_avant.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
Le temps réel mesuré avec l'instrumentation est **8,35 s**, contre **2,26 s** sans `-pg`. Cette différence vient en partie du coût ajouté par le comptage des appels. Le profil complet est fourni dans profil_avant.txt.
|
||||||
|
|
||||||
|
| Fonction | Part du temps propre | Temps propre | Appels |
|
||||||
|
| --- | ---: | ---: | ---: |
|
||||||
|
| `trier_par_montant` | 49,43 % | 3,02 s | 1 |
|
||||||
|
| `rechercher_par_id` | 13,42 % | 0,82 s | 30 000 |
|
||||||
|
| `nb_paires_opposees` | 11,95 % | 0,73 s | 1 |
|
||||||
|
| `nb_facons_rendre` | 8,27 % | 0,51 s | 1 appel depuis `main` |
|
||||||
|
| `longueur` | 6,87 % | 0,42 s | 6 017 |
|
||||||
|
| `meilleure_periode` | 4,91 % | 0,30 s | 1 |
|
||||||
|
| `total_par_client` | 1,80 % | 0,11 s | 1 |
|
||||||
|
| `nb_clients_distincts` | 1,64 % | 0,10 s | 1 |
|
||||||
|
| `total_par_jour` | 0,82 % | 0,05 s | 1 |
|
||||||
|
|
||||||
|
Le tri à bulles est le principal point chaud du profil. `rechercher_par_id` est appelée 30 000 fois et parcourt le tableau à chaque recherche. `ajouter_ligne` appelle `longueur` pour retrouver la fin du rapport ; comme le rapport grandit à chaque ajout, ces recherches répétées reparcourent une quantité croissante de caractères.
|
||||||
|
|
||||||
|
Le graphe d'appels permet aussi de voir le coût récursif de `nb_facons_rendre`. Le profil plat ne montre qu'un appel depuis `main`, mais cet appel entraîne de nombreux appels récursifs. Le temps propre observé ne suffit donc pas à lui seul pour expliquer le coût total.
|
||||||
|
|
||||||
|
Les fonctions les plus coûteuses n'ont pas nécessairement les complexités les plus élevées. Le tri traite 30 000 transactions, tandis que `meilleure_periode` traite 1 000 jours. Le temps mesuré dépend à la fois de la complexité et de la taille effective des données.
|
||||||
|
|
||||||
|
## 3. Complexités algorithmiques et cyclomatiques
|
||||||
|
|
||||||
|
On note **n** le nombre de transactions, **C** le nombre de clients, **J** le nombre de jours, **Q** le nombre de requêtes, **S** la somme à rendre, **k** le nombre de pièces et **L** la longueur finale du rapport. Les paramètres sont considérés variables pour l'analyse, même si le programme utilise des constantes.
|
||||||
|
|
||||||
|
| Fonction | Calcule | Actuelle | Objectif |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| F1 `trier_par_montant` | tri des transactions | O(n²) | O(n log n) |
|
||||||
|
| F2 `nb_clients_distincts` | clients différents | O(n²) | O(n + C) |
|
||||||
|
| F3 `total_par_client` | solde par client | O(n * c) | O(n + C) |
|
||||||
|
| F4 `total_par_jour` | solde par jour | O(n * J) | O(n + J) |
|
||||||
|
| F5 `meilleure_periode` | période la plus rentable | O(J³) | O(J) |
|
||||||
|
| F6 `rechercher_par_id` | recherche par identifiant | O(n) | O(1) par requête |
|
||||||
|
| F7 `nb_paires_opposees` | paires a + b = 0 | O(n²) | O(n log n) |
|
||||||
|
| F8 `nb_facons_rendre` | rendu de monnaie | O(S^n) | O(S × k) |
|
||||||
|
| F9 `categorie` | catégorie d'une transaction | M = 14 | M ≤ 10 |
|
||||||
|
| F10 `ajouter_ligne` | construction du rapport | O(n) | O(L) au total |
|
||||||
|
|
||||||
|
### Complexité cyclomatique des fonctions F1 à F10
|
||||||
|
|
||||||
|
On calcule **M = nombre de décisions + 1**.
|
||||||
|
|
||||||
|
| Fonction | Décisions | Calcul de M |
|
||||||
|
| --- | --- | ---: |
|
||||||
|
| F1 `trier_par_montant` | 2 `for` + 1 `if` + 1 `||` + 1 `&&` | 5 + 1 = **6** |
|
||||||
|
| F2 `nb_clients_distincts` | 2 `for` + 2 `if` | 4 + 1 = **5** |
|
||||||
|
| F3 `total_par_client` | 2 `for` + 1 `if` | 3 + 1 = **4** |
|
||||||
|
| F4 `total_par_jour` | 2 `for` + 1 `if` | 3 + 1 = **4** |
|
||||||
|
| F5 `meilleure_periode` | 3 `for` + 1 `if` | 4 + 1 = **5** |
|
||||||
|
| F6 `rechercher_par_id` | 1 `for` + 1 `if` | 2 + 1 = **3** |
|
||||||
|
| F7 `nb_paires_opposees` | 2 `for` + 1 `if` | 3 + 1 = **4** |
|
||||||
|
| F8 `nb_facons_rendre` | 2 `if` + 1 `||` | 3 + 1 = **4** |
|
||||||
|
| F9 `categorie` | 11 `if`/`else if` + 1 `||` + 1 `&&` | 13 + 1 = **14** |
|
||||||
|
| F10 `ajouter_ligne` | 1 `while` | 1 + 1 = **2** |
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,220 @@
|
|||||||
|
Flat profile:
|
||||||
|
|
||||||
|
Each sample counts as 0.01 seconds.
|
||||||
|
% cumulative self self total
|
||||||
|
time seconds seconds calls s/call s/call name
|
||||||
|
49.46 3.19 3.19 1 3.19 3.19 trier_par_montant
|
||||||
|
13.49 4.06 0.87 30000 0.00 0.00 rechercher_par_id
|
||||||
|
12.40 4.86 0.80 1 0.80 0.80 nb_paires_opposees
|
||||||
|
7.91 5.37 0.51 1 0.51 0.51 nb_facons_rendre
|
||||||
|
6.36 5.78 0.41 6017 0.00 0.00 longueur
|
||||||
|
4.81 6.09 0.31 1 0.31 0.31 meilleure_periode
|
||||||
|
1.86 6.21 0.12 1 0.12 0.12 total_par_client
|
||||||
|
1.71 6.32 0.11 1 0.11 0.11 nb_clients_distincts
|
||||||
|
0.93 6.38 0.06 1 0.06 0.06 total_par_jour
|
||||||
|
0.93 6.44 0.06 _init
|
||||||
|
0.16 6.45 0.01 30000 0.00 0.00 categorie
|
||||||
|
0.00 6.45 0.00 149998 0.00 0.00 alea
|
||||||
|
0.00 6.45 0.00 6017 0.00 0.00 ajouter_ligne
|
||||||
|
0.00 6.45 0.00 1 0.00 0.00 empreinte
|
||||||
|
0.00 6.45 0.00 1 0.00 0.00 generer_transactions
|
||||||
|
|
||||||
|
% the percentage of the total running time of the
|
||||||
|
time program used by this function.
|
||||||
|
|
||||||
|
cumulative a running sum of the number of seconds accounted
|
||||||
|
seconds for by this function and those listed above it.
|
||||||
|
|
||||||
|
self the number of seconds accounted for by this
|
||||||
|
seconds function alone. This is the major sort for this
|
||||||
|
listing.
|
||||||
|
|
||||||
|
calls the number of times this function was invoked, if
|
||||||
|
this function is profiled, else blank.
|
||||||
|
|
||||||
|
self the average number of milliseconds spent in this
|
||||||
|
ms/call function per call, if this function is profiled,
|
||||||
|
else blank.
|
||||||
|
|
||||||
|
total the average number of milliseconds spent in this
|
||||||
|
ms/call function and its descendents per call, if this
|
||||||
|
function is profiled, else blank.
|
||||||
|
|
||||||
|
name the name of the function. This is the minor sort
|
||||||
|
for this listing. The index shows the location of
|
||||||
|
the function in the gprof listing. If the index is
|
||||||
|
in parenthesis it shows where it would appear in
|
||||||
|
the gprof listing if it were to be printed.
|
||||||
|
|
||||||
|
Copyright (C) 2012-2026 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
Copying and distribution of this file, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved.
|
||||||
|
|
||||||
|
Call graph (explanation follows)
|
||||||
|
|
||||||
|
|
||||||
|
granularity: each sample hit covers 4 byte(s) for 0.16% of 6.45 seconds
|
||||||
|
|
||||||
|
index % time self children called name
|
||||||
|
<spontaneous>
|
||||||
|
[1] 99.1 0.00 6.39 main [1]
|
||||||
|
3.19 0.00 1/1 trier_par_montant [2]
|
||||||
|
0.87 0.00 30000/30000 rechercher_par_id [3]
|
||||||
|
0.80 0.00 1/1 nb_paires_opposees [4]
|
||||||
|
0.51 0.00 1/1 nb_facons_rendre [5]
|
||||||
|
0.00 0.41 6017/6017 ajouter_ligne [6]
|
||||||
|
0.31 0.00 1/1 meilleure_periode [8]
|
||||||
|
0.12 0.00 1/1 total_par_client [9]
|
||||||
|
0.11 0.00 1/1 nb_clients_distincts [10]
|
||||||
|
0.06 0.00 1/1 total_par_jour [11]
|
||||||
|
0.01 0.00 30000/30000 categorie [13]
|
||||||
|
0.00 0.00 1/1 generer_transactions [16]
|
||||||
|
0.00 0.00 1/1 empreinte [15]
|
||||||
|
-----------------------------------------------
|
||||||
|
3.19 0.00 1/1 main [1]
|
||||||
|
[2] 49.5 3.19 0.00 1 trier_par_montant [2]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.87 0.00 30000/30000 main [1]
|
||||||
|
[3] 13.5 0.87 0.00 30000 rechercher_par_id [3]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.80 0.00 1/1 main [1]
|
||||||
|
[4] 12.4 0.80 0.00 1 nb_paires_opposees [4]
|
||||||
|
-----------------------------------------------
|
||||||
|
266723738 nb_facons_rendre [5]
|
||||||
|
0.51 0.00 1/1 main [1]
|
||||||
|
[5] 7.9 0.51 0.00 1+266723738 nb_facons_rendre [5]
|
||||||
|
266723738 nb_facons_rendre [5]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.41 6017/6017 main [1]
|
||||||
|
[6] 6.4 0.00 0.41 6017 ajouter_ligne [6]
|
||||||
|
0.41 0.00 6017/6017 longueur [7]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.41 0.00 6017/6017 ajouter_ligne [6]
|
||||||
|
[7] 6.4 0.41 0.00 6017 longueur [7]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.31 0.00 1/1 main [1]
|
||||||
|
[8] 4.8 0.31 0.00 1 meilleure_periode [8]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.12 0.00 1/1 main [1]
|
||||||
|
[9] 1.9 0.12 0.00 1 total_par_client [9]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.11 0.00 1/1 main [1]
|
||||||
|
[10] 1.7 0.11 0.00 1 nb_clients_distincts [10]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.06 0.00 1/1 main [1]
|
||||||
|
[11] 0.9 0.06 0.00 1 total_par_jour [11]
|
||||||
|
-----------------------------------------------
|
||||||
|
<spontaneous>
|
||||||
|
[12] 0.9 0.06 0.00 _init [12]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.01 0.00 30000/30000 main [1]
|
||||||
|
[13] 0.2 0.01 0.00 30000 categorie [13]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.00 149998/149998 generer_transactions [16]
|
||||||
|
[14] 0.0 0.00 0.00 149998 alea [14]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.00 1/1 main [1]
|
||||||
|
[15] 0.0 0.00 0.00 1 empreinte [15]
|
||||||
|
-----------------------------------------------
|
||||||
|
0.00 0.00 1/1 main [1]
|
||||||
|
[16] 0.0 0.00 0.00 1 generer_transactions [16]
|
||||||
|
0.00 0.00 149998/149998 alea [14]
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
This table describes the call tree of the program, and was sorted by
|
||||||
|
the total amount of time spent in each function and its children.
|
||||||
|
|
||||||
|
Each entry in this table consists of several lines. The line with the
|
||||||
|
index number at the left hand margin lists the current function.
|
||||||
|
The lines above it list the functions that called this function,
|
||||||
|
and the lines below it list the functions this one called.
|
||||||
|
This line lists:
|
||||||
|
index A unique number given to each element of the table.
|
||||||
|
Index numbers are sorted numerically.
|
||||||
|
The index number is printed next to every function name so
|
||||||
|
it is easier to look up where the function is in the table.
|
||||||
|
|
||||||
|
% time This is the percentage of the `total' time that was spent
|
||||||
|
in this function and its children. Note that due to
|
||||||
|
different viewpoints, functions excluded by options, etc,
|
||||||
|
these numbers will NOT add up to 100%.
|
||||||
|
|
||||||
|
self This is the total amount of time spent in this function.
|
||||||
|
|
||||||
|
children This is the total amount of time propagated into this
|
||||||
|
function by its children.
|
||||||
|
|
||||||
|
called This is the number of times the function was called.
|
||||||
|
If the function called itself recursively, the number
|
||||||
|
only includes non-recursive calls, and is followed by
|
||||||
|
a `+' and the number of recursive calls.
|
||||||
|
|
||||||
|
name The name of the current function. The index number is
|
||||||
|
printed after it. If the function is a member of a
|
||||||
|
cycle, the cycle number is printed between the
|
||||||
|
function's name and the index number.
|
||||||
|
|
||||||
|
|
||||||
|
For the function's parents, the fields have the following meanings:
|
||||||
|
|
||||||
|
self This is the amount of time that was propagated directly
|
||||||
|
from the function into this parent.
|
||||||
|
|
||||||
|
children This is the amount of time that was propagated from
|
||||||
|
the function's children into this parent.
|
||||||
|
|
||||||
|
called This is the number of times this parent called the
|
||||||
|
function `/' the total number of times the function
|
||||||
|
was called. Recursive calls to the function are not
|
||||||
|
included in the number after the `/'.
|
||||||
|
|
||||||
|
name This is the name of the parent. The parent's index
|
||||||
|
number is printed after it. If the parent is a
|
||||||
|
member of a cycle, the cycle number is printed between
|
||||||
|
the name and the index number.
|
||||||
|
|
||||||
|
If the parents of the function cannot be determined, the word
|
||||||
|
`<spontaneous>' is printed in the `name' field, and all the other
|
||||||
|
fields are blank.
|
||||||
|
|
||||||
|
For the function's children, the fields have the following meanings:
|
||||||
|
|
||||||
|
self This is the amount of time that was propagated directly
|
||||||
|
from the child into the function.
|
||||||
|
|
||||||
|
children This is the amount of time that was propagated from the
|
||||||
|
child's children to the function.
|
||||||
|
|
||||||
|
called This is the number of times the function called
|
||||||
|
this child `/' the total number of times the child
|
||||||
|
was called. Recursive calls by the child are not
|
||||||
|
listed in the number after the `/'.
|
||||||
|
|
||||||
|
name This is the name of the child. The child's index
|
||||||
|
number is printed after it. If the child is a
|
||||||
|
member of a cycle, the cycle number is printed
|
||||||
|
between the name and the index number.
|
||||||
|
|
||||||
|
If there are any cycles (circles) in the call graph, there is an
|
||||||
|
entry for the cycle-as-a-whole. This entry shows who called the
|
||||||
|
cycle (as parents) and the members of the cycle (as children.)
|
||||||
|
The `+' recursive calls entry shows the number of function calls that
|
||||||
|
were internal to the cycle, and the calls entry for each member shows,
|
||||||
|
for that member, how many times it was called from other members of
|
||||||
|
the cycle.
|
||||||
|
|
||||||
|
Copyright (C) 2012-2026 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
Copying and distribution of this file, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved.
|
||||||
|
|
||||||
|
Index by function name
|
||||||
|
|
||||||
|
[12] _init [16] generer_transactions [4] nb_paires_opposees
|
||||||
|
[6] ajouter_ligne [7] longueur [3] rechercher_par_id
|
||||||
|
[14] alea [8] meilleure_periode [9] total_par_client
|
||||||
|
[13] categorie [10] nb_clients_distincts [11] total_par_jour
|
||||||
|
[15] empreinte [5] nb_facons_rendre [2] trier_par_montant
|
||||||
+6017
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user