Repository files navigation

996.icuLICENSE

phpgo

phpgo's mission is to provide a small, simple, stable extension for existing and future PHP applications for much higher concurrency, better performance, with lower resouce consumption and work well with most of the existing php features, extensions and frameworks

phpgo: A php extension that brings into php the go core features:

  • go routine
  • channel
  • select
  • mutex
  • waitgroup
  • timer
  • go routine scheduler

phpgo also brings in a break-through feature which:

  • automatically converts the synchronized function calls in the php extensions (e.g. PDO, redis... etc) into asynchronized

This allows the swithing of execution to another go routine if one go routine is blocked by blocking I/O, thus provides hundred to thousand times of concurrent executions under the same running environment

phpgo can be used under both CLI mode and fast-cgi (php-fpm) mode

phpgo supports php5.4 to 7.2 on linux as of today

0. Reference Manuals

1. Getting started

1.1. Install libgo

The phpgo relies on the the libgo library (thanks libgo!) to provide the underlying coroutine capability, which includes:

  • coroutine creation, execution and scheduling
  • coroutine local storage
  • coroutine listener with the task swap hook capability
  • go channel
  • go mutex
  • hook of system calls (thus allow corroutine switching during blocking system call)

(libgo contains more excellent features and you may want to check them out @ https://github.com/yyzybb537/libgo )

steps to install the libgo:

git clone https://github.com/yyzybb537/libgo
cd libgo
git checkout master
git pull
git reset --hard c280e6170a7d7bd124d98a8062cb47989f9ae4cd #use a compatible version of libgo
mkdir build
cd build
rm -rf *
cmake ..
make
make install
ldconfig

1.2. Build phpgo from source - supported on linux OS

steps to build phpgo:

git clone https://github.com/birdwyx/phpgo
cd phpgo
phpize
./configure -with-php-config=<the path to php-config>
make
make install

you may probably want to do a test first to ensure everything is fine before start using phpgo

cd phpgo
export TEST_PHP_EXECUTABLE=./test_php
php run-tests.php tests

ensure there are no FAIL'ed test cases

then, add the following line into the php.ini

extension=phpgo.so

1.3. First phpgo program

hello_world.php:

<?php
use \go\Scheduler; //for the Scheduler functions go(function(){ //creates a go routine
echo "Hello World!" . PHP_EOL;
});
Scheduler::join(); //execute all go routines

run this program under the command line:

#php hello_world.php
Hello World!
#

Have fun!

1.4. Using phpgo under fast-cgi mode

phpgo can be used under fast-cgi (php-fpm) mode, following are the steps:

Make libgo preloaded

You need to modify your php-fpm service management script (/etc/init.d/php-fpm), add the following line to the /etc/init.d/php-fpm at the very begining of the "start)" section:

export LD_PRELOAD=liblibgo.so

after your modification, the file should look like the following:

/etc/init.d/php-fpm:
...
case "$1" in
start)
echo -n "Starting php-fpm - with libgo preloaded"
export LD_PRELOAD=liblibgo.so
$php_fpm_BIN --daemonize $php_opts
if [ "$?" != 0 ] ; then
echo " failed"
exit 1
fi
...

then issue a "service php-fpm reload" to make the modification take effect

#service php-fpm reload

The reason to do that is for you to obtain the capability that allows the swithing of execution to another go routine while a go routine is I/O blocked, the LD_PRELOAD=liblibgo.so does the trick. For more information, see the dedicated section below that describes the details of what libgo has done for this capability, why the LD_PRELOAD is needed and how it functions.

Setup your go scheduler

A typical way to setup the go scheduler is to add the Scheduler::join() into the index.php

index.php:
use \go\Scheduler
...
your existing code which typically boots up a framework(e.g, laravel) who in turns runs your web service
...
Scheduler::join(); // the last line

Feel free to use the phpgo capability in your web service code

The places that you most likely to use the phpgo functions/methods are the Models / Controllers. The following code demonstrates a uses case where an API gateway consolidate a user's basic information, order placed, and browsing history and send back to the web broswer:

use \go\Scheduler;
...
function getUserDetailInfo(){
$userid = $_GET['userid']; $user_details = [];
$user_orders = [];
$user_browsing_history = [];
go(function(&$user_details){
$redis = new Redis();
$redis->connect(...);
$user_details = $redis->get( "user_details_of_" . $userid );
}, [&$user_details]);
go(function(&$user_orders){
$pdo = new PDO(...);
$user_orders = $pdo->query("select * from tb_order where userid = $userid");
}, [&$user_orders]);
go(function(&$user_browsing_history){
$curl = new Curl(...);
$user_browsing_history =
$curl->get("http://browsing.history.micro.service/path_to_the_browsing_history_query_api");
}, [&$user_browsing_history]);
Scheduler::join();
$result = array(
'user_details' = > $user_details,
'user_orders' => $user_orders,
'user_browsing_history' => $user_browsing_history,
);
echo json_encode($result);
}
...

The code above creates 3 go routines, which run in parallel getting the user basic information, order information and browsing history from redis, databases, and a microservice running http interface; the Scheduler::join() schedules and wait all the 3 go routines to finish running; then the code send back the consolidated result to the broswer

As we all know, due to the synchronized nature of php, in a php script all operations have to be exectued in sequence, in an API gateway that has a lot of interactions with other conter-parts, the total amount of execution time of a script can easily become unacceptable. By using phpgo, the amount of total execution time can reduce to the time of a single operation(given the operations are independent and can be executed in parallel)

2. LD_PRELOAD

to be updated...

3. Go Live

libgo supports using boost context for context switching (default context switching mechanism is u_context) which provides a much better coroutine switch performance (5+ times).

If you are using the phpgo under production environment, it's recommended that you enable the boost context switching by the steps below:

Firstly, you'll need to install boost 1.59.0+, I'll suggest you use 1.59.0, since libgo is using 1.59.0 in auto-integeration testing (as of today: 2018/5/25)

#wget https://sourceforge.net/projects/boost/files/boost/1.59.0/boost_1_59_0.tar.gz
#tar -xvf boost_1_59_0.tar.gz
#cd boost_1_59_0
#./bootstrap.sh
#./b2 -q install

Then, you'll need to add -DENABLE_BOOST_CONTEXT=ON option to the "cmake" command

#cd libgo/build
#rm -rf *
#cmake .. -DENABLE_BOOST_CONTEXT=ON
#make && make install

note: if you see compiler errors during the "make" step, make sure you've done the "rm -rf * " under the build directory

About

PHPGO: A php extension that brings into php the go core features: go routines, channel, select, mutex, waitgroup, timer and scheduler... now supports php5.5 to 7.2 on linux, for both cli and fastcgi, zts and non-zts mode usage

Resources

Stars

94 stars

Watchers

