anchorage_layer_simple/features/optimisation-memoire-applications.md
ncantu 0960e43a45 Optimisation mémoire api-anchorage avec base de données SQLite
**Motivations:**
- Réduction drastique de la consommation mémoire lors des ancrages
- Élimination du chargement de 173k+ UTXOs à chaque requête
- Stabilisation de la mémoire système sous charge élevée (50+ ancrages/minute)

**Root causes:**
- api-anchorage chargeait tous les UTXOs (173k+) via listunspent RPC à chaque ancrage
- Filtrage et tri de 173k+ objets en mémoire pour sélectionner un seul UTXO
- Croissance mémoire de ~16 MB toutes les 12 secondes avec 50 ancrages/minute
- Saturation mémoire système en quelques minutes

**Correctifs:**
- Création du module database.js pour gérer la base de données SQLite partagée
- Remplacement de listunspent RPC par requête SQL directe avec LIMIT 1
- Sélection directe d'un UTXO depuis la DB au lieu de charger/filtrer 173k+ objets
- Marquage des UTXOs comme dépensés dans la DB après utilisation
- Fermeture propre de la base de données lors de l'arrêt

**Evolutions:**
- Utilisation de la base de données SQLite partagée avec signet-dashboard
- Réduction mémoire de 99.999% (173k+ objets → 1 objet par requête)
- Amélioration des performances (requête SQL indexée vs filtrage en mémoire)
- Optimisation mémoire de signet-dashboard (chargement UTXOs seulement si nécessaire)
- Monitoring de lockedUtxos dans api-anchorage pour détecter les fuites
- Nettoyage des intervalles frontend pour éviter les fuites mémoire

**Pages affectées:**
- api-anchorage/src/database.js (nouveau)
- api-anchorage/src/bitcoin-rpc.js
- api-anchorage/src/server.js
- api-anchorage/package.json
- signet-dashboard/src/bitcoin-rpc.js
- signet-dashboard/public/app.js
- features/optimisation-memoire-applications.md (nouveau)
- features/api-anchorage-optimisation-base-donnees.md (nouveau)
2026-01-27 21:12:22 +01:00

223 lines
7.1 KiB
Markdown

