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

Feature/parallelization #414

Merged
merged 20 commits into from
Oct 13, 2020
Merged

Conversation

Jibbarth
Copy link
Collaborator

@Jibbarth Jibbarth commented Jun 21, 2020

Q A
Bug fix? no
New feature? yes
Fixed tickets #390

This PR add parallelization feature.

No external dependencies added, I create a new hidden command 'internal:processors' that launch code sniffer and CS fixer on a list of files.

The runner create as much as it can be new processes for this new command by retrieving number of CPU core, and launch them in parallel.

The new command store all details and fixed issues in cache, then the runner load issues from cache.

Please note that is do only for CodeSniffer and CSFixer processors.

I cannot add Insights instances in cache because there is a problem to cache SplFileInfo (not serializable), so each process need to reinstance them.

Let's talk about performance now.

Gain without cache : https://blackfire.io/profiles/compare/21eebd42-e83c-4bb4-99ad-8e717f42e6e9/graph
=>
image

When cache is already set, I loose slight performance: https://blackfire.io/profiles/compare/6dd977d1-c140-4016-a536-f03274744eca/graph

Maybe should we didn't launch subprocess in this case.
Edit : We bypass now launching subprocess for files that are already in cache 👍


TODO :

  • Fix coding standards (phpstan etc.)
  • Add more tests ?
  • Document the new phpinsights.threads option (in stubs)
  • Test on laravel application, launched with artisan insights
  • Test on Windows (if someone can do the test for me ? 🤗)
  • ...

@Jibbarth Jibbarth added the enhancement New feature or request label Jun 21, 2020
@nunomaduro
Copy link
Owner

@50bhan Wanna review this one?

@50bhan
Copy link
Contributor

50bhan commented Jun 21, 2020

@nunomaduro Sure, I'll check it out tomorrow.

@50bhan
Copy link
Contributor

50bhan commented Jun 22, 2020

Perfect work @Jibbarth 👍 Really like the approach and implementation is clean as always. I have some comments though.

src/Domain/Runner.php Outdated Show resolved Hide resolved
@50bhan
Copy link
Contributor

50bhan commented Jun 22, 2020

Regarding performance, currently we are looking in cache for files at InternalProcessorCommand class. So if we move this check to Runner and before creation of processes, we don't need to create even useless processes. The code can be something like below image:

Screenshot from 2020-06-22 15-24-47

I did a test and you can check the result: https://blackfire.io/profiles/8dcc20f6-2435-4161-896e-92513fa2ece6/graph .

@Jibbarth
Copy link
Collaborator Author

@50bhan I had in mind to check if first file and last file had cache, but your idea is more clever 👍

@Jibbarth Jibbarth marked this pull request as ready for review September 6, 2020 11:35
@Jibbarth
Copy link
Collaborator Author

Jibbarth commented Sep 6, 2020

Anyone who use Windows can help me to test this PR ?

It's pretty simple :

On an other project

Launch this command to add the fork repository in composer

composer config repositories.phpinsights vcs https://github.com/jibbarth/phpinsights

Then require phpinsights on correct branch :

composer require nunomaduro/phpinsights:dev-feature/parallelization

On phpinsights repo

git remote add jibbarth [email protected]:Jibbarth/phpinsights.git
git fetch jibbarth
git checkout feature/parallelization

@ekvedaras
Copy link

I can test tomorrow on a bigger project. Will reply with the results

@ekvedaras
Copy link

ekvedaras commented Sep 7, 2020

Stable version

Finished in about 2 minutes

stable-version

I was unable to run parallelized version though.

In Process.php line 338:

[Symfony\Component\Process\Exception\RuntimeException]
Unable to launch a new process.

Exception trace:

