Benchmark hašovacích tabuliek v PHP cez jednoduchú key-value databázu

Podmienky testovania

upraviť
  • programovací jazyk PHP 7.3.27-1~deb10u1
  • testovacia aplikácia bola „jednovláknová“
    • dáta typu sú interné ukladané ako hašovacie tabuľky[1]
  • implementovaná jednoduchá key-value databáza
    • databáza je uložená celá v pamäte RAM
    • hodnoty key je snaha ukladať ako reťazce resp. blok pamäte
    • hodnoty value sú generované náhodne
  • import nových dát prebieha z vopred vygenerovaného CSV
  • export nových dát prebieha do CSV
    • priamy export do CSV bez konverzií (očakáva, že vstupné dáta sú iba: 'a' – 'z', 'A' – 'Z' a '0' – '9')

Názvy testov

upraviť

Názov je podľa číselných hodnôt konštánt v zdrojovom kóde:

KEY_LENGTH – VALUES – VALUE_LENGTH

Význam konštánt:

  • KEY_LENGTH – koľko bajtov budeme používať pre ukladanie kľúča
  • VALUES – koľko hodnôt sa bude ukladanie pri key-value databáze
    • 1 – napr. pre číslo položky, adresu alebo 1 informáciu
    • 2 – napr. pre ofsety začiatok-koniec
  • VALUE_LENGTH – veľkosť value v bajtov

Výsledky testovania

upraviť
Testy
4 – 1 – 4 4 – 2 – 4 8 – 1 – 4 8 – 2 – 4
záznamov po pridaní [milióny] čas importu [s] čas exportu [s] použitá pamäť [MB] čas importu [s] čas exportu [s] použitá pamäť [MB] čas importu [s] čas exportu [s] použitá pamäť [MB] čas importu [s] čas exportu [s] použitá pamäť [MB]
1 0,58 0,63 143 0,98 0,63 157 0,70 0,69 461 1,09 0,69 478
2 0,59 1,26 216 1,01 1,29 241 0,70 1,35 858 1,11 1,37 881
3 0,60 1,91 331 1,04 1,96 365 0,72 2,00 1294 1,12 2,05 1328
4 0,57 2,58 363 0,99 2,59 405 0,69 2,70 1646 1,07 2,74 1688
5 0,68 3,24 564 1,06 3,20 612 0,76 3,37 2166 1,19 3,44 2217
6 0,58 3,85 596 0,99 3,82 652 0,71 4,14 2519 1,09 4,09 2577
7 0,58 4,66 627 0,99 4,49 692 0,70 4,73 2873 1,13 4,91 2938
8 0,58 5,20 661 0,99 5,15 734 0,72 5,55 3225 1,13 5,54 3299
9 0,77 5,85 1028 1,18 5,82 1109 0,92 6,29 3913 1,33 6,14 3995
10 0,58 6,38 1059 0,98 6,39 1149 0,73 6,93 4266 1,13 6,72 4356
11 0,58 7,36 1091 0,99 7,17 1189 0,60 7,43 4297 0,99 7,44 4396
12 0,60 7,97 1124 1,00 7,84 1229 0,60 8,20 4329 1,01 8,20 4435
13 0,59 8,51 1156 0,99 8,42 1271 0,61 8,70 4362 0,99 8,80 4475
14 0,58 9,14 1187 1,00 9,00 1311 0,60 9,48 4394 1,00 9,52 4515
15 0,59 9,98 1221 0,99 9,56 1351 0,59 9,79 4425 1,00 10,04 4557
16 0,59 10,41 1252 1,00 10,26 1390 0,57 10,56 4459 1,00 10,84 4597
17 0,96 10,95 1955 1,38 10,86 2101 1,01 11,32 5161 1,40 11,45 5308
18 0,58 11,72 1986 0,97 11,51 2141 0,60 12,07 5193 1,01 12,36 5348
19 0,59 12,48 2020 0,98 12,04 2183 0,60 12,76 5224 1,00 12,87 5388
20 0,61 13,23 2051 1,00 12,90 2223 0,59 13,49 5258 0,98 13,47 5430
21 0,59 13,94 2082 0,98 13,33 2263 0,60 13,87 5289 0,99 14,03 5469
22 0,59 14,19 2116 0,98 14,00 2303 0,60 14,59 5320 0,99 14,53 5509
23 0,59 14,77 2147 0,99 14,70 2343 0,60 15,35 5354 0,99 15,16 5549
24 0,58 15,26 2179 1,00 15,34 2384 0,62 16,23 5385 1,01 16,12 5589
25 0,58 16,23 2210 0,97 16,10 2424 0,62 16,90 5417 1,02 16,81 5631
26 0,58 17,03 2244 0,99 16,60 2464 0,60 17,67 5448 1,02 17,24 5671
27 0,58 17,36 2275 0,97 17,05 2504 0,60 18,10 5482 1,00 18,13 5711
28 0,59 17,98 2307 0,97 17,65 2544 0,60 18,69 5513 0,98 18,71 5750
29 0,59 18,76 2340 1,01 18,62 2586 0,61 19,11 5545 0,99 19,52 5790
30 0,58 19,24 2372 1,01 19,44 2626 0,58 20,00 5578 1,02 20,04 5830
31 0,61 19,97 2403 1,00 19,93 2665 0,60 21,04 5610 1,00 20,50 5872
32 0,58 20,69 2435 0,98 20,59 2705 0,60 21,24 5641 1,00 21,38 5912
33 0,59 21,36 2468 0,97 21,23 2745 0,60 21,96 5673 1,02 22,15 5952
34 1,33 21,80 3842 1,76 22,11 4127 1,40 22,45 7049 1,77 22,93 7334
35 0,57 22,87 3873 0,99 22,73 4169 0,59 22,82 7080 1,02 23,48 7374
36 0,60 23,61 3907 0,99 23,31 4209 0,60 24,12 7111 1,01 24,04 7416
37 0,59 23,99 3938 0,99 23,98 4249 0,63 24,59 7145 0,99 24,60 7455
38 0,57 24,47 3970 0,98 24,57 4289 0,61 25,44 7176 1,02 24,75 7495
39 0,58 25,26 4003 0,98 24,97 4329 0,60 26,12 7208 0,99 26,00 7535
40 0,59 25,93 4035 0,98 25,89 4370 0,60 26,79 7241 0,98 26,45 7575
41 0,60 27,05 4066 0,98 26,42 4410 0,61 27,12 7273 1,00 26,98 7615
42 0,58 27,44 4098 1,01 27,19 4450 0,59 28,42 7304 1,02 27,63 7657
43 0,60 28,40 4131 1,00 28,06 4490 0,59 28,66 7336 0,99 28,52 7697
44 0,59 28,63 4163 1,01 27,95 4530 0,61 29,74 7369 1,03 29,01 7736
45 0,59 29,46 4194 0,98 28,86 4572 0,60 29,62 7401 1,00 29,66 7776
46 0,59 30,45 4228 1,00 29,91 4612 0,59 30,05 7432 1,02 30,31 7816
47 0,60 30,71 4259 0,99 30,55 4651 0,59 30,85 7466 0,99 31,53 7858
48 0,61 31,62 4291 0,98 31,19 4691 0,61 32,29 7497 0,99 31,95 7898
49 0,58 31,85 4322 0,99 32,07 4731 0,60 32,50 7529 1,03 32,22 7938
50 0,57 32,10 4356 0,99 32,64 4771 0,60 32,84 7560 1,02 33,32 7978

