database.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. <?php
  2. declare(strict_types=1);
  3. use Swoole\Database\PDOConfig;
  4. use Swoole\Database\PDOPool;
  5. use Swoole\Database\PDOProxy;
  6. use Swoole\Database\PDOStatementProxy;
  7. class Operation
  8. {
  9. public const WORLD_SELECT_SQL = 'SELECT id,randomNumber FROM World WHERE id = ?';
  10. public const FORTUNE_SQL = 'SELECT id, message FROM Fortune';
  11. public const WORLD_UPDATE_SQL = 'UPDATE World SET randomNumber = ? WHERE id = ?';
  12. public static function db(PDOStatement|PDOStatementProxy $db): string
  13. {
  14. $db->execute([mt_rand(1, 10000)]);
  15. return json_encode($db->fetch(PDO::FETCH_ASSOC));
  16. }
  17. public static function fortunes(PDOStatement|PDOStatementProxy $fortune): string
  18. {
  19. $fortune->execute();
  20. $results = $fortune->fetchAll(PDO::FETCH_KEY_PAIR);
  21. $results[0] = 'Additional fortune added at request time.';
  22. asort($results);
  23. $html = '';
  24. foreach ($results as $id => $message) {
  25. $message = htmlspecialchars($message, ENT_QUOTES, 'UTF-8');
  26. $html .= "<tr><td>$id</td><td>$message</td></tr>";
  27. }
  28. return "<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>$html</table></body></html>";
  29. }
  30. public static function query(PDOStatement|PDOStatementProxy $query, int $queries): string
  31. {
  32. $results = [];
  33. while ($queries--) {
  34. $query->execute([mt_rand(1, 10000)]);
  35. $results[] = $query->fetch(PDO::FETCH_ASSOC);
  36. }
  37. return json_encode($results);
  38. }
  39. public static function updates(PDOStatement|PDOStatementProxy $random, PDOStatement|PDOStatementProxy $update, int $queries, string $driver): string
  40. {
  41. $results = $keys = $values = [];
  42. while ($queries--) {
  43. $random->execute([mt_rand(1, 10000)]);
  44. $item = $random->fetch(PDO::FETCH_ASSOC);
  45. $item['randomNumber'] = mt_rand(1, 10000);
  46. $results[] = $item;
  47. if ($driver == 'pgsql') {
  48. $values[] = $keys[] = $item['id'];
  49. $values[] = $item['randomNumber'];
  50. } else {
  51. $update->execute([$item['randomNumber'], $item['id']]);
  52. }
  53. }
  54. if ($driver == 'pgsql') {
  55. $update->execute([...$values, ...$keys]);
  56. }
  57. return json_encode($results);
  58. }
  59. }
  60. class Connection
  61. {
  62. private static PDO $pdo;
  63. private static string $driver;
  64. private static array $updates = [];
  65. private static PDOStatement $db;
  66. private static PDOStatement $fortune;
  67. private static PDOStatement $random;
  68. private static PDOStatement $query;
  69. public static function init(string $driver): void
  70. {
  71. $pdo = new PDO(
  72. "$driver:host=tfb-database;dbname=hello_world",
  73. "benchmarkdbuser",
  74. "benchmarkdbpass",
  75. [
  76. PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
  77. PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
  78. PDO::ATTR_EMULATE_PREPARES => false
  79. ]
  80. );
  81. self::$db = self::$random = self::$query = $pdo->prepare(Operation::WORLD_SELECT_SQL);
  82. self::$fortune = $pdo->prepare(Operation::FORTUNE_SQL);
  83. self::$pdo = $pdo;
  84. self::$driver = $driver;
  85. }
  86. public static function db(): string
  87. {
  88. return Operation::db(self::$db);
  89. }
  90. public static function fortunes(): string
  91. {
  92. return Operation::fortunes(self::$fortune);
  93. }
  94. public static function query(int $queries): string
  95. {
  96. return Operation::query(self::$query, $queries);
  97. }
  98. public static function updates(int $queries): string
  99. {
  100. if (!isset(self::$updates[$queries])) {
  101. self::$updates[$queries] = self::$driver == 'pgsql'
  102. ? self::$pdo->prepare('UPDATE World SET randomNumber = CASE id'.\str_repeat(' WHEN ?::INTEGER THEN ?::INTEGER ', $queries).'END WHERE id IN ('.\str_repeat('?::INTEGER,', $queries - 1).'?::INTEGER)')
  103. : self::$pdo->prepare(Operation::WORLD_UPDATE_SQL);
  104. }
  105. return Operation::updates(self::$random, self::$updates[$queries], $queries, self::$driver);
  106. }
  107. }
  108. class Connections
  109. {
  110. private static PDOPool $pool;
  111. private static string $driver;
  112. public static function init(string $driver): void
  113. {
  114. $config = (new PDOConfig())
  115. ->withDriver($driver)
  116. ->withHost('tfb-database')
  117. ->withPort($driver == 'mysql' ? 3306 : 5432)
  118. ->withDbName('hello_world')
  119. ->withUsername('benchmarkdbuser')
  120. ->withPassword('benchmarkdbpass');
  121. self::$pool = new PDOPool($config, intval(1400 / swoole_cpu_num()));
  122. self::$driver = $driver;
  123. }
  124. public static function db(): string
  125. {
  126. $pdo = self::get();
  127. $result = Operation::db(self::getStatement($pdo, 'select'));
  128. self::put($pdo);
  129. return $result;
  130. }
  131. public static function fortunes(): string
  132. {
  133. $pdo = self::get();
  134. $result = Operation::fortunes(self::getStatement($pdo, 'fortunes'));
  135. self::put($pdo);
  136. return $result;
  137. }
  138. public static function query(int $queries): string
  139. {
  140. $pdo = self::get();
  141. $result = Operation::query(self::getStatement($pdo, 'select'), $queries);
  142. self::put($pdo);
  143. return $result;
  144. }
  145. public static function updates(int $queries): string
  146. {
  147. $pdo = self::get();
  148. $result = Operation::updates(self::getStatement($pdo, 'select'), self::getStatement($pdo, 'update', $queries), $queries, self::$driver);
  149. self::put($pdo);
  150. return $result;
  151. }
  152. private static function get(): PDO|PDOProxy
  153. {
  154. return self::$pool->get();
  155. }
  156. private static function put(PDO|PDOProxy $db): void
  157. {
  158. self::$pool->put($db);
  159. }
  160. private static function getStatement(PDO|PDOProxy $pdo, string $type, int $queries = 0): PDOStatement|PDOStatementProxy
  161. {
  162. if ('select' == $type) {
  163. return $pdo->prepare(Operation::WORLD_SELECT_SQL);
  164. } elseif ('fortunes' == $type) {
  165. return $pdo->prepare(Operation::FORTUNE_SQL);
  166. } else {
  167. return self::$driver == 'pgsql'
  168. ? $pdo->prepare('UPDATE World SET randomNumber = CASE id'.\str_repeat(' WHEN ?::INTEGER THEN ?::INTEGER ', $queries).'END WHERE id IN ('.\str_repeat('?::INTEGER,', $queries - 1).'?::INTEGER)')
  169. : $pdo->prepare(Operation::WORLD_UPDATE_SQL);
  170. }
  171. }
  172. }