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

Multiple PHPStan runs happening in parallel #80

Open
berniedurfee-renaissance opened this issue May 31, 2024 · 10 comments
Open

Multiple PHPStan runs happening in parallel #80

berniedurfee-renaissance opened this issue May 31, 2024 · 10 comments

Comments

@berniedurfee-renaissance

I have a similar issue to this (swordev/phpstan-vscode#11) when using this plugin.

I see many runs of PHPStan happening at the same time. Not sure if it's the same issue, but I don't see this issue on the command line.

I have max core usage for PHPStan set to 2 in my config:

parallel:
	maximumNumberOfProcesses: 2

Using PHPStan v1.11.1

vendor/bin/phpstan --version
PHPStan - PHP Static Analysis Tool 1.11.1
image
@SanderRonde
Copy link
Owner

In theory it should kill any running processes whenever a new one is spawned. I think it should be pretty easy to figure out where it goes wrong. If you open up vscode it should do a single check. If at that point you have many running processes then it's an issue with the config not being respected. If not then something might be going wrong with the killing of processes. Can you test that for me?

Something else it could also be: are you sure your config file is being used in the checks? You can verify by checking the logs of the extension in the output panel.

You can also run phpstan with the same command you see there to test out where it's going wrong.

@berniedurfee-renaissance
Copy link
Author

If I'm very careful not to save often, the extension behaves fine. It's if I'm working fast, making changes and hitting CMD+S often that the processes start to pile up and it bogs my machine down to a crawl with so many PHPStans running simultaneously.

I think the PHPStan worker processes take some time to die.

I see the 2s wait time for the main process to die, but that might not be enough in some instances.

Maybe keep a loop going to be sure the processes are dead? Also, maybe check the child (worker) processes of the main PHPStan process to be sure they're all dead before proceeding to fire up a new process?

@SanderRonde
Copy link
Owner

There is indeed a 2 second timer for the process to exit gracefully. But after that a SIGTERM is sent, after which a SIGKILL is sent if it's still not behaving. Only when either the process exits or it takes 10s to exit does the extension move on and spawn a new one. I could consider bumping the 10s, but I'm not too sure if the extension will be able to be of any use if PHPStan resists being killed.

I could maybe look at the children of the main process but implementing a process-tree crawler that works cross-platform is really hard in node. Every platform has different semantics around these things.

A simpler alternative might be to get PHPStan Pro which has a watch mode that's built into the process itself. Meaning it itself watches instead of an external program (my extension in this case) spawning processes and killing them. By doing so you'll also support the creator (not me btw, I don't get anything from this endorsement). This extension integrates with the Pro mode by showing the errors that Pro collects in your editor and by starting/stopping pro mode as you open your project.

Ideally I'd of course want to fix the issue but it seems to be worse on a mac (at least I haven't heard anyone report it on a windows/linux device yet) and I don't own a mac so I can't reproduce it.

@quazardous
Copy link

quazardous commented Jun 12, 2024

Hi,

I don't know if it's related but sometime phpstan starts piling up project scan.

The bar show "phpstan scanning file 123/1567" (or something like that).

But I do not want phpstan to start project scan (or maybe once at startup). My projects has 1500+ files and my phpstan runs in docker. Just scanning current file is fine but maybe it's a chain effect with the dependencies ?

When it happens vscode just end up crashing on memory usage...

PS: I was not able to make phpstan server work using phpstan@docker. is there some documentation about it ?

EDIT: I'm under fedora 40

@SanderRonde
Copy link
Owner

That does sound like another issue. It's not so much piling up as it's just a single big scan happening. Sounds like the phpstan.singleFileMode setting is what you're looking for. By default this extension checks the whole project (since that's what the author of PHPStan recommends). But with that mode enabled it'll only perform checks for the current file.

The reason he recommends that is that in the long run, performing single-file checks is much slower. Since it invalidates the cache every time. That means it doesn't scan just the files that changed and its usages, but also needs to scan its dependents. So in the long run single-file-mode costs you more CPU time. If you've completed a succesful checks once, the cache will ensure checks from then on are much less heavy. But I can understand not going for complete checks on a relatively low-power machine.

I haven't used PHPStan inside docker myself so no documentation for it (yet). But you should be able to make it work by using the phpstan.binCommand setting, maybe using the phpstan.paths setting too (explanation here). There are also quite some issues on this repo discussing docker support so you might be able to puzzle it together based on those (such as #1).

@wallacio
Copy link

wallacio commented Jul 3, 2024