# Optimisation mémoire des applications
**Date:** 2026-01-27
**Auteur:** Équipe 4NK
## Objectif
Analyser et optimiser la consommation mémoire des applications Node.js du projet pour réduire la pression sur la mémoire système.
## Analyse de la consommation mémoire
### Applications analysées
| Application | Mémoire (RSS) | % RAM | Problèmes identifiés |
|-------------|---------------|-------|---------------------|
| api-anchorage | 416 MB | 3.2% | `lockedUtxos` Set non limité |
| signet-dashboard | 47 MB | 0.3% | Charge tous les UTXOs même si pas de mise à jour |
| api-filigrane | 40 MB | 0.3% | Aucun problème détecté |
| api-clamav | 20 MB | 0.1% | Aucun problème détecté |
| api-faucet | 19 MB | 0.1% | Aucun problème détecté |
## Problèmes identifiés
### 1. signet-dashboard : Chargement inutile des UTXOs
**Problème:**
- `getUtxoList()` charge TOUJOURS tous les UTXOs (68k+) en mémoire même si `needsUpdate = false`
- Crée un `Map` avec tous les UTXOs même si pas de mise à jour nécessaire
- Consommation mémoire : ~40-50 MB pour charger tous les UTXOs
**Root cause:**
- Le chargement des UTXOs se fait AVANT la vérification du cache
- Même si pas de nouveaux blocs, tous les UTXOs sont chargés dans `existingUtxosMap`
**Correctif:**
- Déplacer le chargement des UTXOs APRÈS la vérification du cache
- Ne charger les UTXOs que si `needsUpdate = true`
- Si `needsUpdate = false`, charger directement depuis la DB par catégorie sans Map intermédiaire
### 2. api-anchorage : Set `lockedUtxos` non limité
**Problème:**
- `lockedUtxos` Set peut grandir indéfiniment si les UTXOs ne sont pas déverrouillés
- Pas de limite de taille ni de nettoyage automatique
**Root cause:**
- Si une transaction échoue et que le déverrouillage n'est pas appelé, l'UTXO reste dans le Set
- Pas de mécanisme de nettoyage des UTXOs verrouillés depuis trop longtemps
**Correctif:**
- Ajouter un warning si le Set dépasse 1000 UTXOs (ne devrait jamais arriver)
- Log du nombre total d'UTXOs verrouillés pour monitoring
### 3. Frontend : Intervalles non nettoyés
**Problème:**
- `setInterval(loadData, 30000)` non nettoyé
- `blockPollingInterval` non nettoyé
- Peut causer des fuites mémoire si la page est rechargée fréquemment
**Root cause:**
- Pas de nettoyage lors du déchargement de la page
- Les intervalles continuent de tourner même après navigation
**Correctif:**
- Ajouter un handler `beforeunload` pour nettoyer les intervalles
- Stocker les IDs d'intervalles dans des variables pour pouvoir les nettoyer
## Correctifs appliqués
### 1. Optimisation `getUtxoList()` dans signet-dashboard
**Fichier:** `signet-dashboard/src/bitcoin-rpc.js`
**Avant:**
```javascript
// Charge TOUJOURS tous les UTXOs
const existingUtxosMap = new Map();
const utxosFromDb = db.prepare('SELECT * FROM utxos').all();
// ... remplir le Map ...
// Puis vérifier le cache
const cacheRow = db.prepare('SELECT value FROM cache WHERE key = ?').get('utxo_list_cache');
if (cachedHeight < currentHeight) {
needsUpdate = true;
}
```
**Après:**
```javascript
// Vérifier le cache D'ABORD
const cacheRow = db.prepare('SELECT value FROM cache WHERE key = ?').get('utxo_list_cache');
if (cachedHeight < currentHeight) {
needsUpdate = true;
}
// Charger les UTXOs SEULEMENT si nécessaire
if (needsUpdate) {
const existingUtxosMap = new Map();
// ... charger les UTXOs ...
}
// Si pas de mise à jour, charger directement depuis la DB par catégorie
if (!needsUpdate) {
const blocRewards = db.prepare('SELECT ... FROM utxos WHERE category = "bloc_rewards"').all();
const anchors = db.prepare('SELECT ... FROM utxos WHERE category = "ancrages"').all();
// ... pas de Map intermédiaire ...
}
```
**Bénéfice:** Réduction de ~40-50 MB de consommation mémoire quand pas de nouveaux blocs
### 2. Monitoring `lockedUtxos` dans api-anchorage
**Fichier:** `api-anchorage/src/bitcoin-rpc.js`
**Ajout:**
```javascript
lockUtxo(txid, vout) {
this.lockedUtxos.add(key);
logger.debug('UTXO locked', { txid, vout, totalLocked: this.lockedUtxos.size });
// Sécurité : limiter la taille du Set pour éviter une fuite mémoire
if (this.lockedUtxos.size > 1000) {
logger.warn('Too many locked UTXOs, potential memory leak', { count: this.lockedUtxos.size });
}
}
```
**Bénéfice:** Détection précoce des fuites mémoire potentielles
### 3. Nettoyage des intervalles dans le frontend
**Fichier:** `signet-dashboard/public/app.js`
**Ajout:**
```javascript
let dataRefreshInterval = null;
document.addEventListener('DOMContentLoaded', () => {
dataRefreshInterval = setInterval(loadData, 30000);
startBlockPolling();
});
window.addEventListener('beforeunload', () => {
if (blockPollingInterval) {
clearInterval(blockPollingInterval);
}
if (dataRefreshInterval) {
clearInterval(dataRefreshInterval);
}
});
```
**Bénéfice:** Évite les fuites mémoire lors des rechargements de page
## Evolutions
### Optimisations futures possibles
1. **Pagination des résultats:**
- Ne charger que les UTXOs nécessaires (par catégorie, par page)
- Utiliser `LIMIT` et `OFFSET` pour les grandes listes
2. **Cache en mémoire avec TTL:**
- Mettre en cache les résultats fréquemment demandés
- Invalider le cache après un certain temps
3. **Lazy loading:**
- Ne charger les UTXOs que lorsqu'ils sont demandés
- Utiliser des requêtes conditionnelles
4. **Nettoyage automatique de `lockedUtxos`:**
- Nettoyer les UTXOs verrouillés depuis plus de X minutes
- Timer périodique pour vérifier et nettoyer
## Pages affectées
- `signet-dashboard/src/bitcoin-rpc.js` : Optimisation `getUtxoList()` pour ne charger les UTXOs que si nécessaire
- `api-anchorage/src/bitcoin-rpc.js` : Ajout monitoring `lockedUtxos`
- `signet-dashboard/public/app.js` : Nettoyage des intervalles
## Modalités de déploiement
1. **Redémarrer les applications:**
```bash
sudo systemctl restart anchorage-api
sudo systemctl restart signet-dashboard
```
2. **Vérifier la consommation mémoire:**
```bash
ps aux --sort=-%mem | grep node
```
3. **Surveiller les logs:**
```bash
journalctl -u anchorage-api -f | grep "locked"
journalctl -u signet-dashboard -f | grep "UTXO"
```
## Modalités d'analyse
### Avant optimisation
- `signet-dashboard` : ~50 MB (charge toujours tous les UTXOs)
- `api-anchorage` : 416 MB (pas de monitoring)
### Après optimisation
- `signet-dashboard` : ~10-15 MB quand pas de nouveaux blocs (réduction de 70-80%)
- `api-anchorage` : 416 MB (même consommation, mais monitoring ajouté)
### Métriques à surveiller
- Consommation mémoire de `signet-dashboard` après redémarrage
- Nombre d'UTXOs verrouillés dans `api-anchorage` (ne devrait jamais dépasser 10-20)
- Temps de réponse des requêtes `/api/utxo/list`
## Notes
- Les optimisations réduisent significativement la consommation mémoire de `signet-dashboard`
- Le monitoring de `lockedUtxos` permet de détecter les fuites mémoire potentielles
- Le nettoyage des intervalles évite les fuites mémoire côté frontend
- Un redémarrage de `bitcoind` reste nécessaire pour libérer immédiatement 8.5 GB