From 86e634580a736c0e52613071f2eab73b8fa3572d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ama=C3=ABl=20Kesteman?= Date: Sat, 6 Dec 2025 15:01:39 +0100 Subject: [PATCH 1/2] Feat: ajout test hash --- Main.ipynb | 289 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 201 insertions(+), 88 deletions(-) diff --git a/Main.ipynb b/Main.ipynb index 1bf420f..b38eec5 100644 --- a/Main.ipynb +++ b/Main.ipynb @@ -15,7 +15,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 1, "id": "78fdf40a", "metadata": { "ExecuteTime": { @@ -34,8 +34,10 @@ "import numpy as np\n", "import pandas as pd\n", "import os\n", + "import hashlib\n", "from IPython.display import display\n", - "from scipy import stats\n" + "from scipy import stats\n", + "\n" ] }, { @@ -63,7 +65,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Configs ok: {'KPvKP', 'KRPvKP', 'KQvKP', 'KRvKB', 'KRBvKP', 'KBvK', 'KQvK', 'KRvK', 'KPvK', 'KBNvK', 'KNvK'}\n" + "Configs ok: {'KRBvKP', 'KRvKB', 'KRvK', 'KBNvK', 'KBvK', 'KRPvKP', 'KPvK', 'KNvK', 'KQvK', 'KQvKP', 'KPvKP'}\n" ] }, { @@ -100,7 +102,7 @@ "Récupération des positions de la tablebase KRvKB\n", "Récupération des positions de la tablebase KBvK\n", "Récupération des positions de la tablebase KNvK\n", - "Total positions récupérées: 110000\n", + "Total positions récupérées: 55000\n", "Ajoute de toutes les positions des tablebases dans Redis terminé!\n" ] } @@ -110,7 +112,7 @@ " positions = []\n", " tries = 0\n", "\n", - " while len(positions) < 10000 and tries < 10000000:\n", + " while len(positions) < 10000 and tries < 5000:\n", " board = generate_board_from_config(config)\n", " positions.append(board)\n", " tries += 1\n", @@ -203,7 +205,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 3, "id": "8d49b928-7522-4727-b6d8-224e2bd3a1b7", "metadata": { "ExecuteTime": { @@ -274,7 +276,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "0d955b0d-dc80-4518-954b-7c2df295adca", "metadata": { "ExecuteTime": { @@ -282,25 +284,7 @@ "start_time": "2025-12-06T10:18:18.393765Z" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "BENCHMARK SYZYGY\n", - "BENCHMARK REDIS\n", - "Redis latency array length: 110000\n", - "Syzygy latency array length: 100352\n", - " test statistic p-value \\\n", - "0 paired t-test 123.259244 0.0 \n", - "1 KS-test 0.683873 0.0 \n", - "\n", - " interpretation \n", - "0 H0: mean latency equal (Redis vs Syzygy) \n", - "1 H0: same latency distribution (Redis vs Syzygy) \n" - ] - } - ], + "outputs": [], "source": [ "def statistical_tests(bench_redis, bench_syzygy):\n", " redis_lat = np.array(bench_redis[\"latency\"], dtype=np.float64)\n", @@ -374,47 +358,10 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "id": "a68060e1-0052-4446-a0d3-40bc1756f210", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "=== Benchmark Redis GET : 3pieces ===\n", - "\n", - "=== Benchmark Redis GET : 4pieces ===\n", - "\n", - "=== Benchmark Redis GET : 5pieces ===\n" - ] - }, - { - "data": { - "text/plain": [ - "{'3pieces': {'mean_ms': np.float64(0.13212380988989025),\n", - " 'median_ms': np.float64(0.09551599941914901),\n", - " 'min_ms': np.float64(0.08083799912128597),\n", - " 'max_ms': np.float64(0.8959879996837117),\n", - " 'std_ms': np.float64(0.13300422173582635)},\n", - " '4pieces': {'mean_ms': np.float64(0.11616323999987799),\n", - " 'median_ms': np.float64(0.09786150076251943),\n", - " 'min_ms': np.float64(0.0883979992067907),\n", - " 'max_ms': np.float64(0.5116760003147647),\n", - " 'std_ms': np.float64(0.06668460178765279)},\n", - " '5pieces': {'mean_ms': np.float64(0.14741114000571542),\n", - " 'median_ms': np.float64(0.1148745004684315),\n", - " 'min_ms': np.float64(0.0882360000105109),\n", - " 'max_ms': np.float64(0.8414919993811054),\n", - " 'std_ms': np.float64(0.10206867963393614)}}" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "\n", "\"\"\"\n", @@ -473,29 +420,10 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "a68060e1-0052-4446-a0d3-40bc1756f210", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "MEMORY USAGE REDIS\n", - "Memory Redis: 178.58M\n" - ] - }, - { - "data": { - "text/plain": [ - "'\\n#Test Mémoire Syzygy\\nimport psutil\\n\\ntablebases = chess.syzygy.open_tablebase(\"tablebases/\")\\n\\n#Récuperer les données de proccesus de Syzygy\\nprocess = psutil.Process(os.getpid())\\nmem_bytes = process.memory_info().rss\\nmem_mb = mem_bytes / (1024**2)\\nprint(\"MEMORY USAGE SYZYGY\")\\nprint(f\"Memory Syzygy: {mem_mb}\")\\n'" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "#Test Mémoire Redis ( Stockage du Redis )\n", "redis_server = redis.Redis(host=\"localhost\", port=6379, db=0)\n", @@ -518,11 +446,196 @@ "print(f\"Memory Syzygy: {mem_mb}\")\n", "\"\"\"" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "46157e5c", + "metadata": {}, + "outputs": [], + "source": [ + "def get_250_random_position(tablebases, config):\n", + " positions = []\n", + " tries = 0\n", + "\n", + " while len(positions) < 250 and tries < 5000:\n", + " board = generate_board_from_config(config)\n", + " try:\n", + " tablebases.probe_wdl(board) # thử probe WDL\n", + " positions.append(board)\n", + " except chess.syzygy.MissingTableError:\n", + " pass # bỏ qua nếu table không tồn tại\n", + " tries += 1\n", + " return positions\n", + "\n", + "def add_tablebase_to_redis():\n", + " h = hashlib.new('sha512_256')\n", + " #Connect to Redis server\n", + " redis_server = redis.Redis(host='localhost', port=6379, db=1) #db1 pour H4\n", + " \n", + " tablebases_path = \"tablebases/\" #Chemin vers les tables bases Syzygy\n", + "\n", + " tablebases = chess.syzygy.open_tablebase(tablebases_path)\n", + "\n", + " available_tables = set()\n", + " for f in os.listdir(tablebases_path):\n", + " if f.endswith(\".rtbw\") or f.endswith(\".rtbz\"):\n", + " available_tables.add(f.split(\".\")[0])\n", + "\n", + " print(\"Configs ok:\", available_tables)\n", + " \n", + " configs = [\"KBNvK\",\"KPvK\",\"KPvKP\",\"KQvK\",\"KQvKP\",\"KRBvKP\",\"KRPvKP\",\"KRvK\",\"KRvKB\"]\n", + " config_valide = [c for c in configs if c in available_tables]\n", + " #Configurations de toute les tablebases que l'on utilisera dans le projet.\n", + " all_positions = []\n", + " for config in config_valide:\n", + " print(f\"Récupération des positions de la tablebase {config}\")\n", + " position = get_250_random_position(tablebases,config)\n", + " all_positions.extend(position) #Ajout des positions générées à la liste globale\n", + " \n", + " print(f\"Total positions récupérées: {len(all_positions)}\")\n", + " for position in all_positions:\n", + " try:\n", + " fen = position.fen()\n", + " key = hashlib.md5(fen.encode()).hexdigest()[:16] #Limite à 16 caractères\n", + " wdl = tablebases.probe_wdl(position)\n", + " dtz = tablebases.probe_dtz(position)\n", + " redis_server.hset(key, mapping={\"wdl\": wdl, \"dtz\": dtz}) \n", + " except (KeyError,chess.syzygy.MissingTableError): #vérifie que les positions générés appartiennent bien au table du projet seulement\n", + " continue \n", + " \n", + " print(\"Ajoute de toutes les positions hashés des tablebases dans Redis terminé!\")\n", + "\n", + "if __name__ == \"__main__\":\n", + " add_tablebase_to_redis()\n", + " \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "099ce824", + "metadata": {}, + "outputs": [], + "source": [ + "def benchmark_hash(redis_serveur, pos):\n", + " latency = []\n", + " start_time_all = time.time()\n", + "\n", + " for board in pos:\n", + " fen = board.fen()\n", + " key = hashlib.md5(fen.encode()).hexdigest()[:16] #Limite à 16 caractères\n", + " start_individual = time.time()\n", + " results = redis_serveur.hgetall(key)\n", + " latency.append(time.time() - start_individual)\n", + "\n", + " total_time_all=time.time()-start_time_all\n", + " latency= np.array(latency)\n", + "\n", + " return{\n", + " \"count\": len(pos),\n", + " \"average_latency\": latency.mean(),\n", + " \"p50\": np.percentile(latency,50),\n", + " \"p90\": np.percentile(latency,90),\n", + " \"p95\": np.percentile(latency,95),\n", + " \"p99\": np.percentile(latency,99),\n", + " \"std\": latency.std(),\n", + " \"min\": latency.min(),\n", + " \"max\": latency.max(),\n", + " \"total_time\": total_time_all,\n", + " \"latency\": latency,\n", + " \"rps\": len(latency)/total_time_all,\n", + " }" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "646babb4", + "metadata": {}, + "outputs": [], + "source": [ + "def statistical_tests(bench_redis, bench_hash):\n", + " redis_lat = np.array(bench_redis[\"latency\"], dtype=np.float64)\n", + " hash_lat = np.array(bench_hash[\"latency\"], dtype=np.float64)\n", + " min_len = min(len(redis_lat), len(hash_lat))\n", + " redis_lat = redis_lat[:min_len]\n", + " hash_lat = hash_lat[:min_len]\n", + " \n", + " # PAIRED T-Test (Comparaison median)\n", + " t_stat, t_p = stats.ttest_rel(hash_lat, redis_lat)\n", + " \n", + " # KS Test (Comparaison distribution)\n", + " ks_stat, ks_p = stats.ks_2samp(hash_lat, redis_lat)\n", + " \n", + " df_stats = pd.DataFrame({\n", + " \"test\": [\"paired t-test\", \"KS-test\"],\n", + " \"statistic\": [t_stat, ks_stat],\n", + " \"p-value\": [t_p, ks_p],\n", + " \"interpretation\": [\n", + " \"H0: mean latency equal (Redis vs Hash)\",\n", + " \"H0: same latency distribution (Redis vs Hash)\"\n", + " ]\n", + " })\n", + " print(df_stats)\n", + " return df_stats\n", + "\n", + "def run_experiment():\n", + " redis_server = redis.Redis(host=\"localhost\", port=6379, db=0)\n", + " redis_hash = redis.Redis(host=\"localhost\", port=6379, db=1)\n", + " tablebases = chess.syzygy.open_tablebase(\"tablebases/\")\n", + " \n", + " configs = [\"KBNvK\",\"KPvK\",\"KPvKP\",\"KQvK\",\"KQvKP\",\"KRBvKP\",\"KRPvKP\",\"KRvK\",\"KRvKB\"]\n", + " \n", + " all_positions = []\n", + " for config in configs:\n", + " all_positions += get_250_random_position(tablebases, config)\n", + " \n", + " # Filter to have 2 paired test have the same N\n", + " valid_positions = []\n", + " for board in all_positions:\n", + " try:\n", + " tablebases.probe_wdl(board)\n", + " valid_positions.append(board)\n", + " except chess.syzygy.MissingTableError:\n", + " continue\n", + " \n", + " print(\"BENCHMARK REDIS (FEN)\")\n", + " bench_redis = benchmark_redis(redis_server, valid_positions) # ← db=0 (FEN)\n", + " print(bench_redis)\n", + " \n", + " print(\"BENCHMARK REDIS (HASH)\")\n", + " bench_hash = benchmark_hash(redis_hash, valid_positions) # ← db=1 (Hash), fonction différente\n", + " print(bench_hash)\n", + " \n", + " # Afficher les longueurs APRÈS avoir créé les benchmarks\n", + " print(f\"Redis FEN latency array length: {len(bench_redis['latency'])}\")\n", + " print(f\"Redis Hash latency array length: {len(bench_hash['latency'])}\")\n", + " \n", + " print(\"MEMORY USAGE REDIS (FEN - db=0)\")\n", + " mem_fen_bytes, mem_fen_human = get_redis_memory(redis_server)\n", + " print(f\"Memory: {mem_fen_human} ({mem_fen_bytes} bytes)\")\n", + " \n", + " print(\"MEMORY USAGE REDIS (HASH - db=1)\")\n", + " mem_hash_bytes, mem_hash_human = get_redis_memory(redis_hash)\n", + " print(f\"Memory: {mem_hash_human} ({mem_hash_bytes} bytes)\")\n", + " \n", + " return {\n", + " \"bench_redis\": bench_redis,\n", + " \"bench_hash\": bench_hash,\n", + " \"memory_redis\": mem_fen_bytes,\n", + " \"memory_hash\": mem_hash_bytes\n", + " }\n", + "\n", + "if __name__ == \"__main__\":\n", + " results = run_experiment()\n", + " statistical_tests(results[\"bench_redis\"], results[\"bench_hash\"])" + ] } ], "metadata": { "kernelspec": { - "display_name": ".venv", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -536,7 +649,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.3" + "version": "3.10.12" } }, "nbformat": 4, From 72140b4bd7b68c36df932f0ca09a98c5e0c8ecfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ama=C3=ABl=20Kesteman?= Date: Sat, 6 Dec 2025 15:01:58 +0100 Subject: [PATCH 2/2] Feat: ajout test hash --- Main.ipynb | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 4 deletions(-) diff --git a/Main.ipynb b/Main.ipynb index b38eec5..264a9d0 100644 --- a/Main.ipynb +++ b/Main.ipynb @@ -276,7 +276,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "id": "0d955b0d-dc80-4518-954b-7c2df295adca", "metadata": { "ExecuteTime": { @@ -284,7 +284,25 @@ "start_time": "2025-12-06T10:18:18.393765Z" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "BENCHMARK SYZYGY\n", + "BENCHMARK REDIS\n", + "Redis latency array length: 55000\n", + "Syzygy latency array length: 50127\n", + " test statistic p-value \\\n", + "0 paired t-test 85.042506 0.0 \n", + "1 KS-test 0.546193 0.0 \n", + "\n", + " interpretation \n", + "0 H0: mean latency equal (Redis vs Syzygy) \n", + "1 H0: same latency distribution (Redis vs Syzygy) \n" + ] + } + ], "source": [ "def statistical_tests(bench_redis, bench_syzygy):\n", " redis_lat = np.array(bench_redis[\"latency\"], dtype=np.float64)\n", @@ -358,10 +376,47 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "id": "a68060e1-0052-4446-a0d3-40bc1756f210", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "=== Benchmark Redis GET : 3pieces ===\n", + "\n", + "=== Benchmark Redis GET : 4pieces ===\n", + "\n", + "=== Benchmark Redis GET : 5pieces ===\n" + ] + }, + { + "data": { + "text/plain": [ + "{'3pieces': {'mean_ms': np.float64(0.4589625600419822),\n", + " 'median_ms': np.float64(0.40479199969922774),\n", + " 'min_ms': np.float64(0.20995799968659412),\n", + " 'max_ms': np.float64(4.594801999701303),\n", + " 'std_ms': np.float64(0.42983928490153817)},\n", + " '4pieces': {'mean_ms': np.float64(0.36221424002178537),\n", + " 'median_ms': np.float64(0.33665850014585885),\n", + " 'min_ms': np.float64(0.2021390000663814),\n", + " 'max_ms': np.float64(1.0131979997822782),\n", + " 'std_ms': np.float64(0.12193858759433863)},\n", + " '5pieces': {'mean_ms': np.float64(0.3863061399442813),\n", + " 'median_ms': np.float64(0.3765404999285238),\n", + " 'min_ms': np.float64(0.20748299994011177),\n", + " 'max_ms': np.float64(0.6716950001646182),\n", + " 'std_ms': np.float64(0.09189286718199571)}}" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "\n", "\"\"\"\n",