One of the simplest -- and most often overlooked -- is to bother using minimalist semantic markup with separation of presentation from content and reducing static scripting in the markup to zero.
Outputting markup is one of the more time-intensive memory wasting aspects of a PHP program. This is REALLY true of STATIC content and values that doesn't change from page to page and is why bad/bloated markup is just a waste of processing time. You're sitting there using memory and with the processor sticking it's thumb up it's backside waiting for the networking to respond, and that means holding the connection open longer, the program open longer, and a host of other inefficiencies that a LOT of people just flat out ignore.
It's why I'm always railing against mind-numbingly idiotic HTML like:
<nav class="navbar navbar-toggleable-md navbar-inverse fixed-top bg-inverse">
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href="#">Navbar</a>
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
(722 bytes)
Doing the JOB of:
<div id="top">
<h1><a href="/">Site Title</a></h1>
<input type="checkbox" id="mainMenuShowHide">
<label for="mainMenuShowHide"></label>
<ul id="mainMenu">
<li class="current"><a href="#">Home <span>(current)</span></a></li>
<li><a href="#">Link</a></li>
(275 bytes) -- and no you don't need NAV or the aria role bullshit if you bother using H1..H6 and HR properly; and if you INSIST on derping the page with NAV, change DIV#top to a bloody NAV.
The ONLY reason to be slopping all those extra classes and div in there is a complete and utter ignorance of how to use HTML and CSS properly, and by using OVER THREE TIMES the markup necessary you're making PHP WASTE TIME on something it flat out shouldn't have to!
Same goes for your scripting. If it's static scripting that's the same on every page or pageload, DO NOT PUT IT DIRECTLY INTO A <SCRIPT> TAG, put it into an external file and SRC it in!
In that same way reducing the number of separate sources for scripting and CSS means less markup as well. If you're wasting 3k of the document just linking in two or three dozen separate CSS and stylesheets you're making the server on the whole work harder -- not just your webserver on serving the files themselves and slowing down the pageload, but also on the amount of pointless CRAP you're making PHP waste its time trying to output!
The less your PHP has to output, the less time it has to waste processing markup for output, the less it has to play with memory adding strings together, and the less time it will sit there hogging the connection. Sooner you release that connection the sooner some other user request can be processed when you're banging up against connection limits!
It might sound like something minor, but the REAL bottleneck on ANY hosting is networking, so reducing the work there should be a no-brainer. BUT...
DO NOT OBSESS ABOUT IT! It goes from using minimalist code to obsession when you start getting into things like minification -- aka whitespace stripping. When it comes to your markup output and PHP never sacrifice maintainability and ease of reading your codebase in the name of saving bandwidth. As a rule for HTML and CSS the time and space saved by stripping out tabs and linefeeds is bupkis, and rarely worth the punch you take back in terms of maintaining the codebase. It's only with static files like scripting that it is worth the benefit given the ease of having your deployment file minified whilst maintaining a non-minified equivalent.
... and even then if you're gzipping your output like a good little doobie, it's not the massive difference people play it up to be unless the codebase in question is total crap. (See jQuery)
Another optimization that should become "second habit" is to simply not drop in and out of PHP every Joe-blasted line! I'm of the opinion both from an efficiency and simplicity standpoint that GOOD PHP should only have a single <?php in it as the very first line, and should have NO ?> whatsoever. This is a fairly common practice as if you want to output something, that's why we have echo.
I also advocate avoiding complex string processing methods where/when possible -- and that means no double quoted strings, and none of that heredoc/nowdoc BS. It chews on memory, and even if the performance difference is a barely noticeable one to two percent in most cases the typing difference is just "don't hit shift, and stop escaping all your doubles"... one to two percent overall speed difference by NOT hitting a key? Worth it.
In that same way, AVOID string additions when you don't need them -- like on ECHO. Comma delimits on echo results in multiple sends, often of static data from the static data area, instead of variable space or the stack. When you do something like:
echo "hello $name<br>";
or
echo 'hello ' . $name . '<br>';
In the first case the string has to be split at the variable into multiple parts by the parser. During runtime enough memory has to be allocated for the completed string, which is then added together, and then sent to echo. In the second case the strings are already separate, but because it has to be added together FIRST the memory still has to be allocated and the addition performed. Memory allocated has to be released, and this increases the overall memory footprint and processing time.
But take this:
echo 'hello ', $name, '<br>';
What's the difference you ask? Each substring is sent separately in turn to echo. This means that no extra memory has to be allocated as it's basically the same as passing pointers to echo. PHP doesn't need to make extra copies of it.
Consider the following example which makes it a bit more clear what's going on here:
<?php
function test() { echo 'test'; }
echo 'This is a ' . test() . '<br>';
echo 'This is a ', test(), '<br>';
The resultant markup? NOT what you'd expect.
testThis is a <br>
This is a test<br>
How's that for a mind-f***? The string addition takes precedence meaning the function HAS to execute BEFORE the result string can be sent to echo, hence it echoing "test" BEFORE the echo of the parent. This shows that the resultant string has to be allocated in memory meaning a bigger memory footprint and more time spent copying values around. With the comma delimited echo each part is sent in turn, typically by reference so there's no increase in memory footprint or extra processing overhead!
In that same way:
This is a <?php test(); ?><br>
Would be more efficient than the string addition too, even if it's ugly as hell and harder to maintain. (IMHO)
The amount this might save you in a program is also hard to measure due to a lot of it being in the parsing side (meaning if the code bytecode caches you see less benefit) and requiring a LOT of processes going at once to measure (a flaw of artificial benches) but again it's a simple difference in how you type the same thing in, so why use the crappy way? LAUGHABLY some people will use the "oh it's only a few percent" claim as a LAME EXCUSE for the fact they just can't be bothered to change how they type things in -- in which case they're probably in the wrong business.
Another place where gross inefficiencies lie are string-based template systems -- SMARTY for example. The MASSIVE memory bloat just because "hurr durr, weez bees two stoopids tu yuze functuns" is so mind-blowingly inefficient I cannot understand why anyone would use it by choice apart from fear (of the big bad PHP itself) and ignorance on the part of front-end developers.
That they basically card-stack using code no sane PHP developer would right to justify their bloated train wreck is proof enough of this. See here:
Where they have this gem of stupidity:
<?php if(!empty($foo)): ?>
<?php foreach($foo as $bar): ?>
<a href="<?=$bar['zig']?>"><?=$bar['zag']?></a>
<a href="<?=$bar['zig2']?>"><?=$bar['zag2']?></a>
<a href="<?=$bar['zig3']?>"><?=$bar['zag3']?></a>
<?php endforeach; ?>
<?php else: ?>
There were no rows found.
<?php endif; ?>
That again nobody QUALIFIED to write PHP would probably write... that their dumbass halfwit system does as:
{foreach $foo as $bar}
<a href="{$bar.zig}">{$bar.zag}</a>
<a href="{$bar.zig2}">{$bar.zag2}</a>
<a href="{$bar.zig3}">{$bar.zag3}</a>
{foreachelse}
There were no rows found.
{/foreach}
Which seems nicer, until you realize the amount of processor wasting regex and other string processing their bullshit has to do JUST to turn it into PHP that will actually run, and all to do the job of:
<?php
if (empty($foo)) echo 'There were no rows found';
else foreach ($foo as $bar) echo '
<a href="', $bar.zig, '">', $bar.zag, '</a>
<a href="', $bar.zig2, '">', $bar.zag2, '</a>
<a href="', $bar.zig3, '">', $bar.zag3, '</a>';
If that minor difference in extra characters (all 37 of them) is enough to make you dive for idiocy like SMARTY, you have zero damned business working in PHP in the first bloody place! Go take up something a bit less detail oriented like macramé!
Don't even get me started about their next example, where if the TD are all uniform data they aren't TD and that shouldn't even be a table!
Next up, run in fear the moment someone refers to a "programming paradigm" as you've tread into "sick buzzword" territory used by stupid people to make themselves sound smart. Same goes for when people talk about a "software ecosystem" -- a comparison you REALLY don't want to make given REAL ecosystem concepts like "mass extinction" or "parasitism". The pinnacle of this type of stupidity us found in frameworks, which more often than not remove your control over how the project really works, works against the natural way in which the underlying language itself was meant to work, and often prevents your developers from learning enough about that underlying language to even know if ANY of the claims about it being "easier" or "helping with collaboration" are fact or fiction -- more often than not it's the latter!
A stunning example is the shoe-horning of MVC into PHP. Model-view-controller is a real-time event driven programming concept -- and it's a good one. That would be all fine and dandy if PHP were a realtime event driven language instead of a top-down linear execution linear output one! The end result is more often than not the equivalent of trying to force a fat cow's size 13 hoof into a size 7 pump. You end up needing every shoe-horn in the store and a to borrow Jobbo the Clown's reality distortion field to pull it off.
Which is not to say MVC isn't built on concepts that cannot be applied to PHP; I'm just saying that all the 1:1 implementations are fat bloated train wrecks that more often than not introduce overhead for NOTHING, make things HARDER to actually do, and like every other framework based concept usually gets called "easier" or "simpler" not because it is in fact any of those things, but because the people saying that don't -- AGAIN -- know enough about the underlying language to even flap their yap on the topic.
Concepts that can be applied are the same ones you should always have in web technologies such as separation of concerns. Just as HTML is for saying what things are, CSS is for what things look like, and JS is SUPPOSED to be about enhancing existing functionality, with PHP separating input handling, data retrieval, and result output is important. That's where people TRY to use MVC, but it's just not how PHP was designed to work.
PHP is best used more along the lines of the old 1980's concept of RMP -- Request, Manufacture, Package -- a concept that I can't even find anything about anymore as it seems to have died off about the same time people stopped using clipper.
PHP is ideal for this, as the user makes a request (request), you retrieve the relevant data of that request or store any new data (manufacture), and then you send the result making it pretty (packaging). Just like a turnkey business. In my own codebases I follow this model with an outer "manager" layer that processes the request and sends it to the right "manufacturer", which then in turn sends the result to the template -- our "packaging". It's clean, it's simple, it's linear, and it doesn't go batshit with objects and framework nonsense you generally don't need to waste overhead, processing time, and complex esoteric "only useful in the classroom" concepts on.
Finally, let's talk database queries. There's a LOT of "conventional wisdom" that isn't really wisdom, and again it comes down to a question of resources. EVERYONE seems to talk about database access like they can just keep throwing hardware at the problem -- fine if you can afford to host your entire project on a room full of SPARC M8's with 4tb of memory per machine with 128GFC fibre-channel connected RAID arrays, but that mentality is going to go bits-up face-down on some crappy little $10/mo VPS or shared hosting.
A great example of this is the "when possible ALWAYS make one giant query" -- you'll see this with JOIN's of "many to many" a lot, often mated to things like pulling the ENTIRE result set BEFORE processing it into the template for output. The "one giant query" means one long hog of the SQL connection risking timeout errors on that connection, PHP itself, and stopping other processes from gaining access. The "joins" often mean redundant data in the result set meaning more information being shoved across the NETWORKING (since SQL is typically port or socket access) than needs to be. Copying the entire dataset into an array or other structure means making another copy in memory for NOTHING! More memory, more networking time, more overhead -- and if you're no a machine that doesn't have any of those available it IS going to faceplant, FAST.
See torrent sites running on highly modified versions of phpBB that spend 90% of their "uptime" telling users $db->conn(0).. and no, moving static files to Cloudflare isn't going to fix that!
Breaking those queries into smaller subsets without the join and hard coding processing the like data first and unique data for each second can in fact run smoother even if on paper it isn't "faster" just because you're not creating as big a memory footprint, not hogging the SQL server giving other processes a chance to do what they need, and if need be if the PHP timeout becomes an issue you can send a "please wait" with a refresh to the user for when the completed data set IS ready.
I've lost count the number of projects I've been called in to help "fix'" the past fifteen years where taking something as simple as a join and splitting it into one outer query and a foreach with an inner query was all that was needed to make it APPEAR faster, even though in practice it actually used more CPU and more time. MANY times that's all load balancing is, and it's a concept you get used to if you ever have to deal with things like RTOS, time-slicing, or GOD FORBID co-operative multitasking. (the last of which is a horror show that sends you screaming back to the nice safe world of pre-emptive)
Now, for all that I've said -- yes, much of it may have no impact in YOUR case, it might have a massive impact. Each program is unique and HAS to be treated as such. That's why profiling tools (xDebug, Blackfire, Z-Ray, etc) are important so you aren't wasting time re-coding entire stretches of code that deliver no real boost whilst the real bottleneck goes unaddressed. STILL THOUGH good practices from the start should make it easier to dial in where the big problems are, as you don't end up drowning in all the little ones.
In SO many existing codebases I've been brought in to help with over past two decades or so finding the inefficiency or even simple bugs has been a nightmare JUST because simple good practices were ignored from the start. HTML is notoriously bad for this given how permissive it is over going right past bugs as if nothing was wrong and not strictly enforcing semantics or even logical document structure; but because PHP's "real job" is to basically gather data and apply markup to it, by extension people's PHP is often bloated convoluted wrecks of how NOT to write HTML or PHP. The more bad practices there are, the more sloppy approaches to doing things that are used, the harder it becomes to find what's "REALLY" wrong!
Be it outright bugs, or just plain inefficiencies that are hurting performance.
j
stuff ;)