Skip to content

Commit 002386e

Browse files
authored
PHPLIB-1237 Implement GridFS multi-file upload & download (#1170)
Parallel Benchmarks specs: GridFS upload & download https://github.com/mongodb/specifications/blob/ddfc8b583d49aaf8c4c19fa01255afb66b36b92e/source/benchmarking/benchmarking.rst#gridfs-upload Single implementation using one fork for each file uploaded/downloaded.
1 parent 5d7511d commit 002386e

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
<?php
2+
3+
namespace MongoDB\Benchmark\DriverBench;
4+
5+
use MongoDB\Benchmark\Fixtures\Data;
6+
use MongoDB\Benchmark\Utils;
7+
use PhpBench\Attributes\BeforeMethods;
8+
9+
use function array_map;
10+
use function basename;
11+
use function fopen;
12+
use function is_dir;
13+
use function mkdir;
14+
use function pcntl_fork;
15+
use function pcntl_waitpid;
16+
use function range;
17+
use function sprintf;
18+
use function stream_copy_to_stream;
19+
use function sys_get_temp_dir;
20+
use function unlink;
21+
22+
/**
23+
* For accurate results, run benchmarks on a standalone server.
24+
*
25+
* @see https://github.com/mongodb/specifications/blob/ddfc8b583d49aaf8c4c19fa01255afb66b36b92e/source/benchmarking/benchmarking.rst#parallel
26+
*/
27+
#[AfterMethods('cleanup')]
28+
final class ParallelGridFSBench
29+
{
30+
public static function cleanup(): void
31+
{
32+
Utils::getDatabase()->drop();
33+
34+
foreach (self::getFileNames() as $file) {
35+
unlink($file);
36+
}
37+
}
38+
39+
/**
40+
* GridFS multi-file upload
41+
*
42+
* @see https://github.com/mongodb/specifications/blob/ddfc8b583d49aaf8c4c19fa01255afb66b36b92e/source/benchmarking/benchmarking.rst#gridfs-multi-file-upload
43+
*/
44+
#[BeforeMethods('beforeUpload')]
45+
public function benchUpload(): void
46+
{
47+
$pids = [];
48+
foreach (self::getFileNames() as $file) {
49+
$pid = pcntl_fork();
50+
if ($pid === 0) {
51+
Utils::getDatabase()->selectGridFSBucket()->uploadFromStream(basename($file), fopen($file, 'r'));
52+
53+
// Exit the child process
54+
exit(0);
55+
}
56+
57+
if ($pid === -1) {
58+
throw new RuntimeException('Failed to fork');
59+
}
60+
61+
// Keep the forked process id to wait for it later
62+
$pids[$pid] = true;
63+
}
64+
65+
// Wait for all child processes to finish
66+
while ($pids !== []) {
67+
$pid = pcntl_waitpid(-1, $status);
68+
unset($pids[$pid]);
69+
}
70+
}
71+
72+
public function beforeUpload(): void
73+
{
74+
foreach (self::getFileNames() as $file) {
75+
stream_copy_to_stream(Data::getStream(5 * 1024 * 1024), fopen($file, 'w'));
76+
}
77+
78+
$database = Utils::getDatabase();
79+
$database->drop();
80+
81+
$bucket = $database->selectGridFSBucket();
82+
$bucket->uploadFromStream('init', Data::getStream(1));
83+
84+
Utils::reset();
85+
}
86+
87+
/**
88+
* GridFS multi-file download
89+
*
90+
* @see https://github.com/mongodb/specifications/blob/ddfc8b583d49aaf8c4c19fa01255afb66b36b92e/source/benchmarking/benchmarking.rst#gridfs-multi-file-download
91+
*/
92+
#[BeforeMethods('beforeDownload')]
93+
public function benchDownload(): void
94+
{
95+
$pids = [];
96+
foreach (self::getFileNames() as $file) {
97+
$pid = pcntl_fork();
98+
if ($pid === 0) {
99+
$stream = Utils::getDatabase()
100+
->selectGridFSBucket()
101+
->openDownloadStreamByName(basename($file));
102+
stream_copy_to_stream($stream, fopen($file, 'w'));
103+
104+
// Exit the child process
105+
exit(0);
106+
}
107+
108+
if ($pid === -1) {
109+
throw new RuntimeException('Failed to fork');
110+
}
111+
112+
// Keep the forked process id to wait for it later
113+
$pids[$pid] = true;
114+
}
115+
116+
// Wait for all child processes to finish
117+
while ($pids !== []) {
118+
$pid = pcntl_waitpid(-1, $status);
119+
unset($pids[$pid]);
120+
}
121+
}
122+
123+
public function beforeDownload(): void
124+
{
125+
// Initialize the GridFS bucket with the files
126+
$this->beforeUpload();
127+
$this->benchUpload();
128+
}
129+
130+
private static function getFileNames(): array
131+
{
132+
$tempDir = sys_get_temp_dir() . '/mongodb-php-benchmark';
133+
if (! is_dir($tempDir)) {
134+
mkdir($tempDir);
135+
}
136+
137+
return array_map(
138+
static fn (int $i) => sprintf('%s/file%02d.txt', $tempDir, $i),
139+
range(0, 49),
140+
);
141+
}
142+
}

0 commit comments

Comments
 (0)