by 张宴 With PHP 5.3 and above, using the pthreads PHP extension lets PHP truly support multithreading. When handling repetitive loop tasks, multithreading can greatly shorten program execution time. As I said in a previous article of mine, the performance bottleneck of most websites is not the PHP server, because that can be easily handled by simply scaling out with more servers or more CPU cores (for the various cloud hosts, adding VPS instances or CPU cores is even more convenient — you just add a VPS from a backup image, and you don’t even have to install or configure an operating system or environment). The bottleneck is the MySQL database. If you use a MySQL database, a single join query in SQL might be enough to handle the business logic, but when you run into a large number of concurrent requests, it falls apart. If you use a NoSQL database, you might need ten queries to handle the same business logic, but each query is faster than MySQL — ten NoSQL queries in a loop may well be faster than one MySQL join query, and handling tens of thousands of queries per second is no problem at all. Add PHP multithreading on top, querying NoSQL with ten threads at the same time and aggregating the returned results for output, and it gets even faster. In our actual APP product, calling a single PHP interface that recommends products in real time based on user preferences requires PHP to issue 500~1000 queries to the BigSea NoSQL database in order to compute the user’s personalized preferred product data in real time — the effect of PHP multithreading is very obvious here.
PHP extension download: https://github.com/krakjoe/pthreads PHP manual documentation: http://php.net/manual/zh/book.pthreads.php 1. Compiling and installing the extension (Linux). The configure option —enable-maintainer-zts is mandatory:1
2
3
4
5cd /Data/tgz/php-5.5.1 ./configure --prefix=/Data/apps/php --with-config-file-path=/Data/apps/php/etc --with-mysql=/Data/apps/mysql --with-mysqli=/Data/apps/mysql/bin/mysql_config --with-iconv-dir --with-freetype-dir=/Data/apps/libs --with-jpeg-dir=/Data/apps/libs --with-png-dir=/Data/apps/libs --with-zlib --with-libxml-dir=/usr --enable-xml --disable-rpath --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curl --enable-mbregex --enable-fpm --enable-mbstring --with-mcrypt=/Data/apps/libs --with-gd --enable-gd-native-ttf --with-openssl --with-mhash --enable-pcntl --enable-sockets --with-xmlrpc --enable-zip --enable-soap --enable-opcache --with-pdo-mysql --enable-maintainer-zts make clean make make installunzip pthreads-master.zip cd pthreads-master /Data/apps/php/bin/phpize ./configure --with-php-config=/Data/apps/php/bin/php-config make make install
vi /Data/apps/php/etc/php.ini
Add:
extension = “pthreads.so”
- Here is a PHP code example that uses PHP multithreading, together with a For loop, to fetch Baidu search pages:
view plainprint?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
73<?php
class test\_thread\_run extends Thread
{
public $url;
public $data;
public function __construct($url)
{
$this->url = $url;
}
public function run()
{
if(($url = $this->url))
{
$this->data = model\_http\_curl_get($url);
}
}
}
function model\_thread\_result_get($urls_array)
{
foreach ($urls_array as $key => $value)
{
$thread_array\[$key\] = new test\_thread\_run($value\["url"\]);
$thread_array\[$key\]->start();
}
foreach ($thread_array as $thread\_array\_key => $thread\_array\_value)
{
while($thread_array\[$thread\_array\_key\]->isRunning())
{
usleep(10);
}
if($thread_array\[$thread\_array\_key\]->join())
{
$variable_data\[$thread\_array\_key\] = $thread_array\[$thread\_array\_key\]->data;
}
}
return $variable_data;
}
function model\_http\_curl_get($url,$userAgent="")
{
$userAgent = $userAgent ? $userAgent : 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2)';
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_TIMEOUT, 5);
curl_setopt($curl, CURLOPT_USERAGENT, $userAgent);
$result = curl_exec($curl);
curl_close($curl);
return $result;
}
for ($i=0; $i < 100; $i++)
{
$urls_array\[\] = array("name" => "baidu", "url" => "http://www.baidu.com/s?wd=".mt_rand(10000,20000));
}
$t = microtime(true);
$result = model\_thread\_result_get($urls_array);
$e = microtime(true);
echo "多线程:".($e-$t)."\\n";
$t = microtime(true);
foreach ($urls_array as $key => $value)
{
$result_new\[$key\] = model\_http\_curl_get($value\["url"\]);
}
$e = microtime(true);
echo "For循环:".($e-$t)."\\n";
?>