7 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

996.icuLICENSE

phpgo

phpgo's mission is to provide a small, simple, stable extension for existing and future PHP applications for much higher concurrency, better performance, with lower resouce consumption and work well with most of the existing php features, extensions and frameworks

phpgo: A php extension that brings into php the go core features:

  • go routine
  • channel
  • select
  • mutex
  • waitgroup
  • timer
  • go routine scheduler

phpgo also brings in a break-through feature which:

  • automatically converts the synchronized function calls in the php extensions (e.g. PDO, redis... etc) into asynchronized

This allows the swithing of execution to another go routine if one go routine is blocked by blocking I/O, thus provides hundred to thousand times of concurrent executions under the same running environment

phpgo can be used under both CLI mode and fast-cgi (php-fpm) mode

phpgo supports php5.4 to 7.2 on linux as of today

0. Reference Manuals

1. Getting started

1.1. Install libgo

The phpgo relies on the the libgo library (thanks libgo!) to provide the underlying coroutine capability, which includes:

  • coroutine creation, execution and scheduling
  • coroutine local storage
  • coroutine listener with the task swap hook capability
  • go channel
  • go mutex
  • hook of system calls (thus allow corroutine switching during blocking system call)

(libgo contains more excellent features and you may want to check them out @ https://github.com/yyzybb537/libgo )

steps to install the libgo:

git clone https://github.com/yyzybb537/libgo
cd libgo
git checkout master
git pull
git reset --hard c280e6170a7d7bd124d98a8062cb47989f9ae4cd #use a compatible version of libgo
mkdir build
cd build
rm -rf *
cmake ..
make
make install
ldconfig

1.2. Build phpgo from source - supported on linux OS

steps to build phpgo:

git clone https://github.com/birdwyx/phpgo
cd phpgo
phpize
./configure -with-php-config=<the path to php-config>
make
make install

you may probably want to do a test first to ensure everything is fine before start using phpgo

cd phpgo
export TEST_PHP_EXECUTABLE=./test_php
php run-tests.php tests

ensure there are no FAIL'ed test cases

then, add the following line into the php.ini

extension=phpgo.so

1.3. First phpgo program

hello_world.php:

<?php
use \go\Scheduler; //for the Scheduler functions go(function(){ //creates a go routine
echo "Hello World!" . PHP_EOL;
});
Scheduler::join(); //execute all go routines

run this program under the command line:

#php hello_world.php
Hello World!
#

Have fun!

1.4. Using phpgo under fast-cgi mode

phpgo can be used under fast-cgi (php-fpm) mode, following are the steps:

Make libgo preloaded

You need to modify your php-fpm service management script (/etc/init.d/php-fpm), add the following line to the /etc/init.d/php-fpm at the very begining of the "start)" section:

export LD_PRELOAD=liblibgo.so

after your modification, the file should look like the following:

/etc/init.d/php-fpm:
...
case "$1" in
start)
echo -n "Starting php-fpm - with libgo preloaded"
export LD_PRELOAD=liblibgo.so
$php_fpm_BIN --daemonize $php_opts
if [ "$?" != 0 ] ; then
echo " failed"
exit 1
fi
...

then issue a "service php-fpm reload" to make the modification take effect

#service php-fpm reload

The reason to do that is for you to obtain the capability that allows the swithing of execution to another go routine while a go routine is I/O blocked, the LD_PRELOAD=liblibgo.so does the trick. For more information, see the dedicated section below that describes the details of what libgo has done for this capability, why the LD_PRELOAD is needed and how it functions.

Setup your go scheduler

A typical way to setup the go scheduler is to add the Scheduler::join() into the index.php

index.php:
use \go\Scheduler
...
your existing code which typically boots up a framework(e.g, laravel) who in turns runs your web service
...
Scheduler::join(); // the last line

Feel free to use the phpgo capability in your web service code

The places that you most likely to use the phpgo functions/methods are the Models / Controllers. The following code demonstrates a uses case where an API gateway consolidate a user's basic information, order placed, and browsing history and send back to the web broswer:

use \go\Scheduler;
...
function getUserDetailInfo(){
$userid = $_GET['userid']; $user_details = [];
$user_orders = [];
$user_browsing_history = [];
go(function(&$user_details){
$redis = new Redis();
$redis->connect(...);
$user_details = $redis->get( "user_details_of_" . $userid );
}, [&$user_details]);
go(function(&$user_orders){
$pdo = new PDO(...);
$user_orders = $pdo->query("select * from tb_order where userid = $userid");
}, [&$user_orders]);
go(function(&$user_browsing_history){
$curl = new Curl(...);
$user_browsing_history =
$curl->get("http://browsing.history.micro.service/path_to_the_browsing_history_query_api");
}, [&$user_browsing_history]);
Scheduler::join();
$result = array(
'user_details' = > $user_details,
'user_orders' => $user_orders,
'user_browsing_history' => $user_browsing_history,
);
echo json_encode($result);
}
...

The code above creates 3 go routines, which run in parallel getting the user basic information, order information and browsing history from redis, databases, and a microservice running http interface; the Scheduler::join() schedules and wait all the 3 go routines to finish running; then the code send back the consolidated result to the broswer

As we all know, due to the synchronized nature of php, in a php script all operations have to be exectued in sequence, in an API gateway that has a lot of interactions with other conter-parts, the total amount of execution time of a script can easily become unacceptable. By using phpgo, the amount of total execution time can reduce to the time of a single operation(given the operations are independent and can be executed in parallel)

2. LD_PRELOAD

to be updated...

3. Go Live

libgo supports using boost context for context switching (default context switching mechanism is u_context) which provides a much better coroutine switch performance (5+ times).

If you are using the phpgo under production environment, it's recommended that you enable the boost context switching by the steps below:

Firstly, you'll need to install boost 1.59.0+, I'll suggest you use 1.59.0, since libgo is using 1.59.0 in auto-integeration testing (as of today: 2018/5/25)

#wget https://sourceforge.net/projects/boost/files/boost/1.59.0/boost_1_59_0.tar.gz
#tar -xvf boost_1_59_0.tar.gz
#cd boost_1_59_0
#./bootstrap.sh
#./b2 -q install

Then, you'll need to add -DENABLE_BOOST_CONTEXT=ON option to the "cmake" command

#cd libgo/build
#rm -rf *
#cmake .. -DENABLE_BOOST_CONTEXT=ON
#make && make install

note: if you see compiler errors during the "make" step, make sure you've done the "rm -rf * " under the build directory

About

PHPGO: A php extension that brings into php the go core features: go routines, channel, select, mutex, waitgroup, timer and scheduler... now supports php5.5 to 7.2 on linux, for both cli and fastcgi, zts and non-zts mode usage

Resources

Stars

94 stars

Watchers

7 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

