Files
j.foucher 68cea1eb4d V2 : optimisation API (cache, index, vue materialisee)
- BDD (migrations 1.6.0 + 1.7.0, idempotentes) :
  * 4 nouveaux index composites sur reactevents, triggerevents, sessions
  * vue sessiondebriefs reecrite (sous-requetes correlees -> JOINs)
    puis materialisee dans table session_debriefs_cache via procedure
    stockee rebuild_debrief_cache, recalculee uniquement aux changements
  * fix bug double JOIN participates : TargetRole = "IA" pour les hits
    NPC/objets (au lieu d'un role aleatoire de participant)
- API PHP :
  * connexion PDO en singleton + ATTR_PERSISTENT
  * cache disque par session (cache/sess_<id>/) pour debrief, get, userhistory
    avec invalidation ciblee sur events et lifecycle
  * pagination opt-in (limit/offset) sur lists/sessions_for_user
  * helpers ensure_/rebuild_/invalidate_session_debrief_cache_db
  * debug/benchmark.php pour mesurer la latence des 6 endpoints cles
- Endpoints HTTP : signatures inchangees, compat Unreal preservee
- Gain mesure : -58% a -83% sur les 5 endpoints cles

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 16:41:52 +02:00

107 lines
4.1 KiB
PHP

<?php
// Mesure de latence des endpoints lourds de l'API ProserveAPI.
// A lancer AVANT et APRES chaque palier d'optimisation pour avoir des chiffres comparatifs.
// Usage : POST sur ce fichier avec optionnellement userId et sessionId.
// curl -X POST -d "userId=1&sessionId=42" http://localhost/proserve/debug/benchmark.php
// ou ouvrir directement dans le navigateur (lance avec userId=-1 et sessionId=-1, certains endpoints retourneront vide mais la mesure du round-trip reste valide).
include_once '../config/init.php';
$userId = isset($_POST['userId']) ? intval($_POST['userId']) : (isset($_GET['userId']) ? intval($_GET['userId']) : -1);
$sessionId = isset($_POST['sessionId']) ? intval($_POST['sessionId']) : (isset($_GET['sessionId']) ? intval($_GET['sessionId']) : -1);
$iterations = isset($_POST['iterations']) ? max(1, intval($_POST['iterations'])) : (isset($_GET['iterations']) ? max(1, intval($_GET['iterations'])) : 5);
// si pas de sessionId fourni, prendre la plus recente pour avoir des donnees realistes
if ($sessionId <= 0) {
$stmt = $db->query("SELECT id FROM sessions ORDER BY id DESC LIMIT 1");
$row = $stmt ? $stmt->fetch(PDO::FETCH_ASSOC) : null;
if ($row) $sessionId = intval($row['id']);
}
if ($userId <= 0) {
$stmt = $db->query("SELECT userId FROM participates WHERE sessionId=" . intval($sessionId) . " LIMIT 1");
$row = $stmt ? $stmt->fetch(PDO::FETCH_ASSOC) : null;
if ($row) $userId = intval($row['userId']);
}
// resolution de l'URL de base (meme host et meme path)
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
$base = $scheme . '://' . $host . rtrim(dirname(dirname($_SERVER['SCRIPT_NAME'])), '/\\');
$endpoints = [
'session/debrief' => ['sessionId' => $sessionId, 'userId' => $userId],
'session/get' => ['sessionId' => $sessionId],
'stats/userhistory' => ['userId' => $userId, 'sessionId' => $sessionId, 'quickMode' => 'false'],
'stats/get' => ['userId' => $userId, 'sessionId' => $sessionId],
'lists/sessions_for_user' => ['userId' => $userId],
'lists/users_in_session' => ['sessionId' => $sessionId],
];
function call_endpoint($url, $params)
{
// ext-curl est dispo dans XAMPP par defaut et bcp plus rapide que
// file_get_contents+stream_context_create sur Windows (qui ajoute ~10ms par appel).
static $ch = null;
if ($ch === null) {
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_FORBID_REUSE => false,
CURLOPT_FRESH_CONNECT => false,
]);
}
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
$start = microtime(true);
$resp = curl_exec($ch);
$elapsed_ms = (microtime(true) - $start) * 1000;
$err = curl_errno($ch);
return [
'ms' => round($elapsed_ms, 2),
'bytes' => $resp === false ? 0 : strlen($resp),
'ok' => $err === 0 && $resp !== false,
];
}
function summarize($samples)
{
$times = array_column($samples, 'ms');
sort($times);
$n = count($times);
return [
'min' => $times[0],
'max' => $times[$n - 1],
'median' => $times[intval($n / 2)],
'avg' => round(array_sum($times) / $n, 2),
'bytes' => $samples[0]['bytes'],
'ok' => count(array_filter(array_column($samples, 'ok'))) === $n,
];
}
$results = [
'context' => [
'userId' => $userId,
'sessionId' => $sessionId,
'iterations' => $iterations,
'base_url' => $base,
'timestamp' => date('c'),
],
'endpoints' => [],
];
foreach ($endpoints as $path => $params) {
$url = $base . '/' . $path . '.php';
$samples = [];
for ($i = 0; $i < $iterations; $i++) {
$samples[] = call_endpoint($url, $params);
}
$results['endpoints'][$path] = summarize($samples);
}
print_r(json_encode($results, JSON_PRETTY_PRINT));
?>