Zdrojový kód na testovanie

upraviť
<?php

define("COUNT_IMPORT", -1);
define("RECORDS", 1000000);
define("KEY_LENGTH", 8);
define("VALUES", 2);
define("VALUE_LENGTH", 4); // 2, 4, 6, 8 and more – for generator

function render_csv()
{
	$csv="";
	
	$last_item_index=VALUES-1;
	
	for($a=0;$a<RECORDS;$a++)
	{
		for($b=0;$b<VALUES;$b++)
		{
			$bytes=random_bytes(VALUE_LENGTH/2);
			$item=bin2hex($bytes);
			if($b == $last_item_index)
				$csv.="$item\n";
			else
				$csv.="$item,";
		}
	}
	
	return $csv;
}


$txt="count before | count added | count after | time of import (s) | time of export (s) | alloced memory\n";
echo "$txt\n";
file_put_contents("test.log", "$txt\n");

$date=array();

$new_key=0;
$step=0;
while(1)
{
	$import=render_csv();
	
	$count_before=count($date);
	
	// import
	$start_import=microtime(true);
	$lines=explode("\n", $import);
	unset($lines[count($lines)-1]);
	foreach($lines as $line)
	{
		// key
		$key=sprintf("%0".KEY_LENGTH."d", $new_key);
		$new_key++;
		
		// record
		$values=str_getcsv($line);
		$record_raw=implode("", $values);
		
		// add to date
		$date["$key"]=$record_raw;
	}
	$count_after=count($date);
	$count_diff=$count_after-$count_before;
	
	$end_import=microtime(true);
	$diff_import=sprintf("%0.3f", $end_import-$start_import);
	
	unset($import);
	
	// export
	$start_export=microtime(true);
	$fd=fopen("/dev/null", "w");
	if($fd === false)
		exit;
	foreach($date as $key => $value)
		fwrite($fd, "$key,$value\n");
	fclose($fd);
	$end_export=microtime(true);
	$diff_export=sprintf("%0.3f", $end_export-$start_export);
	
	$usage_memory=memory_get_usage(true);
	
	$txt="$count_before | $count_diff | $count_after | $diff_import | $diff_export | $usage_memory";
	echo "$txt\n";
	file_put_contents("test.log", "$txt\n", FILE_APPEND);
	
	$step++;
	if($step == COUNT_IMPORT)
	{
		echo "\n";
		break;
	}
}

Referencie

upraviť
  1. COMPANY, Sudo Null. Arrays in PHP 7: Hash Tables [online]. sudonull.com, [cit. 2021-06-26]. Dostupné online.