996.icuLICENSE

phpgo

phpgo's mission is to provide a small, simple, stable extension for existing and future PHP applications for much higher concurrency, better performance, with lower resouce consumption and work well with most of the existing php features, extensions and frameworks

phpgo: A php extension that brings into php the go core features:

  • go routine
  • channel
  • select
  • mutex
  • waitgroup
  • timer
  • go routine scheduler

phpgo also brings in a break-through feature which:

  • automatically converts the synchronized function calls in the php extensions (e.g. PDO, redis... etc) into asynchronized

This allows the swithing of execution to another go routine if one go routine is blocked by blocking I/O, thus provides hundred to thousand times of concurrent executions under the same running environment

phpgo can be used under both CLI mode and fast-cgi (php-fpm) mode

phpgo supports php5.4 to 7.2 on linux as of today

0. Reference Manuals

1. Getting started

1.1. Install libgo

The phpgo relies on the the libgo library (thanks libgo!) to provide the underlying coroutine capability, which includes:

  • coroutine creation, execution and scheduling
  • coroutine local storage
  • coroutine listener with the task swap hook capability
  • go channel
  • go mutex
  • hook of system calls (thus allow corroutine switching during blocking system call)

(libgo contains more excellent features and you may want to check them out @ https://github.com/yyzybb537/libgo )

steps to install the libgo:

git clone https://github.com/yyzybb537/libgo
cd libgo
git checkout master
git pull
git reset --hard c280e6170a7d7bd124d98a8062cb47989f9ae4cd #use a compatible version of libgo
mkdir build
cd build
rm -rf *
cmake ..
make
make install
ldconfig

1.2. Build phpgo from source - supported on linux OS

steps to build phpgo:

git clone https://github.com/birdwyx/phpgo
cd phpgo
phpize
./configure -with-php-config=<the path to php-config>
make
make install

you may probably want to do a test first to ensure everything is fine before start using phpgo

cd phpgo
export TEST_PHP_EXECUTABLE=./test_php
php run-tests.php tests

ensure there are no FAIL'ed test cases

then, add the following line into the php.ini

extension=phpgo.so

1.3. First phpgo program

hello_world.php:

<?php
use \go\Scheduler; //for the Scheduler functions go(function(){ //creates a go routine
echo "Hello World!" . PHP_EOL;
});
Scheduler::join(); //execute all go routines

run this program under the command line:

#php hello_world.php
Hello World!
#

Have fun!

1.4. Using phpgo under fast-cgi mode

phpgo can be used under fast-cgi (php-fpm) mode, following are the steps:

Make libgo preloaded

You need to modify your php-fpm service management script (/etc/init.d/php-fpm), add the following line to the /etc/init.d/php-fpm at the very begining of the "start)" section:

export LD_PRELOAD=liblibgo.so

after your modification, the file should look like the following:

/etc/init.d/php-fpm:
...
case "$1" in
start)
echo -n "Starting php-fpm - with libgo preloaded"
export LD_PRELOAD=liblibgo.so
$php_fpm_BIN --daemonize $php_opts
if [ "$?" != 0 ] ; then
echo " failed"
exit 1
fi
...

then issue a "service php-fpm reload" to make the modification take effect

#service php-fpm reload

The reason to do that is for you to obtain the capability that allows the swithing of execution to another go routine while a go routine is I/O blocked, the LD_PRELOAD=liblibgo.so does the trick. For more information, see the dedicated section below that describes the details of what libgo has done for this capability, why the LD_PRELOAD is needed and how it functions.

Setup your go scheduler

A typical way to setup the go scheduler is to add the Scheduler::join() into the index.php

index.php:
use \go\Scheduler
...
your existing code which typically boots up a framework(e.g, laravel) who in turns runs your web service
...
Scheduler::join(); // the last line

Feel free to use the phpgo capability in your web service code

The places that you most likely to use the phpgo functions/methods are the Models / Controllers. The following code demonstrates a uses case where an API gateway consolidate a user's basic information, order placed, and browsing history and send back to the web broswer:

use \go\Scheduler;
...
function getUserDetailInfo(){
$userid = $_GET['userid']; $user_details = [];
$user_orders = [];
$user_browsing_history = [];
go(function(&$user_details){
$redis = new Redis();
$redis->connect(...);
$user_details = $redis->get( "user_details_of_" . $userid );
}, [&$user_details]);
go(function(&$user_orders){
$pdo = new PDO(...);
$user_orders = $pdo->query("select * from tb_order where userid = $userid");
}, [&$user_orders]);
go(function(&$user_browsing_history){
$curl = new Curl(...);
$user_browsing_history =
$curl->get("http://browsing.history.micro.service/path_to_the_browsing_history_query_api");
}, [&$user_browsing_history]);
Scheduler::join();
$result = array(
'user_details' = > $user_details,
'user_orders' => $user_orders,
'user_browsing_history' => $user_browsing_history,
);
echo json_encode($result);
}
...

The code above creates 3 go routines, which run in parallel getting the user basic information, order information and browsing history from redis, databases, and a microservice running http interface; the Scheduler::join() schedules and wait all the 3 go routines to finish running; then the code send back the consolidated result to the broswer

As we all know, due to the synchronized nature of php, in a php script all operations have to be exectued in sequence, in an API gateway that has a lot of interactions with other conter-parts, the total amount of execution time of a script can easily become unacceptable. By using phpgo, the amount of total execution time can reduce to the time of a single operation(given the operations are independent and can be executed in parallel)

2. LD_PRELOAD

to be updated...

3. Go Live

libgo supports using boost context for context switching (default context switching mechanism is u_context) which provides a much better coroutine switch performance (5+ times).

If you are using the phpgo under production environment, it's recommended that you enable the boost context switching by the steps below:

Firstly, you'll need to install boost 1.59.0+, I'll suggest you use 1.59.0, since libgo is using 1.59.0 in auto-integeration testing (as of today: 2018/5/25)

#wget https://sourceforge.net/projects/boost/files/boost/1.59.0/boost_1_59_0.tar.gz
#tar -xvf boost_1_59_0.tar.gz
#cd boost_1_59_0
#./bootstrap.sh
#./b2 -q install

Then, you'll need to add -DENABLE_BOOST_CONTEXT=ON option to the "cmake" command

#cd libgo/build
#rm -rf *
#cmake .. -DENABLE_BOOST_CONTEXT=ON
#make && make install

note: if you see compiler errors during the "make" step, make sure you've done the "rm -rf * " under the build directory

About

PHPGO: A php extension that brings into php the go core features: go routines, channel, select, mutex, waitgroup, timer and scheduler... now supports php5.5 to 7.2 on linux, for both cli and fastcgi, zts and non-zts mode usage

Resources

Stars

94 stars

Watchers

7 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

