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

Performance degradation #549

Open
makstech opened this issue Feb 14, 2023 · 3 comments
Open

Performance degradation #549

makstech opened this issue Feb 14, 2023 · 3 comments

Comments

@makstech
Copy link

Some time ago we were performing updates to all our packages, including the dotenv, where we went from v2 to v5. And later we noticed that the CPU usage and all request times have increased substantially, even though we use pretty beefy instances. On 8 core instances, CPU usage increased by >20%.

After some investigation, we found out that the dotenv load times have skyrocketed and memory consumption has gone up quite a lot too. The primary cause of regression was pinned down to this method

public static function parse(string $entry)
{
return self::splitStringIntoParts($entry)->flatMap(static function (array $parts) {
[$name, $value] = $parts;
return self::parseName($name)->flatMap(static function (string $name) use ($value) {
/** @var Result<Value|null,string> */
$parsedValue = $value === null ? Success::create(null) : self::parseValue($value);
return $parsedValue->map(static function (?Value $value) use ($name) {
return new Entry($name, $value);
});
});
});
}

Where now, to parse one .env line, it needs to create a bunch of classes and then the final entry is at least 2 classes that are kept in memory. Compared to a simple array<string, string> in v2.

Our .env is 2k lines long of which around 400 are empty lines and another 300 are comments.
So we downgraded back to v2 and the difference is huge, especially during peak hours.

For example, in one simple and fast route, during peak hours, the difference between v2 and v5 is around 80ms per request. On a route that has around 65k req/h (1m+ req/day) that makes more than 80 minutes of extra processing time in an hour, just on this route.
Here's an example of that route after the downgrade performed on the 8th of Feb. No other changes to the code or infrastructure were done.
image

I know, the obvious solution would be some sort of caching. But is there really a need for so much more processing and objectifying?

@GrahamCampbell
Copy link
Collaborator

Thanks for getting in touch. I am aware that v5 is slower than v2, and one reason for this is they have different features, and v2 has bugs that could only be sanely resolved by using a slower approach. I would be interested to know what PHP version you are using and what the env files are you are loading are looking like. I doubt the use of objects is what is the cause of the slow-down here, but I would certainly consider a PR that improves performance without introducing bugs, along with evidence.

In general, I would not recommend running this package on every request. Best practice is to use this package to parse your env file, one-time, then cache that across requests. v5 has a modular architecture, enabling this. For example, in Laravel, this package is used to compile a cached configuration file, one time, then that file is "required" by PHP at runtime, so we can make use of opcache, effectively meaning that here is zero IO on each request to load env and config.

@GrahamCampbell
Copy link
Collaborator

I'd also be interested to know if you are using opcache. Loading 100 classes into fpm should make zero difference to performance, other than on the first request.

@makstech
Copy link
Author

We are running PHP 7.4, and yes opcache is enabled.

what the env files are you are loading are looking like

Could you please elaborate on this one?
Just one regular .env file, with a bunch of simple string entries, less than 10 variables that have references, no multi-level references, and no multi-line entries.

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

2 participants