at C:\Users\ekvedaras\AppData\Roaming\Composer\vendor\symfony\process\Process.php:338
Symfony\Component\Process\Process->start() at C:\Users\ekvedaras\AppData\Roaming\Composer\vendor\symfony\process\Process.php:232
Symfony\Component\Process\Process->run() at C:\Users\ekvedaras\AppData\Roaming\Composer\vendor\nunomaduro\phpinsights\src\Domain\Insights\SyntaxCheck.php:52
NunoMaduro\PhpInsights\Domain\Insights\SyntaxCheck->process() at C:\Users\ekvedaras\AppData\Roaming\Composer\vendor\nunomaduro\phpinsights\src\Domain\Runner.php:161
NunoMaduro\PhpInsights\Domain\Runner->run() at C:\Users\ekvedaras\AppData\Roaming\Composer\vendor\nunomaduro\phpinsights\src\Domain\Insights\InsightFactory.php:98
NunoMaduro\PhpInsights\Domain\Insights\InsightFactory->runInsightCollector() at C:\Users\ekvedaras\AppData\Roaming\Composer\vendor\nunomaduro\phpinsights\src\Domain\Insights\InsightFactory.php:69
NunoMaduro\PhpInsights\Domain\Insights\InsightFactory->makeFrom() at C:\Users\ekvedaras\AppData\Roaming\Composer\vendor\nunomaduro\phpinsights\src\Domain\Insights\InsightCollectionFactory.php:67
NunoMaduro\PhpInsights\Domain\Insights\InsightCollectionFactory::NunoMaduro\PhpInsights\Domain\Insights\{closure}() at n/a:n/a
array_map() at C:\Users\ekvedaras\AppData\Roaming\Composer\vendor\nunomaduro\phpinsights\src\Domain\Insights\InsightCollectionFactory.php:68
NunoMaduro\PhpInsights\Domain\Insights\InsightCollectionFactory->get() at C:\Users\ekvedaras\AppData\Roaming\Composer\vendor\nunomaduro\phpinsights\src\Application\Console\Analyser.php:36
NunoMaduro\PhpInsights\Application\Console\Analyser->analyse() at C:\Users\ekvedaras\AppData\Roaming\Composer\vendor\nunomaduro\phpinsights\src\Application\Console\Commands\AnalyseCommand.php:65
NunoMaduro\PhpInsights\Application\Console\Commands\AnalyseCommand->__invoke() at n/a:n/a
call_user_func() at C:\Users\ekvedaras\AppData\Roaming\Composer\vendor\nunomaduro\phpinsights\src\Application\Console\Commands\InvokableCommand.php:34
NunoMaduro\PhpInsights\Application\Console\Commands\InvokableCommand->execute() at C:\Users\ekvedaras\AppData\Roaming\Composer\vendor\symfony\console\Command\Command.php:255
Symfony\Component\Console\Command\Command->run() at C:\Users\ekvedaras\AppData\Roaming\Composer\vendor\symfony\console\Application.php:912
Symfony\Component\Console\Application->doRunCommand() at C:\Users\ekvedaras\AppData\Roaming\Composer\vendor\symfony\console\Application.php:264
Symfony\Component\Console\Application->doRun() at C:\Users\ekvedaras\AppData\Roaming\Composer\vendor\symfony\console\Application.php:140
Symfony\Component\Console\Application->run() at C:\Users\ekvedaras\AppData\Roaming\Composer\vendor\nunomaduro\phpinsights\bin\phpinsights:35
{closure}() at C:\Users\ekvedaras\AppData\Roaming\Composer\vendor\nunomaduro\phpinsights\bin\phpinsights:36

@ekvedaras
Copy link

I guess that project is just too big 😀 Tried to dump the syntax check command and run it manually.

Program 'php.exe' failed to run: The filename or extension is too longAt line:1 char:1
+ C:\php\php.exe "C:\Users\ekvedaras\AppData\Roaming\Composer\vendor\nu ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~.
At line:1 char:1
+ C:\php\php.exe "C:\Users\ekvedaras\AppData\Roaming\Composer\vendor\nu ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (:) [], ApplicationFailedException
    + FullyQualifiedErrorId : NativeCommandFailed

@ekvedaras
Copy link

Might be the culprit https://stackoverflow.com/a/29359348/3805289 . There is a limit on command length. Even when I try to paste the command to windows terminal it already warns about the command being longer then 5KiB.

@Jibbarth
Copy link
Collaborator Author

Jibbarth commented Sep 7, 2020

@ekvedaras Thanks you so much for testing this ! 🤗

If I understand, the bug came from the SyntaxCheck insight which was added in #373 ? Do you reproduce it on dev-master ?

Can you exclude the insight NunoMaduro\PhpInsights\Domain\Insights\SyntaxCheck in your phpinsights.php config file and recheck ?

You are probably right about command lenght, that's something we should care about 😕

@ekvedaras
Copy link

I tested again on a smaller project.

Stable version:
stable-version-mid-project

Parallel version:
parallel-version-mid-project

Not a supper big difference. The cached version ran instantly of course :)) My laptop was not completely idle, but I tried to close most of the apps.
Btw, not sure if relevant. But I saw it fetches the number of cores as 4. Would it make sense to fetch threads instead which is 8 ? Although it seemed like all threads were receiving load, so maybe that works.

@Jibbarth
Copy link
Collaborator Author

@ekvedaras You are right, we used wmic cpu get NumberOfCores to retrieve number of threads available, but I found wmic cpu get NumberOfLogicalProcessors that return the correct result (same results as on my Linux)

I also reduce size of args by passing array of files to analyze by thread in the cache, so we should no longer had problem about command size.

@ekvedaras
Copy link

Tried to run it again. Seems a lot faster actually. But I'm hitting this issue now. Event with --disable-security-check
image

@ekvedaras
Copy link

CPU

Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz

Base speed:	2,80 GHz
Sockets:	1
Cores:	4
Logical processors:	8

v1.14.0

v1-14

Time: 1m 48s

Parallel

parallel-new-version

Time: 28s

That's more like it 👍

@Jibbarth
Copy link
Collaborator Author

@ekvedaras Thanks you so much for helping me to test this feature 🙏

@50bhan @olivernybroe I think this PR is ready for review 😇

Copy link
Collaborator

@olivernybroe olivernybroe left a comment

Choose a reason for hiding this comment

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

Amazing work @Jibbarth!

Just tested it out locally and it worked perfectly fine on my mac.

I'll say this is ready now 🥇

And thanks to @ekvedaras for helping out on this 👍

@50bhan
Copy link
Contributor

50bhan commented Oct 13, 2020

Great job @Jibbarth 👍 I think everything looks great and ready to merge!

@olivernybroe
Copy link
Collaborator

Alright.

@Jibbarth You got green light to merge it in 👍

@Jibbarth Jibbarth merged commit 8517087 into nunomaduro:master Oct 13, 2020
@Jibbarth Jibbarth deleted the feature/parallelization branch October 13, 2020 11:08
@Jibbarth
Copy link
Collaborator Author

Thank you all 🙌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants