I noticed the other day that a new script I wrote for php 5 began outputting html that was viewable before the php script had actually finished. Did this happen with 4?
For instance, I have a long loop that echos something out with each iteration. The output was small in terms of kb, so I dont think it was lag due to the download speed. Can someone explain the difference in output?
Maybe there a difference in the configuration of the output_buffering directive, in php.ini ?
If output_buffering is enabled, PHP will "keep" the generated output in memory (at least, if it doesn't become bigger than the size of the memory buffer), and only send it to the browser when the page's generation is finished.
If output_buffering is disabled, the ouput is sent immediatly when generated, even if the script's execution is not finished yet.
I doubt there is a difference to this regard between PHP 4 and 5, but you can get this behaviour on both versions, namely by enabling/disabling the output_buffer. Maybe the default value for PHP 5 is different than it was for PHP 4? (Haven't checked)
When the data is sent, is dependant on PHP configuration, it's an output buffer, and behaves like a buffer.
Having said that, you can use the function ob_start() and ob_end_flush() to take control of the buffer. The Zend Framework does some clever stuff with output buffering for instance...
The usual suspects are:
Browser and HTML structure
Output buffering or output handlers
HTTP compression handled by PHP or by the web server
A close look at phpinfo() at a tool to see HTTP headers can help you.
Related
I'm starting php directly from the terminal and passing it a .php script to run, I'm not using a web browser.
The documentation for flush() says
Flushes the system write buffers of PHP and whatever backend PHP is
using (CGI, a web server, etc). This attempts to push current output
all the way to the browser with a few caveats.
So based on that, it sounds possible that flush() could still be needed when you need output to immediately get sent to the terminal before the script ends, because of the part where it said "system write buffers of PHP". But I would like to know definitively. I'm using php 8.1 currently, but my question is hopefully not version specific.
I'm wanting to know from someone familiar with PHP's C implementation whether it ever under any circumstances buffers output when started from a terminal, or if that only happens if PHP is started a special way by a server. I know if I run code that intentionally requests buffering by using ob_start() or something like that, then it is supposed to buffer and this will not be ended by calling flush(), that's not what I'm asking about. I'm asking about code that doesn't explicitly request any buffering.
Why not test that yourself?
<?php
// ob_start();
print "Test 1\n";
sleep(1);
print "Test 2";
sleep(5);
print "Test 3";
flush();
sleep(5);
On my test terminal (standard Ubuntu 20.04.5 LTS), ob_start buffers everything, and ignores flush() altogether. Without ob_start, all text is output immediately (even if not ended by a LF, as is the case for the second test).
I haven't a PHP 8.1 handy, but mine says,
> PHP 8.2.1 (cli) (built: Jan 18 2023 10:17:15) (NTS)
> Copyright (c) The PHP Group
> Zend Engine v4.2.1, Copyright (c) Zend Technologies
You might ask a different (opposite, even) question: are there conditions whereby my terminal-run script might start buffering for some reason?
When you call flush() the call gets ultimately redirected to sapi_module, which issues a fflush() on stdout (this on the current source tree on Github, but I don't think this was changed since at least PHP 5). This is enough, I believe, to say that flush() is sufficient.
Is it necessary? On a standard run from the terminal, no. But I didn't include any scriptlets or libraries or Composer modules that might have changed the buffering strategy.
Of course, any of those could have. Just issue an ob_start() (maybe because the module is born to run on a web server) and hey presto!, your script starts buffering and requires flush (actually, in that case, ob_flush() - as said above, flush will not work).
But if that's the case, you've got a completely different beast to deal with - you should probably write your own output function, so that all console writes are routed to some code that can check, say, ob_get_level() and deal with it accordingly. Or, bringing this to the extreme,
declare(ticks=1);
register_tick_function(static function() {
ob_get_level() && ob_flush();
flush();
});
I run a php script from xampp portable on windows. The script takes over a minute. Recently, the script is having flush() problem, as echo statements are not immediately displayed. The script used to work fine earlier with no buffering problem.
Interestingly, I ran the same script copying the xampp portable to another system and the flush statements were working without any problem. Same code, Same xampp portable.
What could be the reason?
Make the first line of your script ob_implicit_flush();.
or
Change the php.ini file setting implicit_flush = On.
From the documentation:
implicit_flush boolean, FALSE by default. Changing this to TRUE tells
PHP to tell the output layer to flush itself automatically after every
output block. This is equivalent to calling the PHP function flush()
after each and every call to print or echo and each and every HTML
block.
When using PHP within an web environment, turning this option on has
serious performance implications and is generally recommended for
debugging purposes only.
I read other responses and you keep insisting on the fact that your home environment and your work environment are the same. However, you can see that there is a difference. This point of view really help (at least to me) to investigate problems.
Since you did not provide many details about the problem, I would try the following checklist:
Settings
Is your PHP settings really identical? Try to compare results of phpinfo() on both environments.
Data
Do you really test your script on identical data? There are many subtle problems that are described in PHP manual:
Even the browser may buffer its input before displaying it. Netscape, for example, buffers text until it receives an end-of-line or the beginning of a tag, and it won't render tables until the tag of the outermost table is seen.
Some versions of Microsoft Internet Explorer will only start to display the page after they have received 256 bytes of output, so you may need to send extra whitespace before flushing to get those browsers to display the page.
http://php.net/manual/en/function.flush.php
or
http://www.php.net/manual/en/function.ob-flush.php#90529 (commenters point out many problems that you may experience)
Try dummy plaintext data instead of HTML. You may try to output simple lines like current time and check behaviour of your script.
Browsers
Try a few browsers (with cleared cache) to see if the issue is browser-specific or not.
I think it may be your browser. Have you cleaned the temporary settings of Iron Portable browser?
this occurs when you use gzip and there is some output have been send so the browser get confused to solve this , i uses this code always
if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false)
{ob_start('ob_gzhandler'); ob_start();}
else
ob_start();
You have not mentioned about the versions of windows both the systems running. Are the systems completely identical?
You also said that you are running a portable version of XAMPP , if you are using a pen drive/thump drive there is a chance that data transfer speeds can vary due to USB speeds.
I had a similar issue where the First system had USB legacy ports and the second one I tested has usb 2+ ports or higher.
The speed and processing time changed based on the systems, while one system took 20 seconds , other took nearly 60 seconds to process.
The slow system produced undesired results [I was working on an image processor].
I guess your case is similar and had to do a lot with the system vitals.
Cheers
Clain
I figured out that the problem is with antivirus. I recently switched to Bitdefender from Avast. When I switched back to Avast, the problem disappeared miraculously. So, i guess antivirus is also a factor here.
In my PHP.INI, gzip compression already enabled. May I use ob_start('ob_gzhandler'); in my PHP pages? And whats different between these two?
Enabling compression like this:in PHP.ini can be done like this:
zlib.output_compression = On
this will mean every page PHP serves will be compressed, which may or may not be what you want.
Using ob_start('ob_gzhandler') however will only compress that particular buffer / page and will not affect anything else served by PHP.
Use the second method if you want to compress only certain output. Mixing the two will be pointless, and will probably just use extra CPU cycles trying to compress the already compressed output.
It could be that PHP is clever enough to only do the compression once, but it's still a fruitless exercise to use both approaches together.
It's usually better to enable compression in your web server, although this depends on what you are trying to achieve.
You cannot use the two together.
"You cannot use both ob_gzhandler() and zlib.output_compression. Also note that using zlib.output_compression is preferred over ob_gzhandler()."
http://www.php.net/manual/en/function.ob-gzhandler.php
You can still use ob_start() if you need to buffer your output, you just cannot us the gzhandler callback.
Hey, well I don't really know how to describe this but here's my current situation.
On my old host, I could have a loop going and echo things in the loop. As the code was running that loop, the text i was echoing would appear right away and I could see things happening.
Now though, on my current host if I have a loop like that I only see the text that was being echoed once the loop is done and the script is fully done executing.
I was just wondering if anyone knows why?
Thanks!
edit: output buffering and output compression is off.
As others have said, it sounds like output buffering is on by default on your host.
You can turn it off programatically, using ob_end_flush() (which sends any buffered output), or ob_end_clean() (which will discard any output). Calling one of those functions early in your code (at the top of your script, or in some config file, for example) will get you at least part of the way there.
You may also be able to turn off output buffering in php.ini, or by setting php_value output_buffering Off in an .htaccess file, if you wanted to turn it off globally.
As Tobias P. points out, you can then use flush() to (try to) force whatever PHP is hooked up to (apache, CGI etc) to flush the output as well.
Do you use flush() ? If you do, maybe the server caches the response and sends it all at once, ask your webhoster
Output buffering my be on by default in the server config. As Tobias says, consult you webhost.
As has been stated, output buffering is likely enabled by the webhost in php.ini.
I believe you can inspect this yourself (though, it's possible for the webhost to disable access to the function):
echo ini_get('output_buffering');
Edit: some useful links
http://php.net/manual/en/outcontrol.configuration.php
http://php.net/manual/en/book.outcontrol.php
I have a really simple PHP script here,which simply loads several libraries (6 or 7 small classes) and initialize some variables then generate a very small amount of html code. But seeing from the memory_get_usage() function, I see 1.21MB memory usage.
Is that normal or something is wrong?
If you want to see what is actually loaded up when you execute PHP use this: get_defined_vars
The reason PHP is consuming memory may not be your script at all but rather your PHP configuration and other extensions being loaded when php executes.
Depends on the libraries. All it takes is one snippet of code to load up your memory. Have you tried to run a code profiler?