Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial implementation of benchmarks #60

Merged
merged 1 commit into from
Feb 5, 2018
Merged

Conversation

dbalabka
Copy link
Contributor

@dbalabka dbalabka commented Dec 20, 2017

I think it is important to see some benchmarks comparing with PDO due to pure PHP implementations usually are slow. It is important to know how much slower.
In case of the async driver, we can come up with a conclusion to use the async driver instead of PDO to get a performance boost by executing queries in an async way.

I'm proposing to run benchmarks right after each build to see the performance. Hope that in future PHP releases pure PHP driver implementation performance will be very close to PDO.

There is only one benchmark with simple query SELECT $n with following implementations:

  1. Sync execution using PDO
  2. Sync execution using AmpMySQL
  3. Async execution using AmpMySQL
  4. Async execution using AmpMySQL with connection pool

.travis.yml Outdated
@@ -69,6 +69,8 @@ before_script:
script:
- phpdbg -qrr vendor/bin/phpunit --coverage-text --coverage-clover build/logs/clover.xml
- PHP_CS_FIXER_IGNORE_ENV=1 php vendor/bin/php-cs-fixer --diff --dry-run -v fix
- chmod +x benchmarks/bin/php_no_xdebug
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just commit the file go Git with chmod +x and it will be fine. No need to run this each time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. Never used this feature :) Fixed

.travis.yml Outdated
@@ -69,6 +69,8 @@ before_script:
script:
- phpdbg -qrr vendor/bin/phpunit --coverage-text --coverage-clover build/logs/clover.xml
- PHP_CS_FIXER_IGNORE_ENV=1 php vendor/bin/php-cs-fixer --diff --dry-run -v fix
- chmod +x benchmarks/bin/php_no_xdebug
- PATH=$PATH:$(pwd)/benchmarks/bin vendor/bin/phpbench run --report=aggregate
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure we have to run that for each build job. It's probably better to have a matrix that separates builds which run (unit) tests and then only one job (one PHP version is enough) to run these benchmarks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Fully agree :)

foreach (range(1, $this->maxQueries) as $i) {
/** @var ResultSet $resultSet */
$resultSet = yield $connection->query("SELECT $i");
yield $resultSet->advance();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will fetch one row, while PDO fetches all rows.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Previously I have used fetchAll, but in the new version it's not available.

yield all(array_map(function ($resultSet) {
/** @var ResultSet $resultSet */
return $resultSet->advance();
}, $resultSets));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can leave of the all if you want, it will implicitly be applied if you yield an array of promises, but that's personal preference, just a hint if you didn't know.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. Not sure, but probably a previous version of amp had required all here. Cool, now much clearer.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, 1.x didn't allow yielding array of promises.

temporaryPath="$(mktemp -t php.XXXX).ini"

# Using awk to ensure that files ending without newlines do not lead to configuration error
php -i | grep "\.ini" | grep -o -e '\(/[a-z0-9._-]\+\)\+\.ini' | grep -v xdebug | xargs awk 'FNR==1{print ""}1' > "$temporaryPath"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no need for that on Travis at least:

- phpenv config-rm xdebug.ini || echo "No xdebug config."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you suggested, now I remove all configuration with -n, so think that there no need for this configuration anymore.

# Using awk to ensure that files ending without newlines do not lead to configuration error
php -i | grep "\.ini" | grep -o -e '\(/[a-z0-9._-]\+\)\+\.ini' | grep -v xdebug | xargs awk 'FNR==1{print ""}1' > "$temporaryPath"

php -n -c "$temporaryPath" -dopcache.enable_cli=1 -dzend.assertions=-1 "$@"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about just doing -n and not passing any config at all?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm... probably PDO might not work, but let try :)

composer.json Outdated
@@ -3,7 +3,8 @@
"description": "Asynchronous parallel Mysql client built on the Amp concurrency framework",
"require": {
"amphp/amp": "^2",
"amphp/socket": "^0.10"
"amphp/socket": "^0.10",
"phpbench/phpbench": "^0.13.0"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should go into require-dev, actually it's there, too, so delete it here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Probably during merge I have added this in both sections.

wait(call(function() {
$connection = $this->connectionPool;
/** @var ResultSet[] $resultSets */
$resultSets = yield all(array_map(function ($i) use ($connection) {
Copy link
Member

@trowski trowski Dec 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also benching creating the connections to the database. Priming the pool would give more realistic benchmarks for a running application doing queries simultaneously.

Copy link
Contributor Author

@dbalabka dbalabka Dec 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@trowski I already have faced with this problem. To avoid such situation I have added @Warmup(1) to create all needed connection during the first run and avoid connection overhead to be included in overall benchmark time.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I copy the body of benchAsyncQueriesUsingPool to init, it reduces the time for the benchmark relative to the others significantly. Can you explain what's going on there?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@trowski in nutshell PHPBench does not count the time that was spent during init execution.

To understand how it works need to describe how works Revs(revolutions), Iterations and BeforeMethods(read more http://phpbench.readthedocs.io/en/latest/writing-benchmarks.html)

During one Warmup(it is equivalent to one revolution) we create all needed connections in the pool(read more http://phpbench.readthedocs.io/en/latest/writing-benchmarks.html?highlight=Warmup)

@kelunik
Copy link
Member

kelunik commented Dec 21, 2017

@torinaki I think switching to stages could make the build way easier like https://travis-ci.org/FriendsOfPHP/PHP-CS-Fixer does it.

@dbalabka
Copy link
Contributor Author

dbalabka commented Jan 9, 2018

@kelunik I did a migration to stages. The only issue is that I can't get build green due to unstable test:
Amp\Mysql\Test\ConnectionPoolTest::testIdleConnectionsRemovedAfterTimeout
I see same failing test in master:
https://travis-ci.org/amphp/mysql/jobs/324452178
Also, it affects benchmark stage. It doesn't run because test stage is failing.

@dbalabka
Copy link
Contributor Author

dbalabka commented Feb 4, 2018

@kelunik, @trowski I have implemented stages. It works. Currently, benchmarks would not be started if tests are failing. I see there are some unstable tests in master. Probably it would be better to enable benchmarks to run always in spite of tests status. How do you think?

@kelunik
Copy link
Member

kelunik commented Feb 4, 2018

No, these tests should just be fixed.

Could you add your new directory to .php_cs.dist and adjust the code style accordingly, please?

Other than that, it looks pretty fine now. 👍

@dbalabka
Copy link
Contributor Author

dbalabka commented Feb 5, 2018

@kelunik done. Please check

@kelunik
Copy link
Member

kelunik commented Feb 5, 2018

Thanks!

@kelunik kelunik merged commit fd33e79 into amphp:master Feb 5, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants