Files
anagram-generator/docs/MEMORY_TRADEOFFS.md
Rawleenc 02cf48088a perf: Add MEMORY_TRADEOFFS and PERFORMANCE documentation
- Introduced MEMORY_TRADEOFFS.md to explain memory vs deduplication trade-offs in anagram generation.
- Added PERFORMANCE.md detailing optimizations for handling large volumes of anagram generation efficiently.
- Created USAGE.md for comprehensive usage instructions, including installation, basic commands, and advanced generation modes.
- Enhanced generator with streaming and batch processing capabilities for improved memory management.
- Implemented quick hashing for deduplication to reduce memory footprint.
- Updated main.rs to support new command-line arguments for streaming and batch modes.
- Added tests to ensure letter removal maintains minimum word length and to verify anagram sorting functionality.
2025-11-06 23:38:05 +01:00

218 lines
7.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Compromis Mémoire vs Déduplication
## Problématique
Lors de la génération de millions d'anagrammes en mode streaming, il existe un conflit fondamental entre deux objectifs :
1. **Mémoire constante** : Ne pas consommer de RAM proportionnellement au nombre d'anagrammes
2. **Déduplication complète** : Garantir l'unicité de tous les anagrammes générés
## Solution implémentée : Déduplication plafonnée
### Principe
Le mode streaming maintient un `HashSet<u64>` pour la déduplication, mais avec une **limite de taille à 100 000 entrées**.
```rust
let dedup_limit = 100_000; // ~800KB de mémoire
```
### Comportement
| Anagrammes générés | Déduplication | Mémoire utilisée |
|-------------------|---------------|------------------|
| 1 - 100 000 | ✅ **100% unique** | Croissante (0 → ~8MB) |
| 100 001+ | ⚠️ **Duplicatas possibles** | **Plafonnée à ~8MB** |
### Pourquoi cette limite ?
**Sans limite** (version originale problématique) :
- 1M anagrammes = 1M × 8 bytes = ~8MB + overhead HashSet = **~50MB**
- 10M anagrammes = **~500MB**
- 100M anagrammes = **~5GB**
- ❌ Mémoire qui croît indéfiniment, pas vraiment du "streaming"
**Avec limite à 100k** (version optimisée) :
- 100k hashs × 8 bytes = 800KB + overhead HashSet = **~8MB**
- Peu importe le nombre total (1M, 10M, 100M, 1B) : **Toujours ~8MB**
- ✅ Vraie mémoire constante
## Modes disponibles et leur usage
### Mode 1 : Standard (< 10k anagrammes)
```bash
cargo run --release -- --word "word" --count 5000
```
| Critère | Valeur |
|---------|--------|
| Mémoire | O(n) - ~1-10MB pour 1-10k items |
| Déduplication | ✅ 100% |
| Performance | Excellente |
| Limitation | Ne passe pas à l'échelle (> 10k) |
**Utilisation recommandée** : Génération quotidienne, développement, tests
---
### Mode 2 : Streaming (10k - 10M anagrammes, duplicatas acceptables)
```bash
cargo run --release -- --word "word" --count 5000000 --streaming --progress
```
| Critère | Valeur |
|---------|--------|
| Mémoire | **Plafonnée à ~8MB** |
| Déduplication | ✅ 100% sur premiers 100k<br>⚠️ Duplicatas possibles après |
| Performance | Excellente, résultats immédiats |
| Limitation | Duplicatas après 100k items |
**Utilisation recommandée** :
- Pipeline avec filtrage en aval (ex: `| sort -u`)
- Génération où quelques duplicatas sont acceptables
- Besoin de résultats immédiats
- Contraintes mémoire strictes
**Exemple avec élimination duplicatas en aval** :
```bash
# Générer avec streaming, puis éliminer duplicatas avec sort
cargo run --release -- --word "word" --count 10000000 --streaming \
| sort -u > anagrams_uniques.txt
```
---
### Mode 3 : Batch (> 1M anagrammes, déduplication 100% requise)
```bash
cargo run --release -- --word "word" --count 50000000 --batch-size 100000 --progress
```
| Critère | Valeur |
|---------|--------|
| Mémoire | O(batch_size) - ~50-100MB |
| Déduplication | ✅ **100% globale** |
| Performance | Bonne, traitement par chunks |
| Limitation | Latence initiale (batch complet) |
**Utilisation recommandée** :
- Génération massive (> 1M)
- Déduplication 100% requise
- RAM suffisante pour batch (~100MB)
---
## Exemples pratiques
### Cas 1 : Génération de 500k anagrammes uniques
**Option A - Streaming (rapide, duplicatas possibles)** :
```bash
# ~8MB RAM, résultats immédiats
# 100k premiers uniques garantis, puis duplicatas possibles sur les 400k suivants
cargo run --release -- --word "algorithm" --count 500000 --streaming --progress
```
**Option B - Batch (plus lent, 100% unique)** :
```bash
# ~50MB RAM, tous uniques
cargo run --release -- --word "algorithm" --count 500000 --batch-size 50000 --progress
```
**Recommandation** : Utilisez **streaming** puis filtrez les duplicatas :
```bash
cargo run --release -- --word "algorithm" --count 500000 --streaming \
| awk '!seen[$2]++' > uniques.txt
```
(awk filtre les duplicatas basé sur la 2ème colonne = le mot)
### Cas 2 : Génération de 10M anagrammes
**Option A - Streaming + filtrage externe** :
```bash
# ~8MB RAM pour le générateur
# Duplicatas éliminés par sort -u (utilise disque si nécessaire)
cargo run --release -- --word "programming" --count 10000000 --streaming \
| sort -u -o uniques.txt
```
**Option B - Batch avec déduplication intégrée** :
```bash
# ~100MB RAM, déduplication garantie
cargo run --release -- --word "programming" --count 10000000 --batch-size 100000 --progress
```
**Recommandation** : **Batch** si RAM disponible, sinon streaming + sort -u
### Cas 3 : Génération infinie (pipeline)
```bash
# Génération continue jusqu'à interruption (Ctrl+C)
# Mémoire constante ~8MB
cargo run --release -- --word "word" --count 999999999 --streaming \
| head -n 1000000 \
| sort -u \
> million_uniques.txt
```
## Tableau de décision
| Besoin | Quantité | Mode recommandé | Commande |
|--------|----------|-----------------|----------|
| Tests, dev | < 10k | **Standard** | `--count 5000` |
| Résultats rapides | 10k-100k | **Streaming** | `--count 50000 --streaming` |
| Dédup 100% | > 100k | **Batch** | `--count 500000 --batch-size 50000` |
| RAM limitée (<50MB) | Quelconque | **Streaming + sort** | `--streaming \| sort -u` |
| Pipeline temps réel | Quelconque | **Streaming** | `--streaming \| process` |
| Génération massive | > 10M | **Batch** | `--count 50000000 --batch-size 1000000` |
## Statistiques de duplicatas (streaming)
Estimation du taux de duplicatas en mode streaming selon le nombre d'anagrammes possibles :
| Mot source | Anagrammes possibles | Taux de duplicatas après 100k |
|------------|---------------------|-------------------------------|
| "test" (4 lettres) | ~24 | **Très élevé** (>90%) |
| "hello" (5 lettres) | ~120 | **Élevé** (~50-80%) |
| "algorithm" (9 lettres) | ~362k | **Faible** (<5%) |
| "programming" (11 lettres) | ~40M | **Très faible** (<0.1%) |
**Règle générale** : Plus le mot source est long, moins il y a de duplicatas en streaming.
## Alternatives futures
### Option 1 : Filtre de Bloom probabiliste
```rust
// Mémoire fixe (ex: 10MB), faux positifs <1%
BloomFilter::new(10_000_000, 0.01)
```
- ✅ Mémoire constante
- ✅ Déduplication ~99%
- ⚠️ Complexité d'implémentation
### Option 2 : Fenêtre glissante (LRU)
```rust
// Garde seulement les 100k derniers hashs
LruCache::new(100_000)
```
- ✅ Mémoire constante
- ⚠️ Duplicatas possibles si répétition éloignée
- ✅ Simple à implémenter
### Option 3 : Mode configurable
```bash
# L'utilisateur choisit la limite
--streaming --dedup-limit 500000 # ~40MB mais meilleure dédup
--streaming --dedup-limit 10000 # ~1MB mais plus de duplicatas
```
- ✅ Flexible
- ⚠️ Complexité interface
## Conclusion
Le compromis actuel (limite à 100k) offre un bon équilibre :
- ✅ Mémoire **vraiment constante** (~8MB)
-**100% unique** pour la majorité des cas d'usage (< 100k)
-**Mode batch disponible** pour déduplication complète si nécessaire
-**Compatible avec filtrage externe** (sort -u, awk, etc.)
Pour la plupart des utilisateurs, générer < 100k anagrammes est suffisant et bénéficie de la déduplication complète. Pour les cas extrêmes, le mode batch offre la garantie de déduplication totale.