Bonjour,
Afin d'occuper mon temps libre le week-end, je suis en train de développer un petit jeu en PHP sans la moindre prétention ni le moindre intérêt ni même l'objectif de le mettre en ligne.
En somme, je le fais dans le but principal de me remettre un peu au développement PHP que j'ai plus ou moins abandonné depuis quelques années.
Or, après quelques scripts pour le jeu, je me pose une question qui m'empêche d'avancer. À savoir, dans le cadre du dit jeu qui se veut être au tour par tour à raison d'un tour par heure, vaut-il mieux que les données du compte du membre soient récupérées lors de sa connexion et stocker en session ou bien récupérer au compte goutte dans la base de données lorsqu'il y en a besoin ?
J'étais parti du principe que la récupération d'une session est forcément plus rapide qu'une récupération de données dans une base de données puisqu'il s'agit de lire un fichier et d'en désérialiser le contenu alors que la base de données demande d'interpréter une requête, d'accéder à un fichier, de récupérer ce que l'on souhaite et de formater le tout pour le renvoyer au script qui, à son tour, va encore retraiter les dites données pour les stocker dans des objets (dans mon cas).
Or, j'ai mis en place un petit test consistant à enregistrer 20 lignes en base de données et à comparer le temps d'exécution nécessaire au session_start() et à à la récupération via une requête SQL et le résultat s'avère être à l'extrême opposé de mes attentes. La plupart des résultats donnent quelque chose comme ça :
Autant dire que la différence est énorme.Durée de récupération de la session : 5.3167343139648E-5
Durée de récupération dans la BDD : 0.00022292137145996
À telle point que je suppose que l'erreur vient de moi ou de mon "protocole de test" qui serait trop bancale.
Afin que vous puissiez voir exactement ce que je teste, voici mes scripts qui vous permettront, juste en changeant les identifiants pour la BDD dans les scripts "index" et "test", de tester également (ne faites pas attention aux commentaires en anglais qui doivent être insultant pour ceux doués dans cette langue, je m'entraîne comme je peux ) :
Code Index : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 <?php error_reporting(E_ALL); ini_set("display_errors", 1); /** * We want to know what is the more efficient -faster- way between use SESSION to store all data of a member * Or request the database on every single page * To do this, we use two scripts : * - This one : * -> Create database and data in it * -> Create session and store database data in it * - The second one : * -> Load data from database * -> Load data from the session */ require_once("Data.php"); // Create database, table and twenty lines of data $user = 'SuperAdmin'; $password = 'SuperAdmin'; try { $_SQL = new PDO("mysql:host=localhost", $user, $password); } catch(PDOException $e) { echo 'Erreur PDO : ' . $e->getMessage(); exit; } $create_database = 'CREATE DATABASE IF NOT EXISTS `session_vs_database` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci'; $select_database = 'USE session_vs_database'; $create_data_table = ' CREATE TABLE IF NOT EXISTS `data` ( `int_4` int(4) UNSIGNED NOT NULL, `string_20` varchar(20) NOT NULL, `string_60` varchar(60) NOT NULL, `string_80` varchar(60) NOT NULL, PRIMARY KEY (`int_4`), UNIQUE INDEX `int_4_UNIQUE` (`int_4` ASC) ) ENGINE=InnoDB DEFAULT CHARSET=utf8'; try { $_SQL->query($create_database) or die(print_r($_SQL->errorInfo(), true)); $_SQL->query($select_database) or die(print_r($_SQL->errorInfo(), true)); $_SQL->query($create_data_table) or die(print_r($_SQL->errorInfo(), true)); } catch(PDoException $e) { echo 'Erreur PDO : ' . $e->getMessage(); exit; } if(!Data::thereIsEnoughLines($_SQL)) Data::putTwentyLinesInDatabase($_SQL); // Get data in database $data = Data::getTwentyLinesOfData($_SQL); // Store it in $_SESSION session_start(); $_SESSION['data'] = $data; echo '<a href="session_vs_database_test.php">Exécuter le test</a>'; ?>
Code Test : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 <?php error_reporting(E_ALL); ini_set("display_errors", 1); /** * We want to know what is the more efficient -faster- way between use SESSION to store all data of a member * Or request the database on every single page * To do this, we use two scripts : * - This one : * -> Load data from session * -> Load data from database * - The other one : * -> Create database and data in it * -> Create session and store database data in it */ require_once("Data.php"); // We need the connexion in all cases i think $user = 'SuperAdmin'; $password = 'SuperAdmin'; $database = 'session_vs_database'; try { $_SQL = new PDO("mysql:dbname=" . $database . ";host=localhost", $user, $password); } catch(PDOException $e) { echo 'Erreur PDO : ' . $e->getMessage(); exit; } $start_time = microtime(true); session_start(); // No more to do I suppose $time_after_session = microtime(true); $data = Data::getTwentyLinesOfData($_SQL); $final_after_sql = microtime(true); echo 'Durée de récupération de la session : ' . ($time_after_session - $start_time) . '<br />'; echo 'Durée de récupération dans la BDD : ' . ($final_after_sql - $time_after_session) . '<br />'; ?>
Code Class Data : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 <?php class Data { public $int_4; // Like an id public $string_20; // Kind of username public $string_60; // Like password hash public $string_80; // Maybe an email address public function __construct($int_4, $string_20, $string_60, $string_80) { $this->int_4 = $int_4; $this->string_20 = $string_20; $this->string_60 = $string_60; $this->string_80 = $string_80; } public static function getTwentyLinesOfData(&$_SQL) { $req = 'SELECT * FROM data LIMIT 0, 20'; $results = $_SQL->query($req); $data = array(); foreach($results as $line) $data[] = new Data($line['int_4'], $line['string_20'], $line['string_60'], $line['string_80']); return $data; } public static function thereIsEnoughLines(&$_SQL) { $req = 'SELECT COUNT(int_4) FROM data'; $result = $_SQL->query($req)->fetch(); if($result['COUNT(int_4)'] >= 20) return true; return false; } public static function putTwentyLinesInDatabase(&$_SQL) { $req = 'INSERT INTO data (int_4, string_20, string_60, string_80) VALUES '; for($i = 0; $i < 20; $i++) { $string_20 = substr(hash('sha512', rand()), 0, 20); $string_60 = substr(hash('sha512', rand()), 0, 60); $string_80 = substr(hash('sha512', rand()), 0, 80); if($i < 19) $req .= '(' . $i . ', "' . $string_20 . '", "' . $string_60 . '", "' . $string_80 . '"), '; else $req = $req .= '(' . $i . ', "' . $string_20 . '", "' . $string_60 . '", "' . $string_80 . '")'; } try { $_SQL->query($req); } catch(PDoException $e) { echo 'Erreur PDO : ' . $e->getMessage(); } } } ?>
Je sais également qu'il est possible de stocker les sessions dans la mémoire vive, ce qui accélérerait sans nul doute le processus de récupération des données, mais la mise en place de memcache me semble bien obscure pour le moment (j'espérais que c'était intégré à PHP mais a priori c'est un serveur à part).
En tous les cas, cette différence de durée d'exécution me semble bien étrange et si vous pouviez m'éclairer sur le pourquoi de celle-ci ou sur les erreurs dans mon raisonnement je vous en serais reconnaissant
Alfanor.
Partager