FOR THE PLANET
Carsten Windler
Grafix NewRelic
55,7
Billion electronic devices by 2025
57
Million tonnes of electronic waste in 2021
57
~4%
IT's share of total greenhouse gas emissions
~2%
Share of data centres in global
energy consumption
Green Software Engineering
Green Coding
SHIFT
RETHINK
REDUCE
REDUCE
My Goodness
Why Didn't I Think of That?
How to not do CSV imports:
?
Let's optimize some code!
class StringPositionBench
{
public function benchStrContains()
{
str_contains('string contains PHP', 'PHP');
}
public function benchPregMatch()
{
preg_match("/php/i", 'string contains PHP');
}
}
?
$resultArray = [];
for ($i = 0; $i <= 10000; $i++) {
$resultArray[] = sprintf('%s %d', trans('row'), $i);
}
// Time (seconds): 0.45
// Memory Peak (MB): 80.65
?
?
$resultArray = [];
$transRow = trans('row');
for ($i = 0; $i <= 10000; $i++) {
$resultArray[] = sprintf('%s %d', $transRow, $i);
}
// Time (seconds): 0.015 (=> 0.03x)
// Memory Peak (MB): 80.65 (=> 1.00x)
!
$transRow = trans('row');
$resultArray = [];
for ($i = 0; $i <= 10000; $i++) {
$resultArray[] = $transRow . ' ' . $i;
}
// Time (seconds): 0.007 (=> 0.48x)
// Memory Peak (MB): 52.64 (=> 0.65x)
!
$transRow = trans('row');
$resultArray = new SplFixedArray(10001);
for ($i = 0; $i <= 10000; $i++) {
$resultArray[] = $transRow . ' ' . $i;
}
// Time (seconds): 0.0064 (=> 0.94x)
// Memory Peak (MB): 52.14 (=> 0.99x)
!
$transRow = trans('row');
$resultArray = new SplFixedArray(10001);
for ($i = 0; $i <= 10000; $i++) {
$resultArray[] = $transRow . ' ' . $i;
}
// From:
// Time (seconds): 0.45
// Memory Peak (MB): 80.65
// To:
// Time (seconds): 0.0064 (=> 0.01x)
// Memory Peak (MB): 52.15 (=> 0.65x)
🎉
What else?
Bootstrap
Business Logic
Finish
up
.env
config
routes
middlewarez!!!1
events
DI container
observers
service providers
validators
Bootstrap
Business Logic
Finish
up
*Runs/second
Guzzle
14.553*
Nyholm
17.734*
=> approx. 21% faster!
class DateFormatBench
{
public function benchDate()
{
date('D M d Y H:m:s');
}
public function benchDateTime()
{
(new \DateTime())->format('D M d Y H:m:s');
}
public function benchCarbon()
{
(new Carbon\Carbon())->format('D M d Y H:m:s');
}
}
Carbon has 180+ language files
approx. 3,5 MB
https://carstenwindler.de/green-it/why-phps-carbon-is-bad-for-the-climate/
70+ tCO2e per year
wasted
* https://sustainablewebdesign.org/calculating-digital-emissions/
fzaninotto/Faker
* https://marmelab.com/blog/2020/10/21/sunsetting-faker.html
https://www.pexels.com/photo/red-sunset-over-water-10276693/
🪦
Over the years, Faker has probably emitted more than 11 Metric tons of CO2 equivalent. Being such a significant contributor to climate change kills me.
François Zaninotto*
composer require everything
https://unsplash.com/photos/FO2zwDMQzUM
EXPLAIN
statementhttps://unsplash.com/photos/Wpnoqo2plFA
performance_tests
some_flag = 1
export id, first_name, last_name
$stmt = DB::select(
'SELECT * FROM performance_tests WHERE some_flag = 1'
);
$fp = fopen('/tmp/export.csv', 'wb');
foreach ($stmt as $row) {
$fields = [
$row->id,
$row->first_name,
$row->last_name,
];
fputcsv($fp, $fields);
}
fclose($fp);
// #1: Raw SQL
DB::select(
'SELECT *
FROM performance_tests WHERE some_flag = 1'
);
// Time: 1.02s
// Memory Peak: 242.71 MB
// #2: Raw SQL + projection
DB::select(
'SELECT id, first_name, last_name
FROM performance_tests WHERE some_flag = 1'
);
// Time: 0.74s
// Memory Peak: 191.62 MB
// #3: Raw SQL + cursor
DB::cursor(
'SELECT *
FROM performance_tests WHERE some_flag = 1'
);
// Time: 0.78s
// Memory Peak: 82.2 MB
// #4: Raw SQL + cursor + projection
DB::cursor(
'SELECT id, first_name, last_name
FROM performance_tests WHERE some_flag = 1'
);
// Time: 0.70s
// Memory Peak: 63.17 MB
Type | Time (s) |
Memory Peak (MB) |
---|---|---|
Raw SQL | 1.02 | 243 |
Raw SQL + projection | 0.73 | 192 |
Raw SQL + cursor | 0.78 | 82 |
Raw SQL + projections + cursor | 0.70 | 63 |
$result = PerformanceTest::where('some_flag', '=', 1)->get();
$fp = fopen('/tmp/export.csv', 'wb');
foreach ($result as $performanceTest) {
$fields = [
$performanceTest->id,
$performanceTest->first_name,
$performanceTest->last_name,
];
fputcsv($fp, $fields);
}
fclose($fp);
// #5: Eloquent
PerformanceTest::where('some_flag', '=', 1)->get();
// Time: 3.74s
// Memory Peak: 378.92 MB
// #6: Eloquent + projection
$result = PerformanceTest::where('some_flag', '=', 1)
->select(['id', 'first_name', 'last_name'])
->get();
// Time: 3.48s
// Memory Peak: 345.10 MB
// #7: Eloquent + lazy
PerformanceTest::where('some_flag', '=', 1)->lazy();
// Time: 21.63s
// Memory Peak: 55.1 MB
// #8: Eloquent + cursor
PerformanceTest::where('some_flag', '=', 1)->cursor();
// Time: 4.14s
// Memory Peak: 85.47 MB
// #9: Eloquent + Collection filter
PerformanceTest::get()->where('some_flag', '=', 1);
// Time: 7.77s
// Memory Peak: 705.52 MB
PerformanceTest::where('some_flag', '=', 1)->get();
Type | Time (s) |
Memory Peak (MB) |
---|---|---|
Eloquent | 3.74 | 379 |
Eloquent + projection | 3.48 | 345 |
Eloquent + lazy | 21.63 | 55 |
Eloquent + cursor | 4.14 | 85 |
Eloquent + cursor + projection | 3.99 | 66 |
Eloquent + collection filter | 7.77 | 705 |
Type | Time (s) |
Memory Peak (MB) |
---|---|---|
Raw SQL | 1.02 | 243 |
Raw SQL + projection | 0.73 | 192 |
Raw SQL + cursor | 0.78 | 82 |
Raw SQL + projections + cursor | 0.70 | 63 |
Type | Time (s) |
Memory Peak (MB) |
---|---|---|
Eloquent | 3.74 | 379 |
Eloquent + projection | 3.48 | 345 |
Eloquent + lazy | 21.63 | 55 |
Eloquent + cursor | 4.14 | 85 |
Eloquent + cursor + projection | 3.99 | 66 |
Eloquent + collection filter | 7.77 | 705 |
There is so much more...
THANK YOU
Carsten Windler
Principal Engineer @
https://www.linkedin.com/in/cwindler
https://carstenwindler.de
https://plana.earth
Source: Cloudflare
GET /users/12
GET /users/12/address
GET /users/12?fields=id,last_name
https://www.pexels.com/photo/woman-writing-on-whiteboard-3861943/
https://www.pexels.com/photo/black-trash-bin-with-full-of-trash-3806764/
There are only two hard things in Computer Science: cache invalidation and naming things.
— Phil Karlton
php.ini
rlerdorf/opcache-status
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0
opcache_reset()
$cache = [];
for ($i = 1; $i <= 10000; $i++) {
$randomNumber = random_int(1, 100);
if (isset($cache[$randomNumber])) {
$result = $cache[$randomNumber];
} else {
$result = sqrt($randomNumber);
$cache[$randomNumber] = $result;
}
echo $result;
}
// Vergleich mit CodeBench