996.icuLICENSE

phpgo

phpgo's mission is to provide a small, simple, stable extension for existing and future PHP applications for much higher concurrency, better performance, with lower resouce consumption and work well with most of the existing php features, extensions and frameworks

phpgo: A php extension that brings into php the go core features:

  • go routine
  • channel
  • select
  • mutex
  • waitgroup
  • timer
  • go routine scheduler

phpgo also brings in a break-through feature which:

  • automatically converts the synchronized function calls in the php extensions (e.g. PDO, redis... etc) into asynchronized

This allows the swithing of execution to another go routine if one go routine is blocked by blocking I/O, thus provides hundred to thousand times of concurrent executions under the same running environment

phpgo can be used under both CLI mode and fast-cgi (php-fpm) mode

phpgo supports php5.4 to 7.2 on linux as of today

0. Reference Manuals

1. Getting started

1.1. Install libgo

The phpgo relies on the the libgo library (thanks libgo!) to provide the underlying coroutine capability, which includes:

  • coroutine creation, execution and scheduling
  • coroutine local storage
  • coroutine listener with the task swap hook capability
  • go channel
  • go mutex
  • hook of system calls (thus allow corroutine switching during blocking system call)

(libgo contains more excellent features and you may want to check them out @ https://github.com/yyzybb537/libgo )

steps to install the libgo:

git clone https://github.com/yyzybb537/libgo
cd libgo
git checkout master
git pull
git reset --hard c280e6170a7d7bd124d98a8062cb47989f9ae4cd #use a compatible version of libgo
mkdir build
cd build
rm -rf *
cmake ..
make
make install
ldconfig

1.2. Build phpgo from source - supported on linux OS

steps to build phpgo:

git clone https://github.com/birdwyx/phpgo
cd phpgo
phpize
./configure -with-php-config=<the path to php-config>
make
make install

you may probably want to do a test first to ensure everything is fine before start using phpgo

cd phpgo
export TEST_PHP_EXECUTABLE=./test_php
php run-tests.php tests

ensure there are no FAIL'ed test cases

then, add the following line into the php.ini

extension=phpgo.so

1.3. First phpgo program

hello_world.php:

<?php
use \go\Scheduler; //for the Scheduler functions go(function(){ //creates a go routine
echo "Hello World!" . PHP_EOL;
});
Scheduler::join(); //execute all go routines

run this program under the command line:

#php hello_world.php
Hello World!
#

Have fun!

1.4. Using phpgo under fast-cgi mode

phpgo can be used under fast-cgi (php-fpm) mode, following are the steps:

Make libgo preloaded

You need to modify your php-fpm service management script (/etc/init.d/php-fpm), add the following line to the /etc/init.d/php-fpm at the very begining of the "start)" section:

export LD_PRELOAD=liblibgo.so

after your modification, the file should look like the following:

/etc/init.d/php-fpm:
...
case "$1" in
start)
echo -n "Starting php-fpm - with libgo preloaded"
export LD_PRELOAD=liblibgo.so
$php_fpm_BIN --daemonize $php_opts
if [ "$?" != 0 ] ; then
echo " failed"
exit 1
fi
...

then issue a "service php-fpm reload" to make the modification take effect

#service php-fpm reload

The reason to do that is for you to obtain the capability that allows the swithing of execution to another go routine while a go routine is I/O blocked, the LD_PRELOAD=liblibgo.so does the trick. For more information, see the dedicated section below that describes the details of what libgo has done for this capability, why the LD_PRELOAD is needed and how it functions.

Setup your go scheduler

A typical way to setup the go scheduler is to add the Scheduler::join() into the index.php

index.php:
use \go\Scheduler
...
your existing code which typically boots up a framework(e.g, laravel) who in turns runs your web service
...
Scheduler::join(); // the last line

Feel free to use the phpgo capability in your web service code

The places that you most likely to use the phpgo functions/methods are the Models / Controllers. The following code demonstrates a uses case where an API gateway consolidate a user's basic information, order placed, and browsing history and send back to the web broswer:

use \go\Scheduler;
...
function getUserDetailInfo(){
$userid = $_GET['userid']; $user_details = [];
$user_orders = [];
$user_browsing_history = [];
go(function(&$user_details){
$redis = new Redis();
$redis->connect(...);
$user_details = $redis->get( "user_details_of_" . $userid );
}, [&$user_details]);
go(function(&$user_orders){
$pdo = new PDO(...);
$user_orders = $pdo->query("select * from tb_order where userid = $userid");
}, [&$user_orders]);
go(function(&$user_browsing_history){
$curl = new Curl(...);
$user_browsing_history =
$curl->get("http://browsing.history.micro.service/path_to_the_browsing_history_query_api");
}, [&$user_browsing_history]);
Scheduler::join();
$result = array(
'user_details' = > $user_details,
'user_orders' => $user_orders,
'user_browsing_history' => $user_browsing_history,
);
echo json_encode($result);
}
...

The code above creates 3 go routines, which run in parallel getting the user basic information, order information and browsing history from redis, databases, and a microservice running http interface; the Scheduler::join() schedules and wait all the 3 go routines to finish running; then the code send back the consolidated result to the broswer

As we all know, due to the synchronized nature of php, in a php script all operations have to be exectued in sequence, in an API gateway that has a lot of interactions with other conter-parts, the total amount of execution time of a script can easily become unacceptable. By using phpgo, the amount of total execution time can reduce to the time of a single operation(given the operations are independent and can be executed in parallel)

2. LD_PRELOAD

to be updated...

3. Go Live

libgo supports using boost context for context switching (default context switching mechanism is u_context) which provides a much better coroutine switch performance (5+ times).

If you are using the phpgo under production environment, it's recommended that you enable the boost context switching by the steps below:

Firstly, you'll need to install boost 1.59.0+, I'll suggest you use 1.59.0, since libgo is using 1.59.0 in auto-integeration testing (as of today: 2018/5/25)

#wget https://sourceforge.net/projects/boost/files/boost/1.59.0/boost_1_59_0.tar.gz
#tar -xvf boost_1_59_0.tar.gz
#cd boost_1_59_0
#./bootstrap.sh
#./b2 -q install

Then, you'll need to add -DENABLE_BOOST_CONTEXT=ON option to the "cmake" command

#cd libgo/build
#rm -rf *
#cmake .. -DENABLE_BOOST_CONTEXT=ON
#make && make install

note: if you see compiler errors during the "make" step, make sure you've done the "rm -rf * " under the build directory

About

PHPGO: A php extension that brings into php the go core features: go routines, channel, select, mutex, waitgroup, timer and scheduler... now supports php5.5 to 7.2 on linux, for both cli and fastcgi, zts and non-zts mode usage

Resources

Stars

94 stars

Watchers

7 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

996.icuLICENSE

