forked from menault/2026_TD3_DEV51_Qualite_Algo
Partie 1
This commit is contained in:
+234
@@ -0,0 +1,234 @@
|
||||
# Compte rendu du TD de complexité algorithmique
|
||||
|
||||
Ce compte rendu traite les trois étapes du palier 1 du TD
|
||||
(page 68 de `R5A04_Algorithmique_MM.pdf`) : mesurer la version initiale,
|
||||
la profiler, puis calculer les complexités algorithmiques et cyclomatiques.
|
||||
|
||||
Les mesures ont été réalisées le 21 octobre 2026 sur Linux x86_64, avec
|
||||
GCC 16.2.1 et GNU gprof 2.47. Le fichier `banque.c` est dans sa version initiale.
|
||||
Les données sont reproductibles grâce à la graine fixe du générateur.
|
||||
|
||||
| Paramètre | Valeur |
|
||||
|---|---:|
|
||||
| Transactions, `n` | 30 000 |
|
||||
| Clients, `C` | 2 000 |
|
||||
| Jours, `J` | 1 000 |
|
||||
| Requêtes par identifiant, `Q` | 30 000 |
|
||||
| Somme à rendre, `S` | 400 centimes |
|
||||
| Types de pièces, `k` | 8 |
|
||||
|
||||
## 1. Mesurer la version initiale
|
||||
|
||||
Le Makefile compile le programme avec
|
||||
`gcc -std=c11 -Wall -Wextra -Wpedantic -O2 banque.c -o build/banque`.
|
||||
La compilation s'est terminée sans avertissement. Les commandes utilisées
|
||||
pour compiler et enregistrer une mesure sont les suivantes, depuis la racine :
|
||||
|
||||
```bash
|
||||
make -B all
|
||||
(cd build && { time -p ./banque > sortie.txt; } 2> temps_avant.txt)
|
||||
cat build/sortie.txt build/temps_avant.txt
|
||||
```
|
||||
|
||||
Résultat de l'exécution mesurée :
|
||||
|
||||
```text
|
||||
Clients distincts : 2000
|
||||
Somme des requêtes : -2624578
|
||||
Meilleure période : jours 650 à 986 (3548830)
|
||||
Paires opposées : 5832
|
||||
Façons de rendre 400 : 1960497
|
||||
Empreinte : ff68d260a7a58441
|
||||
real 2.43
|
||||
user 2.39
|
||||
sys 0.00
|
||||
```
|
||||
|
||||
Le temps réel est de **2,43 s**. Le temps CPU passé dans le programme est de
|
||||
2,39 s ; le temps système est arrondi à 0,00 s. Cette mesure porte sur une
|
||||
exécution et peut varier selon la charge de la machine.
|
||||
|
||||
L'empreinte obtenue est bien **`ff68d260a7a58441`**, celle attendue dans le TD.
|
||||
Le rapport produit contient 6 017 lignes, soit 120 348 octets. Les résultats
|
||||
sont conservés dans [sortie.txt](build/sortie.txt) et
|
||||
[temps_avant.txt](build/temps_avant.txt).
|
||||
|
||||
## 2. Profiler et comparer aux complexités
|
||||
|
||||
Le profil a été généré avec les commandes suivantes :
|
||||
|
||||
```bash
|
||||
make profile
|
||||
cp build/profil/profil.txt build/profil/profil_avant.txt
|
||||
```
|
||||
|
||||
La cible `profile` utilise une compilation en `-O0 -g -pg`, exécute le programme,
|
||||
puis lance `gprof -b ./banque gmon.out` dans `build/profil`. Le profil initial
|
||||
est conservé dans [profil_avant.txt](build/profil/profil_avant.txt).
|
||||
|
||||
Cette exécution produit également l'empreinte attendue. Les fichiers
|
||||
`build/rapport.txt` et `build/profil/rapport.txt` ont été comparés : ils sont
|
||||
identiques octet par octet.
|
||||
|
||||
### Résultats de gprof
|
||||
|
||||
Le tableau reprend les temps propres du profil plat : ils correspondent au
|
||||
temps passé dans chaque fonction, hors fonctions appelées. Les pourcentages
|
||||
portent sur environ **6,44 s de temps CPU échantillonné**.
|
||||
|
||||
| Fonction | Appels | Temps propre (s) | Part du temps |
|
||||
|---|---:|---:|---:|
|
||||
| F1 — `trier_par_montant` | 1 | 3,13 | 48,60 % |
|
||||
| F6 — `rechercher_par_id` | 30 000 | 0,85 | 13,20 % |
|
||||
| F7 — `nb_paires_opposees` | 1 | 0,76 | 11,80 % |
|
||||
| F8 — `nb_facons_rendre` | 1 appel initial | 0,66 | 10,17 % |
|
||||
| `longueur`, appelée par F10 | 6 017 | 0,41 | 6,37 % |
|
||||
| F5 — `meilleure_periode` | 1 | 0,32 | 4,97 % |
|
||||
| F2 — `nb_clients_distincts` | 1 | 0,11 | 1,71 % |
|
||||
| F3 — `total_par_client` | 1 | 0,11 | 1,71 % |
|
||||
| F4 — `total_par_jour` | 1 | 0,05 | 0,78 % |
|
||||
| F9 — `categorie` | 30 000 | 0,03 | 0,39 % |
|
||||
| F10 — `ajouter_ligne` | 6 017 | 0,00 | 0,00 % |
|
||||
|
||||
Le graphe d'appels précise que F8 effectue **266 723 738 appels récursifs**,
|
||||
en plus de l'appel initial. Le compteur du profil plat ne montre que cet
|
||||
appel initial. Les écarts entre les pourcentages et les temps affichés
|
||||
s'expliquent par les arrondis ; quelques échantillons sont aussi attribués
|
||||
à `_init`.
|
||||
|
||||
Le temps cumulé de F10, en incluant `longueur`, est d'environ **0,41 s**.
|
||||
Son temps propre affiché à 0,00 s ne signifie donc pas que la construction
|
||||
du rapport est gratuite. Plus généralement, une valeur nulle dans ce profil
|
||||
ne prouve pas l'absence de coût : la période d'échantillonnage est de 0,01 s.
|
||||
|
||||
Ces temps ne se comparent pas directement aux 2,43 s de la première étape :
|
||||
le profil utilise `-O0` et l'instrumentation `-pg`, tandis que la mesure
|
||||
initiale utilise `-O2`. Le profil décrit le comportement de cette version
|
||||
instrumentée, pour ces données et sur cette machine.
|
||||
|
||||
### Les fonctions les plus coûteuses ont-elles les pires complexités ?
|
||||
|
||||
**Non, pas systématiquement.** La complexité décrit la croissance du nombre
|
||||
d'opérations lorsque la taille des entrées augmente. Le profil mesure le coût
|
||||
d'une exécution précise. Ce coût dépend aussi des tailles effectivement
|
||||
utilisées, du nombre d'appels, des données et du travail effectué à chaque
|
||||
itération.
|
||||
|
||||
- **F1 : le tri quadratique domine ici.** Le tri à bulles effectue
|
||||
`n(n - 1) / 2`, soit **449 985 000 comparaisons de paires voisines**, avec
|
||||
des échanges de structures lorsque les transactions sont mal ordonnées.
|
||||
Sa complexité est `O(n²)` et il représente 48,60 % du temps échantillonné.
|
||||
|
||||
- **F5 : une complexité cubique ne suffit pas à en faire la fonction la plus
|
||||
lente.** Ses trois boucles donnent une complexité `O(J³)`, mais elles portent
|
||||
sur **1 000 jours**, alors que F1 traite 30 000 transactions. F5 effectue
|
||||
`J(J + 1)(J + 2) / 6`, soit **167 167 000 additions**, et prend environ
|
||||
0,32 s, contre 3,13 s pour F1. Les variables et les tailles diffèrent :
|
||||
comparer uniquement les exposants serait trompeur.
|
||||
|
||||
- **F6 : le nombre d'appels compte.** Une recherche par identifiant est en
|
||||
`O(n)` au pire cas, mais `main` l'effectue **30 000 fois**. Le coût de
|
||||
l'ensemble des recherches est donc `O(Q × n)`, soit `O(n²)` lorsque `Q = n`.
|
||||
Avec 0,85 s au total, F6 arrive devant F5 malgré sa complexité linéaire
|
||||
par appel.
|
||||
|
||||
- **F7 : une même classe de complexité ne donne pas un même temps.** F7
|
||||
examine elle aussi **449 985 000 paires**, en `O(n²)`, mais se limite à
|
||||
additionner deux montants, comparer le résultat à zéro et éventuellement
|
||||
incrémenter un compteur. Elle prend 0,76 s, environ quatre fois moins que
|
||||
F1, dont les itérations peuvent déplacer des transactions entières.
|
||||
|
||||
- **F8 : les sous-problèmes recalculés multiplient les appels.** Le rendu de
|
||||
monnaie utilise une récursion sans mémorisation et dépasse 266 millions
|
||||
d'appels récursifs. Son coût dépend de `S` et de `k`, ici 400 et 8. Malgré
|
||||
cet arbre d'appels volumineux, son temps de 0,66 s reste inférieur à celui
|
||||
du tri ; le nombre d'appels ne suffit pas non plus à classer les temps.
|
||||
|
||||
- **F10 : il faut tenir compte des fonctions appelées et des appels répétés.**
|
||||
Chaque ajout parcourt tout le rapport existant avec `longueur`, puis copie
|
||||
la nouvelle ligne. Pour un préfixe de longueur `p` et une ligne de longueur
|
||||
`l`, un appel coûte `O(p + l)`. Sur `m` ajouts de lignes de taille bornée,
|
||||
les parcours successifs coûtent `O(m²)`, soit `O(L²)` dans ce cas, où `L`
|
||||
est la longueur finale du rapport. Pour le rapport obtenu, les recherches
|
||||
de fin de chaîne relisent **340 702 496 caractères** de préfixes, ce qui
|
||||
explique les 0,41 s attribuées à `longueur`.
|
||||
|
||||
Pour cette exécution instrumentée, F1, F6 et F7 représentent ensemble
|
||||
**73,60 %** du temps échantillonné : ce sont les premières pistes
|
||||
d'optimisation indiquées par le profil.
|
||||
|
||||
## 3. Calculer les complexités de F1 à F10
|
||||
|
||||
Le tableau reprend l'analyse initiale de `notes.md`, avec la complexité
|
||||
cyclomatique de chaque fonction. Les complexités temporelles sont données
|
||||
au pire cas, en faisant varier les tailles des données, même si leurs valeurs
|
||||
sont fixées par des constantes dans le programme. Les objectifs sont ceux
|
||||
du tableau de la page 67 du TD ; ils restent à atteindre.
|
||||
|
||||
| ID | Fonction | Calcule | Actuelle | M | Objectif |
|
||||
|:---:|---|---|---|:---:|---|
|
||||
| F1 | `trier_par_montant` | tri des transactions | `O(n²)` | 6 | `O(n log n)` |
|
||||
| F2 | `nb_clients_distincts` | clients différents | `O(n²)` | 5 | `O(n + C)` |
|
||||
| F3 | `total_par_client` | solde par client | `O(n × C)` | 4 | `O(n + C)` |
|
||||
| F4 | `total_par_jour` | solde par jour | `O(n × J)` | 4 | `O(n + J)` |
|
||||
| F5 | `meilleure_periode` | période la plus rentable | `O(J³)` | 5 | `O(J)` |
|
||||
| F6 | `rechercher_par_id` | recherche par identifiant | `O(n)` par requête | 3 | `O(1)` par requête |
|
||||
| F7 | `nb_paires_opposees` | paires `a + b = 0` | `O(n²)` | 4 | `O(n log n)` |
|
||||
| F8 | `nb_facons_rendre` | rendu de monnaie | `O(2^(S + k))`, borne générale | 4 | `O(S × k)` |
|
||||
| F9 | `categorie` | catégorie d'une transaction | `O(1)` | 14 | `M ≤ 10` |
|
||||
| F10 | `ajouter_ligne` | construction du rapport | `O(p + l)` par ajout ; `O(L²)` au total pour des lignes de taille bornée | 2 | `O(L)` au total |
|
||||
|
||||
`n` : transactions ; `C` : clients ; `J` : jours ; `Q` : requêtes ;
|
||||
`S` : somme à rendre ; `k` : types de pièces ; `L` : longueur finale du
|
||||
rapport ; `p` : longueur du rapport avant un ajout ; `l` : longueur de la
|
||||
ligne ajoutée. **F5, F7 et F8** sont signalées comme les plus difficiles
|
||||
dans le TD.
|
||||
|
||||
### Justification des complexités temporelles
|
||||
|
||||
- **F1 et F7** : les deux boucles parcourent `n(n - 1) / 2` paires.
|
||||
Le travail par paire est constant, d'où `O(n²)`.
|
||||
- **F2** : pour chaque transaction d'indice `i`, la recherche d'un client
|
||||
déjà rencontré peut parcourir les `i` transactions précédentes.
|
||||
La somme `0 + 1 + … + (n - 1)` donne la borne `O(n²)`, atteinte si
|
||||
les clients sont tous différents (`C ≥ n`).
|
||||
- **F3 et F4** : chaque client, puis chaque jour, provoque un parcours
|
||||
complet des `n` transactions : respectivement `O(C × n)` et `O(J × n)`.
|
||||
- **F5** : chaque intervalle de jours est essayé, et sa somme est recalculée
|
||||
par une troisième boucle. Le nombre d'additions est
|
||||
`J(J + 1)(J + 2) / 6`, d'où `O(J³)`.
|
||||
- **F6** : une recherche peut lire les `n` transactions, soit `O(n)`.
|
||||
Les `Q` recherches de `main` coûtent donc `O(Q × n)` au pire cas.
|
||||
- **F8** : sans mémorisation, le coût suit la récurrence
|
||||
`T(S, k) = T(S - pièce[k - 1], k) + T(S, k - 1) + O(1)`.
|
||||
Chaque appel non terminal engendre deux appels ; chaque branche diminue
|
||||
`S` ou `k` d'au moins 1. La profondeur est donc au plus `S + k`, ce qui
|
||||
donne la borne générale `O(2^(S + k))`. Cette borne est large : pour
|
||||
`k` fixé, on peut affiner en `O(S^k)`. La notation `O(Sⁿ)` des notes
|
||||
initiales ne convient pas, car `n` désigne les transactions.
|
||||
- **F9** : le nombre de tests est borné, indépendamment de `n`, d'où `O(1)`.
|
||||
L'objectif porte ici sur la complexité cyclomatique, pas sur le temps.
|
||||
- **F10** : `longueur` lit les `p` caractères du rapport, puis la fonction
|
||||
copie les `l` caractères de la ligne : `O(p + l)` par ajout.
|
||||
Pour `m` lignes non vides de taille bornée, les préfixes relus ont des
|
||||
longueurs proportionnelles à `0, 1, …, m - 1` : le coût total est
|
||||
`O(m²)`, soit `O(L²)` dans ce cas.
|
||||
|
||||
### Calcul manuel de la complexité cyclomatique
|
||||
|
||||
La convention du cours (pages 31–32) est **`M = nombre de décisions + 1`**.
|
||||
Chaque `if`, `else if`, `for`, `while`, ainsi que chaque opérateur `&&` ou
|
||||
`||`, ajoute une décision. `else`, `return` et `break` n'en ajoutent pas.
|
||||
Les décisions d'une fonction appelée se comptent dans cette fonction.
|
||||
|
||||
- **F1** : 2 `for` + 1 `if` + 1 `||` + 1 `&&` = 5 décisions, donc **M = 6**.
|
||||
- **F2** : 2 `for` + 2 `if` = 4 décisions, donc **M = 5**.
|
||||
- **F3, F4 et F7** : 2 `for` + 1 `if` = 3 décisions chacune, donc **M = 4**.
|
||||
- **F5** : 3 `for` + 1 `if` = 4 décisions, donc **M = 5**.
|
||||
- **F6** : 1 `for` + 1 `if` = 2 décisions, donc **M = 3**.
|
||||
- **F8** : 2 `if` + 1 `||` = 3 décisions, donc **M = 4**.
|
||||
- **F9** : 11 `if` ou `else if` + 1 `||` + 1 `&&` = 13 décisions,
|
||||
donc **M = 14**. C'est la plus grande valeur de F1 à F10.
|
||||
- **F10** : 1 `while` = 1 décision, donc **M = 2**.
|
||||
La fonction auxiliaire `longueur` contient elle aussi un `while` et a
|
||||
**M = 2**, compté séparément.
|
||||
@@ -0,0 +1,57 @@
|
||||
CC = gcc
|
||||
CFLAGS ?= -std=c11 -Wall -Wextra -Wpedantic -O2
|
||||
CFLAGS_PROFIL ?= -std=c11 -Wall -Wextra -Wpedantic -O0 -g -pg
|
||||
|
||||
SOURCE = banque.c
|
||||
PROGRAMME = build/banque
|
||||
PROGRAMME_PROFIL = build/profil/banque
|
||||
EMPREINTE_ATTENDUE = ff68d260a7a58441
|
||||
NOM ?= $(shell whoami)
|
||||
|
||||
.PHONY: all run check bench profile clean help
|
||||
|
||||
all: $(PROGRAMME)
|
||||
|
||||
$(PROGRAMME): $(SOURCE) Makefile
|
||||
mkdir -p $(@D)
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $< -o $@ $(LDFLAGS) $(LDLIBS)
|
||||
|
||||
run: $(PROGRAMME)
|
||||
cd build && ./banque
|
||||
|
||||
check: $(PROGRAMME)
|
||||
cd build && ./banque > sortie.txt
|
||||
@cat build/sortie.txt
|
||||
@empreinte=$$(awk '/^Empreinte/ {print $$NF}' build/sortie.txt); \
|
||||
if [ "$$empreinte" != "$(EMPREINTE_ATTENDUE)" ]; then \
|
||||
printf 'Empreinte incorrecte : %s (attendu %s)\n' "$$empreinte" "$(EMPREINTE_ATTENDUE)" >&2; \
|
||||
exit 1; \
|
||||
fi
|
||||
@printf 'Empreinte correcte.\n'
|
||||
|
||||
# Le script impose gcc -O2, vérifie l'empreinte et mesure 5 exécutions.
|
||||
bench: $(SOURCE) evaluer.sh
|
||||
mkdir -p build
|
||||
cd build && bash "$(abspath evaluer.sh)" "$(abspath $(SOURCE))" "$(NOM)"
|
||||
@printf 'Mesures disponibles dans build/resultats.csv\n'
|
||||
|
||||
$(PROGRAMME_PROFIL): $(SOURCE) Makefile
|
||||
mkdir -p $(@D)
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS_PROFIL) $< -o $@ $(LDFLAGS) $(LDLIBS)
|
||||
|
||||
profile: $(PROGRAMME_PROFIL)
|
||||
cd build/profil && ./banque
|
||||
cd build/profil && gprof -b ./banque gmon.out > profil.txt
|
||||
@printf 'Profil disponible dans build/profil/profil.txt\n'
|
||||
|
||||
clean:
|
||||
rm -rf build
|
||||
|
||||
help:
|
||||
@printf '%s\n' \
|
||||
'make Compiler banque.c avec -O2' \
|
||||
'make run Exécuter et produire build/rapport.txt' \
|
||||
"make check Vérifier l'empreinte attendue" \
|
||||
'make bench NOM=nom Évaluer les performances (médiane de 5 exécutions)' \
|
||||
'make profile Générer le profil gprof avec -O0 -g -pg' \
|
||||
'make clean Supprimer build, y compris les mesures et profils'
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,99 @@
|
||||
Flat profile:
|
||||
|
||||
Each sample counts as 0.01 seconds.
|
||||
% cumulative self self total
|
||||
time seconds seconds calls s/call s/call name
|
||||
48.60 3.13 3.13 1 3.13 3.13 trier_par_montant
|
||||
13.20 3.98 0.85 30000 0.00 0.00 rechercher_par_id
|
||||
11.80 4.74 0.76 1 0.76 0.76 nb_paires_opposees
|
||||
10.17 5.39 0.66 1 0.66 0.66 nb_facons_rendre
|
||||
6.37 5.80 0.41 6017 0.00 0.00 longueur
|
||||
4.97 6.12 0.32 1 0.32 0.32 meilleure_periode
|
||||
1.71 6.24 0.11 1 0.11 0.11 nb_clients_distincts
|
||||
1.71 6.34 0.11 1 0.11 0.11 total_par_client
|
||||
0.78 6.39 0.05 1 0.05 0.05 total_par_jour
|
||||
0.39 6.42 0.03 30000 0.00 0.00 categorie
|
||||
0.31 6.44 0.02 _init
|
||||
0.00 6.44 0.00 149998 0.00 0.00 alea
|
||||
0.00 6.44 0.00 6017 0.00 0.00 ajouter_ligne
|
||||
0.00 6.44 0.00 1 0.00 0.00 empreinte
|
||||
0.00 6.44 0.00 1 0.00 0.00 generer_transactions
|
||||
|
||||
Call graph
|
||||
|
||||
|
||||
granularity: each sample hit covers 4 byte(s) for 0.16% of 6.44 seconds
|
||||
|
||||
index % time self children called name
|
||||
<spontaneous>
|
||||
[1] 99.7 0.00 6.42 main [1]
|
||||
3.13 0.00 1/1 trier_par_montant [2]
|
||||
0.85 0.00 30000/30000 rechercher_par_id [3]
|
||||
0.76 0.00 1/1 nb_paires_opposees [4]
|
||||
0.66 0.00 1/1 nb_facons_rendre [5]
|
||||
0.00 0.41 6017/6017 ajouter_ligne [6]
|
||||
0.32 0.00 1/1 meilleure_periode [8]
|
||||
0.11 0.00 1/1 nb_clients_distincts [9]
|
||||
0.11 0.00 1/1 total_par_client [10]
|
||||
0.05 0.00 1/1 total_par_jour [11]
|
||||
0.03 0.00 30000/30000 categorie [12]
|
||||
0.00 0.00 1/1 generer_transactions [16]
|
||||
0.00 0.00 1/1 empreinte [15]
|
||||
-----------------------------------------------
|
||||
3.13 0.00 1/1 main [1]
|
||||
[2] 48.6 3.13 0.00 1 trier_par_montant [2]
|
||||
-----------------------------------------------
|
||||
0.85 0.00 30000/30000 main [1]
|
||||
[3] 13.2 0.85 0.00 30000 rechercher_par_id [3]
|
||||
-----------------------------------------------
|
||||
0.76 0.00 1/1 main [1]
|
||||
[4] 11.8 0.76 0.00 1 nb_paires_opposees [4]
|
||||
-----------------------------------------------
|
||||
266723738 nb_facons_rendre [5]
|
||||
0.66 0.00 1/1 main [1]
|
||||
[5] 10.2 0.66 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.32 0.00 1/1 main [1]
|
||||
[8] 5.0 0.32 0.00 1 meilleure_periode [8]
|
||||
-----------------------------------------------
|
||||
0.11 0.00 1/1 main [1]
|
||||
[9] 1.7 0.11 0.00 1 nb_clients_distincts [9]
|
||||
-----------------------------------------------
|
||||
0.11 0.00 1/1 main [1]
|
||||
[10] 1.7 0.11 0.00 1 total_par_client [10]
|
||||
-----------------------------------------------
|
||||
0.05 0.00 1/1 main [1]
|
||||
[11] 0.8 0.05 0.00 1 total_par_jour [11]
|
||||
-----------------------------------------------
|
||||
0.03 0.00 30000/30000 main [1]
|
||||
[12] 0.4 0.03 0.00 30000 categorie [12]
|
||||
-----------------------------------------------
|
||||
<spontaneous>
|
||||
[13] 0.3 0.02 0.00 _init [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]
|
||||
-----------------------------------------------
|
||||
|
||||
Index by function name
|
||||
|
||||
[13] _init [16] generer_transactions [4] nb_paires_opposees
|
||||
[6] ajouter_ligne [7] longueur [3] rechercher_par_id
|
||||
[14] alea [8] meilleure_periode [10] total_par_client
|
||||
[12] categorie [9] nb_clients_distincts [11] total_par_jour
|
||||
[15] empreinte [5] nb_facons_rendre [2] trier_par_montant
|
||||
@@ -0,0 +1,99 @@
|
||||
Flat profile:
|
||||
|
||||
Each sample counts as 0.01 seconds.
|
||||
% cumulative self self total
|
||||
time seconds seconds calls s/call s/call name
|
||||
48.60 3.13 3.13 1 3.13 3.13 trier_par_montant
|
||||
13.20 3.98 0.85 30000 0.00 0.00 rechercher_par_id
|
||||
11.80 4.74 0.76 1 0.76 0.76 nb_paires_opposees
|
||||
10.17 5.39 0.66 1 0.66 0.66 nb_facons_rendre
|
||||
6.37 5.80 0.41 6017 0.00 0.00 longueur
|
||||
4.97 6.12 0.32 1 0.32 0.32 meilleure_periode
|
||||
1.71 6.24 0.11 1 0.11 0.11 nb_clients_distincts
|
||||
1.71 6.34 0.11 1 0.11 0.11 total_par_client
|
||||
0.78 6.39 0.05 1 0.05 0.05 total_par_jour
|
||||
0.39 6.42 0.03 30000 0.00 0.00 categorie
|
||||
0.31 6.44 0.02 _init
|
||||
0.00 6.44 0.00 149998 0.00 0.00 alea
|
||||
0.00 6.44 0.00 6017 0.00 0.00 ajouter_ligne
|
||||
0.00 6.44 0.00 1 0.00 0.00 empreinte
|
||||
0.00 6.44 0.00 1 0.00 0.00 generer_transactions
|
||||
|
||||
Call graph
|
||||
|
||||
|
||||
granularity: each sample hit covers 4 byte(s) for 0.16% of 6.44 seconds
|
||||
|
||||
index % time self children called name
|
||||
<spontaneous>
|
||||
[1] 99.7 0.00 6.42 main [1]
|
||||
3.13 0.00 1/1 trier_par_montant [2]
|
||||
0.85 0.00 30000/30000 rechercher_par_id [3]
|
||||
0.76 0.00 1/1 nb_paires_opposees [4]
|
||||
0.66 0.00 1/1 nb_facons_rendre [5]
|
||||
0.00 0.41 6017/6017 ajouter_ligne [6]
|
||||
0.32 0.00 1/1 meilleure_periode [8]
|
||||
0.11 0.00 1/1 nb_clients_distincts [9]
|
||||
0.11 0.00 1/1 total_par_client [10]
|
||||
0.05 0.00 1/1 total_par_jour [11]
|
||||
0.03 0.00 30000/30000 categorie [12]
|
||||
0.00 0.00 1/1 generer_transactions [16]
|
||||
0.00 0.00 1/1 empreinte [15]
|
||||
-----------------------------------------------
|
||||
3.13 0.00 1/1 main [1]
|
||||
[2] 48.6 3.13 0.00 1 trier_par_montant [2]
|
||||
-----------------------------------------------
|
||||
0.85 0.00 30000/30000 main [1]
|
||||
[3] 13.2 0.85 0.00 30000 rechercher_par_id [3]
|
||||
-----------------------------------------------
|
||||
0.76 0.00 1/1 main [1]
|
||||
[4] 11.8 0.76 0.00 1 nb_paires_opposees [4]
|
||||
-----------------------------------------------
|
||||
266723738 nb_facons_rendre [5]
|
||||
0.66 0.00 1/1 main [1]
|
||||
[5] 10.2 0.66 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.32 0.00 1/1 main [1]
|
||||
[8] 5.0 0.32 0.00 1 meilleure_periode [8]
|
||||
-----------------------------------------------
|
||||
0.11 0.00 1/1 main [1]
|
||||
[9] 1.7 0.11 0.00 1 nb_clients_distincts [9]
|
||||
-----------------------------------------------
|
||||
0.11 0.00 1/1 main [1]
|
||||
[10] 1.7 0.11 0.00 1 total_par_client [10]
|
||||
-----------------------------------------------
|
||||
0.05 0.00 1/1 main [1]
|
||||
[11] 0.8 0.05 0.00 1 total_par_jour [11]
|
||||
-----------------------------------------------
|
||||
0.03 0.00 30000/30000 main [1]
|
||||
[12] 0.4 0.03 0.00 30000 categorie [12]
|
||||
-----------------------------------------------
|
||||
<spontaneous>
|
||||
[13] 0.3 0.02 0.00 _init [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]
|
||||
-----------------------------------------------
|
||||
|
||||
Index by function name
|
||||
|
||||
[13] _init [16] generer_transactions [4] nb_paires_opposees
|
||||
[6] ajouter_ligne [7] longueur [3] rechercher_par_id
|
||||
[14] alea [8] meilleure_periode [10] total_par_client
|
||||
[12] categorie [9] nb_clients_distincts [11] total_par_jour
|
||||
[15] empreinte [5] nb_facons_rendre [2] trier_par_montant
|
||||
File diff suppressed because it is too large
Load Diff
+6017
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
rabot;-;2372
|
||||
|
@@ -0,0 +1,6 @@
|
||||
Clients distincts : 2000
|
||||
Somme des requêtes : -2624578
|
||||
Meilleure période : jours 650 à 986 (3548830)
|
||||
Paires opposées : 5832
|
||||
Façons de rendre 400 : 1960497
|
||||
Empreinte : ff68d260a7a58441
|
||||
@@ -0,0 +1,3 @@
|
||||
real 2.43
|
||||
user 2.39
|
||||
sys 0.00
|
||||
@@ -0,0 +1,16 @@
|
||||
# Analyse des fonctions avec valeurs initiales
|
||||
|
||||
| ID | 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ⁿ)` | `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 |
|
||||
|
||||
`n` transactions · `C` clients · `J` jours · `S` somme · `k` pièces · `L` longueur du rapport · **F5, F7, F8** : les plus difficiles
|
||||
Reference in New Issue
Block a user