SPEED UP your code
FOR THE PLANET
Carsten Windler
Grafix NewRelic
only bits and bytes?
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
SUSTAINABLE IT
GREEN IT
GREEN SOFTWARE ENGINEERING
SHIFT
RETHINK
REDUCE
REDUCE
PERFORMANCE IN MIND
My Goodness
Why Didn't I Think of That?
How to not do CSV imports:
- Load the whole CSV file into memory
- Create a Model from every row
- Iterate over the Collection of Models
- Do some super slow calculations
- Use the Model to save the data
- ...?
- Timeout
?
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');
}
}
?
AI SUPPORT
$resultArray = [];
for ($i = 0; $i <= 10000; $i++) {
$resultArray[] = sprintf('%s %d', trans('row'), $i);
}
// Time (seconds): 0.45
// Memory Peak (MB): 80.65
?
?
REDUCE FUNCTION CALLS
$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)
!
STRING CONCATENATION
$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)
!
Preallocate array
$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)
!
OVERALL
$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)
🎉
PROFILING
What else?
LIFECYCLE OF An HTTP REQUESt
Bootstrap
Business Logic
Finish
up
.env
config
routes
middlewarez!!!1
events
DI container
observers
service providers
validators
Bootstrap
Business Logic
Finish
up
PACKAGES
*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
PACKAGE Footprint
https://carstenwindler.de/green-it/why-phps-carbon-is-bad-for-the-climate/
- Carbon has 200,000 daily installs
- 3 MB language files downloaded in vain
- 200,000 x 3 MB x 365 = 213,687 GB
- 0.81 kWh/GB of data traffic*
- 442 gCO2e/kWh*
- 213,687 GB × 0.81 kWh/GB = 173,086 kWh
- 173,086 kWh × 442 gCO2e/kWh = 76,504,219 gCO2e
70+ tCO2e per year
wasted
CARBONS CARBON
* 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
ARCHITECTURE
https://unsplash.com/photos/FO2zwDMQzUM
DATABASE
-
Use the right tool for the job
- SQL
- NoSQL
- Key/Value
-
Learn about performance tweaks
- Indexes
- Projection
- Slow query log
-
EXPLAIN
statement - ORM necessary?
https://unsplash.com/photos/Wpnoqo2plFA
- Table
performance_tests
- 500,000 rows
- half of them have
some_flag = 1
-
export
id, first_name, last_name
EXAMPLE: CSV EXPORT
$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...
- Hosting
- Cloud services
-
Time
- Developer
- CI/CD
- QA
- Product manager
- SEO
- Customer satisfaction
MONEY
THANK YOU
Carsten Windler
Principal Engineer @
https://www.linkedin.com/in/cwindler
https://carstenwindler.de
https://plana.earth
APIs
Source: Cloudflare
-
Avoid API calls
- Caching
-
Reduce amount of data
- Is all information necessary?
-
Split up endpoints
GET /users/12
GET /users/12/address
-
Specify fields
GET /users/12?fields=id,last_name
APIs
https://www.pexels.com/photo/woman-writing-on-whiteboard-3861943/
- Log only what is necessary
- Data retention
- Garbage collectors / log rotation
- Compression / file formats
https://www.pexels.com/photo/black-trash-bin-with-full-of-trash-3806764/
STorage
CACHING
- Byte code cache (OPcache)
- Proxy cache (CDN)
- HTTP cache (Varnish)
- Server-side caching (Redis)
- Client-side caching (Browser)
- In-Memory-Caching
There are only two hard things in Computer Science: cache invalidation and naming things.
— Phil Karlton
OPcache
-
Check if enabled
php.ini
rlerdorf/opcache-status
-
Optimize memory usage, e.g.
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
-
Disable timestamp validation
opcache.validate_timestamps=0
opcache_reset()
IN-MEMORY CACHING
$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
SERVERLESS / Faas
Speed up your code
By Carsten Windler
Speed up your code
How to improve PHP code to emit less carbon. Talk on the PHP Developer Day 2023 in Dresden, 22.09.2023.
- 165