phpgo

phpgo's mission is to provide a small, simple, stable extension for existing and future PHP applications for much higher concurrency, better performance, with lower resouce consumption and work well with most of the existing php features, extensions and frameworks

phpgo: A php extension that brings into php the go core features:

  • go routine
  • channel
  • select
  • mutex
  • waitgroup
  • timer
  • go routine scheduler

phpgo also brings in a break-through feature which:

  • automatically converts the synchronized function calls in the php extensions (e.g. PDO, redis... etc) into asynchronized

This allows the swithing of execution to another go routine if one go routine is blocked by blocking I/O, thus provides hundred to thousand times of concurrent executions under the same running environment

phpgo can be used under both CLI mode and fast-cgi (php-fpm) mode

phpgo supports php5.4 to 7.2 on linux as of today

0. Reference Manuals

1. Getting started

1.1. Install libgo

The phpgo relies on the the libgo library (thanks libgo!) to provide the underlying coroutine capability, which includes:

  • coroutine creation, execution and scheduling
  • coroutine local storage
  • coroutine listener with the task swap hook capability
  • go channel
  • go mutex
  • hook of system calls (thus allow corroutine switching during blocking system call)

(libgo contains more excellent features and you may want to check them out @ https://github.com/yyzybb537/libgo )

steps to install the libgo:

git clone https://github.com/yyzybb537/libgo
cd libgo
git checkout master
git pull
git reset --hard c280e6170a7d7bd124d98a8062cb47989f9ae4cd #use a compatible version of libgo
mkdir build
cd build
rm -rf *
cmake ..
make
make install
ldconfig

1.2. Build phpgo from source - supported on linux OS

steps to build phpgo:

git clone https://github.com/birdwyx/phpgo
cd phpgo
phpize
./configure -with-php-config=<the path to php-config>
make
make install

you may probably want to do a test first to ensure everything is fine before start using phpgo

cd phpgo
export TEST_PHP_EXECUTABLE=./test_php
php run-tests.php tests

ensure there are no FAIL'ed test cases

then, add the following line into the php.ini

extension=phpgo.so

1.3. First phpgo program

hello_world.php:

<?php
use \go\Scheduler; //for the Scheduler functions go(function(){ //creates a go routine
echo "Hello World!" . PHP_EOL;
});
Scheduler::join(); //execute all go routines

run this program under the command line:

#php hello_world.php
Hello World!
#

Have fun!

1.4. Using phpgo under fast-cgi mode

phpgo can be used under fast-cgi (php-fpm) mode, following are the steps:

Make libgo preloaded

You need to modify your php-fpm service management script (/etc/init.d/php-fpm), add the following line to the /etc/init.d/php-fpm at the very begining of the "start)" section:

export LD_PRELOAD=liblibgo.so

after your modification, the file should look like the following:

/etc/init.d/php-fpm:
...
case "$1" in
start)
echo -n "Starting php-fpm - with libgo preloaded"
export LD_PRELOAD=liblibgo.so
$php_fpm_BIN --daemonize $php_opts
if [ "$?" != 0 ] ; then
echo " failed"
exit 1
fi
...

then issue a "service php-fpm reload" to make the modification take effect

#service php-fpm reload

The reason to do that is for you to obtain the capability that allows the swithing of execution to another go routine while a go routine is I/O blocked, the LD_PRELOAD=liblibgo.so does the trick. For more information, see the dedicated section below that describes the details of what libgo has done for this capability, why the LD_PRELOAD is needed and how it functions.

Setup your go scheduler

A typical way to setup the go scheduler is to add the Scheduler::join() into the index.php

index.php:
use \go\Scheduler
...
your existing code which typically boots up a framework(e.g, laravel) who in turns runs your web service
...
Scheduler::join(); // the last line

Feel free to use the phpgo capability in your web service code

The places that you most likely to use the phpgo functions/methods are the Models / Controllers. The following code demonstrates a uses case where an API gateway consolidate a user's basic information, order placed, and browsing history and send back to the web broswer:

use \go\Scheduler;
...
function getUserDetailInfo(){
$userid = $_GET['userid']; $user_details = [];
$user_orders = [];
$user_browsing_history = [];
go(function(&$user_details){
$redis = new Redis();
$redis->connect(...);
$user_details = $redis->get( "user_details_of_" . $userid );
}, [&$user_details]);
go(function(&$user_orders){
$pdo = new PDO(...);
$user_orders = $pdo->query("select * from tb_order where userid = $userid");
}, [&$user_orders]);
go(function(&$user_browsing_history){
$curl = new Curl(...);
$user_browsing_history =
$curl->get("http://browsing.history.micro.service/path_to_the_browsing_history_query_api");
}, [&$user_browsing_history]);
Scheduler::join();
$result = array(
'user_details' = > $user_details,
'user_orders' => $user_orders,
'user_browsing_history' => $user_browsing_history,
);
echo json_encode($result);
}
...

The code above creates 3 go routines, which run in parallel getting the user basic information, order information and browsing history from redis, databases, and a microservice running http interface; the Scheduler::join() schedules and wait all the 3 go routines to finish running; then the code send back the consolidated result to the broswer

As we all know, due to the synchronized nature of php, in a php script all operations have to be exectued in sequence, in an API gateway that has a lot of interactions with other conter-parts, the total amount of execution time of a script can easily become unacceptable. By using phpgo, the amount of total execution time can reduce to the time of a single operation(given the operations are independent and can be executed in parallel)

2. LD_PRELOAD

to be updated...

3. Go Live

libgo supports using boost context for context switching (default context switching mechanism is u_context) which provides a much better coroutine switch performance (5+ times).

If you are using the phpgo under production environment, it's recommended that you enable the boost context switching by the steps below:

Firstly, you'll need to install boost 1.59.0+, I'll suggest you use 1.59.0, since libgo is using 1.59.0 in auto-integeration testing (as of today: 2018/5/25)

#wget https://sourceforge.net/projects/boost/files/boost/1.59.0/boost_1_59_0.tar.gz
#tar -xvf boost_1_59_0.tar.gz
#cd boost_1_59_0
#./bootstrap.sh
#./b2 -q install

Then, you'll need to add -DENABLE_BOOST_CONTEXT=ON option to the "cmake" command

#cd libgo/build
#rm -rf *
#cmake .. -DENABLE_BOOST_CONTEXT=ON
#make && make install

note: if you see compiler errors during the "make" step, make sure you've done the "rm -rf * " under the build directory

About

PHPGO: A php extension that brings into php the go core features: go routines, channel, select, mutex, waitgroup, timer and scheduler... now supports php5.5 to 7.2 on linux, for both cli and fastcgi, zts and non-zts mode usage

Resources

Stars

94 stars

Watchers

7 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

996.icuLICENSE

