Carbon is bad for the climate. Thus, Green IT aims to reduce the impact of IT on the climate as much as possible by reducing the emissions. While we can’t write software that does not consume any electricity, we should use it wisely. This is especially true for software that is used a lot.
With approx. 200,000 Installations per day, nesbot/carbon is surely one of the most used Composer packages today. It is packed with features and offers translations for almost every language you could think of.
But it’s feature-richness and popularity comes with a price: a vast amount of, well, carbon emissions it causes. Oh, the irony.
Carbon, unfortunately, is slow and bloated. Allow me to explain what I mean.
Carbon is slow
PHP has its own date-related objects and functions. Their usage and syntax might not be as streamlined as Carbons API, yet they often enough do the job just right. To compare the performance of the PHP-native functions with the Carbon counterparts, I used PHPBench. You can find the benchmarks in my repository.
Please note that I didn’t pick any particularly bad examples on purpose, just some everyday use cases.
Example 1: Subtract 30 days
First simple scenario: subtract 30 days from the current time, and return the timestamp. The PHPBench file looks like this:
<?php namespace PerformanceTests\Tests\Benchmark; use PhpBench\Attributes as Bench; use Carbon; class Subtract30DaysBench { #[Bench\Revs(5000)] #[Bench\Iterations(10)] public function benchStrtotime() { strtotime('-30 days'); } #[Bench\Revs(5000)] #[Bench\Iterations(10)] public function benchCarbon() { (new Carbon\Carbon())->subDays('30')->getTimestamp(); } #[Bench\Revs(5000)] #[Bench\Iterations(10)] public function benchCarbon2() { (new Carbon\Carbon('-30 days'))->getTimestamp(); } #[Bench\Revs(5000)] #[Bench\Iterations(10)] public function benchDateTime() { (new \DateTime())->sub(\DateInterval::createFromDateString('30 day'))->getTimestamp(); } #[Bench\Revs(5000)] #[Bench\Iterations(10)] public function benchDateTime2() { (new \DateTime('-30 days'))->getTimestamp(); } }
Let’s have a look at the results. Of course, the absolute values will vary, but we are more interested in the relations. The mode column indicates the Microseconds (μs) it took to run the Benchmark on average:

Both PHP-native strtotime function and the DateTime class are not much harder to use than the pendant of Carbon, but significantly faster. It takes Carbon at least 5 times and up to almost 10 times as long for the same result.
Example 2: Date format
Now, let’s generate a Date string from the current timestamp.
class DateFormatBench { #[Bench\Revs(5000)] #[Bench\Iterations(10)] public function benchDate() { date('D M d Y H:m:s'); } #[Bench\Revs(5000)] #[Bench\Iterations(10)] public function benchDateTime() { (new DateTime())->format('D M d Y H:m:s'); } #[Bench\Revs(5000)] #[Bench\Iterations(10)] public function benchCarbon() { (new Carbon\Carbon())->format('D M d Y H:m:s'); } }

Same here – the date-Function works great, and beats Carbon easily.
Example 3: Diff
The last example is about getting to know the difference between two dates.
class DiffBench { #[Bench\Revs(5000)] #[Bench\Iterations(10)] public function benchDate() { $origin = new \DateTimeImmutable(); $target = new \DateTimeImmutable('-3 days'); $interval = $origin->diff($target); $interval->d; } #[Bench\Revs(5000)] #[Bench\Iterations(10)] public function benchCarbon() { Carbon\Carbon::now()->subDays(2)->diffInDays(); } }

Admittedly, Carbon’s API is much nicer to use here, but is it worth to be 10 times slower?
What do the results tell us?
As you can see, Carbon always gets outperformed by native PHP functions. This is not really surprising, since the native functions are always faster. So at least, Carbon should give us a much better coding experience to compensate for the poorer performance. This is a matter of taste, I’d argue that mostly the PHP-native way is not much different.
But does it really matter if it takes 1 microsecond or 9? If it occurs only a few times during a request, surely not – unless you can live with the fact that the way you chose is 9 times slower for no good reason.
Yet, if you use Carbon in, let’s say, a CSV import function for big data loads, it will make a difference and piles up to wasted seconds. So if you can’t live without Carbon, at least consider not using it in performance critical parts of your application.
Improvements
The instantiation of a Carbon object is quite time-consuming, since with 3 MB in memory, it is pretty big. You can save a lot of execution time if you create the instance once, and reuse it, like in the following example:
class InstantiationBench { #[Bench\Revs(10)] #[Bench\Iterations(5)] public function benchDate() { for ($i = 0; $i < 10000; $i++) { date('D M d Y H:m:s', $i); } } #[Bench\Revs(10)] #[Bench\Iterations(5)] public function benchDateTimeNewInstance() { for ($i = 0; $i < 10000; $i++) { (new \DateTime())->setTimestamp($i)->format('D M d Y H:m:s'); } } #[Bench\Revs(10)] #[Bench\Iterations(5)] public function benchDateTimeSameInstance() { $date = new \DateTime(); for ($i = 0; $i < 10000; $i++) { $date->setTimestamp($i)->format('D M d Y H:m:s'); } } #[Bench\Revs(10)] #[Bench\Iterations(5)] public function benchCarbonNewInstance() { for ($i = 0; $i < 10000; $i++) { (new Carbon\Carbon($i))->format('Y-m-d'); } } #[Bench\Revs(10)] #[Bench\Iterations(5)] public function benchCarbonSameInstance() { $carbon = new Carbon\Carbon(); for ($i = 0; $i < 10000; $i++) { $carbon->setTimestamp($i)->format('Y-m-d'); } } }

What can we learn from these results? Reusing an instance definitely pays off!
For the same result, the execution time varies between 3ms and 40ms (Please note that the results are in Milliseconds (ms) and not Microseconds (μs) anymore!) This is over 13 times the difference! And yes, 40ms makes a difference, if added to an API response, for example.
It also shows that doing a quick check of the performance of your chosen solution pays off as well. Especially when you are working on performance-critical parts of your code, consider and test alternatives.
From an environmental perspective, Carbon just consumes unnecessary energy.
How reliable are these tests?
Finally, a word on the methodology chosen: PHPBench can only tell you the time needed on the machine where the tests were performed. The tests in this post were run on a Macbook Pro M1 and PHP 8.1.13.
If you run the tests on your machine, they will most likely show you different results. I tested them on different machines as well, and, of course, ended up with different results. Yet, one thing was always the same: Carbon was always the slowest option.
Carbon is bloated
But Carbon is not only slow, it is bloated as well. As we saw above, a Carbon instance alone consumes quite some memory. It doesn’t stop here.
Once downloaded, Carbon uses up approx. 5 MB on your local disk. Not bad for a DateTime API, right? Let’s have a closer look.
You’ll quickly identify a folder called Lang which alone weights 3.5 MB. This folder holds over 180 localization files. This is, on the one hand, pretty great because it brings the worldwide community closer together. It comes with a serious cost, though.
Most likely, your application will not support all these languages. A good amount of data in this directory is useless for you, and many others. Let’s assume an average project only uses 500kb of localization data, which is already a lot. This means that 3 MB has been downloaded in vain.
Let’s do the math
Doesn’t sound much? Well, as mentioned, Carbon (the package) has approx. 200,000 daily(!) installs, which in turn means that 600,000 MB (200,000 × 3 MB) gets downloaded every day. This equals 585 GB per day and sums up to 213,687 GB (200,000 × 3 MB × 365) or 208 TB per year – without serving a purpose.
Assuming an energy consumption of 0.81 kWh per GB of data traffic, and 442 g CO2e per kWh (using the Sustainable Web Design methodology), this sums up to over 70 tonnes (!) of carbon (the gas) per year that is caused only by these unnecessary data transfers of language files.
213,687 GB × 0.81 kWh/GB = 173,086 kWh
173,086 kWh × 442 gCO2e/kWh = 76,504,219 gCO2e
76,504,219 gCO2e / 1000 / 1000 = 76.5 tCO2e / Year
Isn’t that a bit much of carbon (both the gas, and the package) wasted? To be fair, the actual mileage will vary, as we do a lot of assumptions here. Estimating or even measuring carbon emissions of Software is challenging to say the least.
Yet, it should show that software does have a noticeable impact on the climate. And this is only one little package amongst many. The same thinking led the creator of the also well known fzaninotto/Faker package to abandon its creation.
It would help a lot of the maintainers of Carbon could refactor the library to separate the localization files from the code. I can’t say how much effort this would cause, both regarding refactoring and future maintenance, but definitely it would be a great step towards sustainability.
Conclusion
With the knowledge we gathered above, my conclusion is: avoid the Carbon package if you can. Not because it is not good (it is well written and offers a lot of functionality), but because we pay a high price for a bit of comfort. Or better, the environment and our users pay the price.
Often enough, PHP will do the job. If you still need Carbon, at least consider using it only if really necessary, and try to avoid continuous instantiation – especially in parts of your application which are executed a lot.
What do you think? Is Carbon still worth it?
Great write-up! I wasn’t aware that Carbon adds so much overhead.
What got me thinking, and what I’d like to comment on are the two questions from the article.
> Admittedly, Carbon’s API is much nicer to use here, but is it worth to be 10 times slower?
> What do you think? Is Carbon still worth it?
By no means do I have, or could have the data on how people are using Carbon. Having said that, my assumption (yes, I know, assumptions are dangerous) is that the majority of Carbon installations are there for simple operations like the one from your first example. These are the situations where I can’t find any justification for using packages like Carbon. I think that a good analogy for that would be in lines of “using a tractor to go to a supermarket for a bag of groceries”.
On the other hand, is there a place for things like Carbon in the PHP system? Being pragmatic, I say yes, but… Looking at its impact and looking at the data on how poorly it scales in regard to wasted resources and carbon emissions, the responsible thing IMO to do would be to pose some questions before including it in the app (and not just Carbon). At least being mindful of its inclusion would be a great start!
For example:
– Are you working on an application that heavily uses dates and date manipulation?
– What are the time gains? Is it in the domain of a rounding error, or you can deliver something useful much faster?
I’d love to see more mindfulness about the tech we use in the IT industry.
Thanks for your comment!
I think you’re analogy with the tractor nails it. We always take the tractor, because we might need to suddenly cross a cow meadow, and we want to be prepared, just in case 🙂
If we start measuring our solutions a bit better, and right from the beginning, it can make a big difference.