I think that does sound like another issue - albeit one that we're also seeing. Project contains > 2000 files/scripts, which renders VSCode unusable for 10-15 seconds after every save as PHPStan rips through the entire project. On a machine with 10th gen i7 CPU, that does seem abnormally long.

Enabling singleFileMode does improve things marginally but there's still a considerable delay between ctrl+s and being able to navigate method definitions etc by ctrl+click on method names, for example whilst "PHPStan checking..." whirls away in the status bar. I do only see a single php process running, so it's not like it's kicked off multiple processes.

Performance is preventing us from using this on-save so we'd love to find a solution. Any help in diagnosing this, if it's not related to other the other people in this issue's experiences would be appreciated. Fully appreciate it may be nothing to do with this extension, either.

@SanderRonde
Copy link
Owner

That does indeed sound unrelated to the extension. The performance hit probably comes from running PHPStan itself, which is spawned by the extension but since it's spawned in it shouldn't be hanging up the UI thread. If that's happening it's likely that your computer is just being maxed out. That's not surprising btw, when I run it on my own desktop PC (with a similarly powerful CPU) it also freezes completely. At my job we've got a massive 128-core beast of a dev-server that I can execute PHPStan on. Even on that thing it takes ~20s to check ~2k files and it consumes a large amount of processing power. PHPStan is pretty demanding.

You can test this out by just running PHPStan by itself on the commandline. If it's fast, it's the extension's fault. If it's slow, then it's PHPStan itself being slow :)

@martijn-dd
Copy link

I have the same as berniedurfee-renaissance on my Mac.
PHP processes piling up.

I checked the extension log files of VS Code.
In the PHPStan Client Log I noticed the following (hide the file path with ------) :

[check:23] Check started for file: ------
[check:22] Check completed for file, errors= {"fileSpecificErrors":{},"notFileSpecificErrors":[]}
[check:23] Spawning PHPStan with the following configuration: {"binStr":"/opt/homebrew/bin/phpstan","args":["analyse","-c","------/phpstan.neon","--error-format=json","--no-interaction","--memory-limit=1G","--no-progress","------.php"],"tmpDir":"/tmp/phpstan"}
[process-spawner] Spawning process 18610 with timeout 900000
[file-watcher] Checking: Document changed

with timeout 900000 => 900 seconds I guess?
But in the extension settings the Project timeout is 300000 and the other timeout is 30000.

Maybe that timeout of 15 minutes could cause that it looks like the processes are not stopped/killed but takes longer than expected.

Let me know if I need to provide more details to help you solve the issue.

@SanderRonde
Copy link
Owner

Correct that's 15 minutes. There's two timeouts:

  • The regular timeout that you specify. If PHPStan runs longer than this the extension tries to kill this check and reports it as failed.
  • This 15m timeout that is just there to ensure that there are no PHPStan zombie processes remaining. PHPStan has the tendency to leave zombies and this code will just kill whatever is alive after 15m to ensure all of those zombies are dead. You could see this as more of a fail-safe that doesn't let PHPStan gracefully exit.

(I agree that logging-wise this is very unclear, might change that in the future)

@Sectimus
Copy link

Sectimus commented Jul 24, 2024

Just like to add I am also getting the same issue. I too am using docker. Same experience, if I am going at a slow pace everything works nicely, but a quick ctrl+s here, ctrl+z there, another ctrl+s here and bam you have a bunch of php instances eating your laptop alive.
Twice now today I have had a hard OOM crash due to this, I really like this extension, once everything works, it works great. But it does make it difficult to continue use...
Here is my config for reference:

"phpstan.rootDir": "${workspaceFolder}",
"phpstan.configFile": "build/phpstan/src.1.neon.dist,build/phpstan/src.2.neon.dist,build/phpstan/tests.1.neon.dist,build/phpstan/tests.2.neon.dist,build/phpstan/tests.3.neon.dist",
"phpstan.binPath": "/var/www/REDACTED/vendor/bin/phpstan",
"phpstan.projectTimeout": 9999999,
"phpstan.paths":{
	"${workspaceFolder}": "/var/www/REDACTED",
},
"phpstan.binCommand": ["docker", "exec", "-t", "REDACTED_api_php-1", "php", "/var/www/REDACTED/vendor/bin/phpstan"],
"phpstan.memoryLimit": "4096M",

I have tried the singleFileMode option as well, that does indeed make the general experience much snappier, but the php instances are still not killed, they don't seem to be doing anything else when they get in this "zombie" state, they exist purely to consume human brains resources and nothing more.

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

No branches or pull requests

6 participants