phpgo

phpgo's mission is to provide a small, simple, stable extension for existing and future PHP applications for much higher concurrency, better performance, with lower resouce consumption and work well with most of the existing php features, extensions and frameworks

phpgo: A php extension that brings into php the go core features:

  • go routine
  • channel
  • select
  • mutex
  • waitgroup
  • timer
  • go routine scheduler

phpgo also brings in a break-through feature which:

  • automatically converts the synchronized function calls in the php extensions (e.g. PDO, redis... etc) into asynchronized

This allows the swithing of execution to another go routine if one go routine is blocked by blocking I/O, thus provides hundred to thousand times of concurrent executions under the same running environment

phpgo can be used under both CLI mode and fast-cgi (php-fpm) mode

phpgo supports php5.4 to 7.2 on linux as of today

0. Reference Manuals

1. Getting started

1.1. Install libgo

The phpgo relies on the the libgo library (thanks libgo!) to provide the underlying coroutine capability, which includes:

  • coroutine creation, execution and scheduling
  • coroutine local storage
  • coroutine listener with the task swap hook capability
  • go channel
  • go mutex
  • hook of system calls (thus allow corroutine switching during blocking system call)

(libgo contains more excellent features and you may want to check them out @ https://github.com/yyzybb537/libgo )

steps to install the libgo:

git clone https://github.com/yyzybb537/libgo
cd libgo
git checkout master
git pull
git reset --hard c280e6170a7d7bd124d98a8062cb47989f9ae4cd #use a compatible version of libgo
mkdir build
cd build
rm -rf *
cmake ..
make
make install
ldconfig

1.2. Build phpgo from source - supported on linux OS

steps to build phpgo:

git clone https://github.com/birdwyx/phpgo
cd phpgo
phpize
./configure -with-php-config=<the path to php-config>
make
make install

you may probably want to do a test first to ensure everything is fine before start using phpgo

cd phpgo
export TEST_PHP_EXECUTABLE=./test_php
php run-tests.php tests

ensure there are no FAIL'ed test cases

then, add the following line into the php.ini

extension=phpgo.so

1.3. First phpgo program

hello_world.php:

<?php
use \go\Scheduler; //for the Scheduler functions go(function(){ //creates a go routine
echo "Hello World!" . PHP_EOL;
});
Scheduler::join(); //execute all go routines

run this program under the command line:

#php hello_world.php
Hello World!
#

Have fun!

1.4. Using phpgo under fast-cgi mode

phpgo can be used under fast-cgi (php-fpm) mode, following are the steps:

Make libgo preloaded

You need to modify your php-fpm service management script (/etc/init.d/php-fpm), add the following line to the /etc/init.d/php-fpm at the very begining of the "start)" section:

export LD_PRELOAD=liblibgo.so

after your modification, the file should look like the following:

/etc/init.d/php-fpm:
...
case "$1" in
start)
echo -n "Starting php-fpm - with libgo preloaded"
export LD_PRELOAD=liblibgo.so
$php_fpm_BIN --daemonize $php_opts
if [ "$?" != 0 ] ; then
echo " failed"
exit 1
fi
...

then issue a "service php-fpm reload" to make the modification take effect

#service php-fpm reload

The reason to do that is for you to obtain the capability that allows the swithing of execution to another go routine while a go routine is I/O blocked, the LD_PRELOAD=liblibgo.so does the trick. For more information, see the dedicated section below that describes the details of what libgo has done for this capability, why the LD_PRELOAD is needed and how it functions.

Setup your go scheduler

A typical way to setup the go scheduler is to add the Scheduler::join() into the index.php

index.php:
use \go\Scheduler
...
your existing code which typically boots up a framework(e.g, laravel) who in turns runs your web service
...
Scheduler::join(); // the last line

Feel free to use the phpgo capability in your web service code

The places that you most likely to use the phpgo functions/methods are the Models / Controllers. The following code demonstrates a uses case where an API gateway consolidate a user's basic information, order placed, and browsing history and send back to the web broswer:

use \go\Scheduler;
...
function getUserDetailInfo(){
$userid = $_GET['userid']; $user_details = [];
$user_orders = [];
$user_browsing_history = [];
go(function(&$user_details){
$redis = new Redis();
$redis->connect(...);
$user_details = $redis->get( "user_details_of_" . $userid );
}, [&$user_details]);
go(function(&$user_orders){
$pdo = new PDO(...);
$user_orders = $pdo->query("select * from tb_order where userid = $userid");
}, [&$user_orders]);
go(function(&$user_browsing_history){
$curl = new Curl(...);
$user_browsing_history =
$curl->get("http://browsing.history.micro.service/path_to_the_browsing_history_query_api");
}, [&$user_browsing_history]);
Scheduler::join();
$result = array(
'user_details' = > $user_details,
'user_orders' => $user_orders,
'user_browsing_history' => $user_browsing_history,
);
echo json_encode($result);
}
...

The code above creates 3 go routines, which run in parallel getting the user basic information, order information and browsing history from redis, databases, and a microservice running http interface; the Scheduler::join() schedules and wait all the 3 go routines to finish running; then the code send back the consolidated result to the broswer

As we all know, due to the synchronized nature of php, in a php script all operations have to be exectued in sequence, in an API gateway that has a lot of interactions with other conter-parts, the total amount of execution time of a script can easily become unacceptable. By using phpgo, the amount of total execution time can reduce to the time of a single operation(given the operations are independent and can be executed in parallel)

2. LD_PRELOAD

to be updated...

3. Go Live

libgo supports using boost context for context switching (default context switching mechanism is u_context) which provides a much better coroutine switch performance (5+ times).

If you are using the phpgo under production environment, it's recommended that you enable the boost context switching by the steps below:

Firstly, you'll need to install boost 1.59.0+, I'll suggest you use 1.59.0, since libgo is using 1.59.0 in auto-integeration testing (as of today: 2018/5/25)

#wget https://sourceforge.net/projects/boost/files/boost/1.59.0/boost_1_59_0.tar.gz
#tar -xvf boost_1_59_0.tar.gz
#cd boost_1_59_0
#./bootstrap.sh
#./b2 -q install

Then, you'll need to add -DENABLE_BOOST_CONTEXT=ON option to the "cmake" command

#cd libgo/build
#rm -rf *
#cmake .. -DENABLE_BOOST_CONTEXT=ON
#make && make install

note: if you see compiler errors during the "make" step, make sure you've done the "rm -rf * " under the build directory

About

PHPGO: A php extension that brings into php the go core features: go routines, channel, select, mutex, waitgroup, timer and scheduler... now supports php5.5 to 7.2 on linux, for both cli and fastcgi, zts and non-zts mode usage

Resources

Stars

94 stars

Watchers

7 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

996.icuLICENSE

phpgo

phpgo's mission is to provide a small, simple, stable extension for existing and future PHP applications for much higher concurrency, better performance, with lower resouce consumption and work well with most of the existing php features, extensions and frameworks

phpgo: A php extension that brings into php the go core features:

  • go routine
  • channel
  • select
  • mutex
  • waitgroup
  • timer
  • go routine scheduler

phpgo also brings in a break-through feature which:

  • automatically converts the synchronized function calls in the php extensions (e.g. PDO, redis... etc) into asynchronized

This allows the swithing of execution to another go routine if one go routine is blocked by blocking I/O, thus provides hundred to thousand times of concurrent executions under the same running environment

phpgo can be used under both CLI mode and fast-cgi (php-fpm) mode

phpgo supports php5.4 to 7.2 on linux as of today

0. Reference Manuals

1. Getting started

1.1. Install libgo

The phpgo relies on the the libgo library (thanks libgo!) to provide the underlying coroutine capability, which includes:

  • coroutine creation, execution and scheduling
  • coroutine local storage
  • coroutine listener with the task swap hook capability
  • go channel
  • go mutex
  • hook of system calls (thus allow corroutine switching during blocking system call)

(libgo contains more excellent features and you may want to check them out @ https://github.com/yyzybb537/libgo )

steps to install the libgo:

git clone https://github.com/yyzybb537/libgo
cd libgo
git checkout master
git pull
git reset --hard c280e6170a7d7bd124d98a8062cb47989f9ae4cd #use a compatible version of libgo
mkdir build
cd build
rm -rf *
cmake ..
make
make install
ldconfig

1.2. Build phpgo from source - supported on linux OS

steps to build phpgo:

git clone https://github.com/birdwyx/phpgo
cd phpgo
phpize
./configure -with-php-config=<the path to php-config>
make
make install

you may probably want to do a test first to ensure everything is fine before start using phpgo

cd phpgo
export TEST_PHP_EXECUTABLE=./test_php
php run-tests.php tests

ensure there are no FAIL'ed test cases

then, add the following line into the php.ini

extension=phpgo.so

1.3. First phpgo program

hello_world.php:

<?php
use \go\Scheduler; //for the Scheduler functions go(function(){ //creates a go routine
echo "Hello World!" . PHP_EOL;
});
Scheduler::join(); //execute all go routines

run this program under the command line:

#php hello_world.php
Hello World!
#

Have fun!

1.4. Using phpgo under fast-cgi mode

phpgo can be used under fast-cgi (php-fpm) mode, following are the steps:

Make libgo preloaded

You need to modify your php-fpm service management script (/etc/init.d/php-fpm), add the following line to the /etc/init.d/php-fpm at the very begining of the "start)" section:

export LD_PRELOAD=liblibgo.so

after your modification, the file should look like the following:

/etc/init.d/php-fpm:
...
case "$1" in
start)
echo -n "Starting php-fpm - with libgo preloaded"
export LD_PRELOAD=liblibgo.so
$php_fpm_BIN --daemonize $php_opts
if [ "$?" != 0 ] ; then
echo " failed"
exit 1
fi
...

then issue a "service php-fpm reload" to make the modification take effect

#service php-fpm reload

The reason to do that is for you to obtain the capability that allows the swithing of execution to another go routine while a go routine is I/O blocked, the LD_PRELOAD=liblibgo.so does the trick. For more information, see the dedicated section below that describes the details of what libgo has done for this capability, why the LD_PRELOAD is needed and how it functions.

Setup your go scheduler

A typical way to setup the go scheduler is to add the Scheduler::join() into the index.php

index.php:
use \go\Scheduler
...
your existing code which typically boots up a framework(e.g, laravel) who in turns runs your web service
...
Scheduler::join(); // the last line

Feel free to use the phpgo capability in your web service code

The places that you most likely to use the phpgo functions/methods are the Models / Controllers. The following code demonstrates a uses case where an API gateway consolidate a user's basic information, order placed, and browsing history and send back to the web broswer:

use \go\Scheduler;
...
function getUserDetailInfo(){
$userid = $_GET['userid']; $user_details = [];
$user_orders = [];
$user_browsing_history = [];
go(function(&$user_details){
$redis = new Redis();
$redis->connect(...);
$user_details = $redis->get( "user_details_of_" . $userid );
}, [&$user_details]);
go(function(&$user_orders){
$pdo = new PDO(...);
$user_orders = $pdo->query("select * from tb_order where userid = $userid");
}, [&$user_orders]);
go(function(&$user_browsing_history){
$curl = new Curl(...);
$user_browsing_history =
$curl->get("http://browsing.history.micro.service/path_to_the_browsing_history_query_api");
}, [&$user_browsing_history]);
Scheduler::join();
$result = array(
'user_details' = > $user_details,
'user_orders' => $user_orders,
'user_browsing_history' => $user_browsing_history,
);
echo json_encode($result);
}
...

The code above creates 3 go routines, which run in parallel getting the user basic information, order information and browsing history from redis, databases, and a microservice running http interface; the Scheduler::join() schedules and wait all the 3 go routines to finish running; then the code send back the consolidated result to the broswer

As we all know, due to the synchronized nature of php, in a php script all operations have to be exectued in sequence, in an API gateway that has a lot of interactions with other conter-parts, the total amount of execution time of a script can easily become unacceptable. By using phpgo, the amount of total execution time can reduce to the time of a single operation(given the operations are independent and can be executed in parallel)

2. LD_PRELOAD

to be updated...

3. Go Live

libgo supports using boost context for context switching (default context switching mechanism is u_context) which provides a much better coroutine switch performance (5+ times).

If you are using the phpgo under production environment, it's recommended that you enable the boost context switching by the steps below:

Firstly, you'll need to install boost 1.59.0+, I'll suggest you use 1.59.0, since libgo is using 1.59.0 in auto-integeration testing (as of today: 2018/5/25)

#wget https://sourceforge.net/projects/boost/files/boost/1.59.0/boost_1_59_0.tar.gz
#tar -xvf boost_1_59_0.tar.gz
#cd boost_1_59_0
#./bootstrap.sh
#./b2 -q install

Then, you'll need to add -DENABLE_BOOST_CONTEXT=ON option to the "cmake" command

#cd libgo/build
#rm -rf *
#cmake .. -DENABLE_BOOST_CONTEXT=ON
#make && make install

note: if you see compiler errors during the "make" step, make sure you've done the "rm -rf * " under the build directory

About

PHPGO: A php extension that brings into php the go core features: go routines, channel, select, mutex, waitgroup, timer and scheduler... now supports php5.5 to 7.2 on linux, for both cli and fastcgi, zts and non-zts mode usage

Resources

Stars

94 stars

Watchers

7 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

996.icuLICENSE

phpgo

phpgo's mission is to provide a small, simple, stable extension for existing and future PHP applications for much higher concurrency, better performance, with lower resouce consumption and work well with most of the existing php features, extensions and frameworks

phpgo: A php extension that brings into php the go core features:

  • go routine
  • channel
  • select
  • mutex
  • waitgroup
  • timer
  • go routine scheduler

phpgo also brings in a break-through feature which:

  • automatically converts the synchronized function calls in the php extensions (e.g. PDO, redis... etc) into asynchronized

This allows the swithing of execution to another go routine if one go routine is blocked by blocking I/O, thus provides hundred to thousand times of concurrent executions under the same running environment

phpgo can be used under both CLI mode and fast-cgi (php-fpm) mode

phpgo supports php5.4 to 7.2 on linux as of today

0. Reference Manuals

1. Getting started

1.1. Install libgo

The phpgo relies on the the libgo library (thanks libgo!) to provide the underlying coroutine capability, which includes:

  • coroutine creation, execution and scheduling
  • coroutine local storage
  • coroutine listener with the task swap hook capability
  • go channel
  • go mutex
  • hook of system calls (thus allow corroutine switching during blocking system call)

(libgo contains more excellent features and you may want to check them out @ https://github.com/yyzybb537/libgo )

steps to install the libgo:

git clone https://github.com/yyzybb537/libgo
cd libgo
git checkout master
git pull
git reset --hard c280e6170a7d7bd124d98a8062cb47989f9ae4cd #use a compatible version of libgo
mkdir build
cd build
rm -rf *
cmake ..
make
make install
ldconfig

1.2. Build phpgo from source - supported on linux OS

steps to build phpgo:

git clone https://github.com/birdwyx/phpgo
cd phpgo
phpize
./configure -with-php-config=<the path to php-config>
make
make install

you may probably want to do a test first to ensure everything is fine before start using phpgo

cd phpgo
export TEST_PHP_EXECUTABLE=./test_php
php run-tests.php tests

ensure there are no FAIL'ed test cases

then, add the following line into the php.ini

extension=phpgo.so

1.3. First phpgo program

hello_world.php:

<?php
use \go\Scheduler; //for the Scheduler functions go(function(){ //creates a go routine
echo "Hello World!" . PHP_EOL;
});
Scheduler::join(); //execute all go routines

run this program under the command line:

#php hello_world.php
Hello World!
#

Have fun!

1.4. Using phpgo under fast-cgi mode

phpgo can be used under fast-cgi (php-fpm) mode, following are the steps:

Make libgo preloaded

You need to modify your php-fpm service management script (/etc/init.d/php-fpm), add the following line to the /etc/init.d/php-fpm at the very begining of the "start)" section:

export LD_PRELOAD=liblibgo.so

after your modification, the file should look like the following:

/etc/init.d/php-fpm:
...
case "$1" in
start)
echo -n "Starting php-fpm - with libgo preloaded"
export LD_PRELOAD=liblibgo.so
$php_fpm_BIN --daemonize $php_opts
if [ "$?" != 0 ] ; then
echo " failed"
exit 1
fi
...

then issue a "service php-fpm reload" to make the modification take effect

#service php-fpm reload

The reason to do that is for you to obtain the capability that allows the swithing of execution to another go routine while a go routine is I/O blocked, the LD_PRELOAD=liblibgo.so does the trick. For more information, see the dedicated section below that describes the details of what libgo has done for this capability, why the LD_PRELOAD is needed and how it functions.

Setup your go scheduler

A typical way to setup the go scheduler is to add the Scheduler::join() into the index.php

index.php:
use \go\Scheduler
...
your existing code which typically boots up a framework(e.g, laravel) who in turns runs your web service
...
Scheduler::join(); // the last line

Feel free to use the phpgo capability in your web service code

The places that you most likely to use the phpgo functions/methods are the Models / Controllers. The following code demonstrates a uses case where an API gateway consolidate a user's basic information, order placed, and browsing history and send back to the web broswer:

use \go\Scheduler;
...
function getUserDetailInfo(){
$userid = $_GET['userid']; $user_details = [];
$user_orders = [];
$user_browsing_history = [];
go(function(&$user_details){
$redis = new Redis();
$redis->connect(...);
$user_details = $redis->get( "user_details_of_" . $userid );
}, [&$user_details]);
go(function(&$user_orders){
$pdo = new PDO(...);
$user_orders = $pdo->query("select * from tb_order where userid = $userid");
}, [&$user_orders]);
go(function(&$user_browsing_history){
$curl = new Curl(...);
$user_browsing_history =
$curl->get("http://browsing.history.micro.service/path_to_the_browsing_history_query_api");
}, [&$user_browsing_history]);
Scheduler::join();
$result = array(
'user_details' = > $user_details,
'user_orders' => $user_orders,
'user_browsing_history' => $user_browsing_history,
);
echo json_encode($result);
}
...

The code above creates 3 go routines, which run in parallel getting the user basic information, order information and browsing history from redis, databases, and a microservice running http interface; the Scheduler::join() schedules and wait all the 3 go routines to finish running; then the code send back the consolidated result to the broswer

As we all know, due to the synchronized nature of php, in a php script all operations have to be exectued in sequence, in an API gateway that has a lot of interactions with other conter-parts, the total amount of execution time of a script can easily become unacceptable. By using phpgo, the amount of total execution time can reduce to the time of a single operation(given the operations are independent and can be executed in parallel)

2. LD_PRELOAD

to be updated...

3. Go Live

libgo supports using boost context for context switching (default context switching mechanism is u_context) which provides a much better coroutine switch performance (5+ times).

If you are using the phpgo under production environment, it's recommended that you enable the boost context switching by the steps below:

Firstly, you'll need to install boost 1.59.0+, I'll suggest you use 1.59.0, since libgo is using 1.59.0 in auto-integeration testing (as of today: 2018/5/25)

#wget https://sourceforge.net/projects/boost/files/boost/1.59.0/boost_1_59_0.tar.gz
#tar -xvf boost_1_59_0.tar.gz
#cd boost_1_59_0
#./bootstrap.sh
#./b2 -q install

Then, you'll need to add -DENABLE_BOOST_CONTEXT=ON option to the "cmake" command

#cd libgo/build
#rm -rf *
#cmake .. -DENABLE_BOOST_CONTEXT=ON
#make && make install

note: if you see compiler errors during the "make" step, make sure you've done the "rm -rf * " under the build directory

About

PHPGO: A php extension that brings into php the go core features: go routines, channel, select, mutex, waitgroup, timer and scheduler... now supports php5.5 to 7.2 on linux, for both cli and fastcgi, zts and non-zts mode usage

Resources

Stars

94 stars

Watchers

7 watching

Forks

Releases

Packages

Contributors

Languages