ob_flush takes long time to be executed - php

In my website(running with drupal) the ob_flush function takes a long time(between 10 - 100 secs) to be executed. How do I find out why? What can cause this so long time?

Try this:
ob_start();
//Your code to generate the output
$result = ob_get_contents(); //save the contents of output buffer to a string
ob_end_clean();
echo $result;
It is run quick for me.

[You may want to tag your question with Drupal, since this feels like it might be a Drupal issue. Specifically, I suspect that when you flush the buffer, you're writing to an outer buffer, which triggers a ton of hooks to be called to filter the data you've just written.]
I suspect that your problem is nested buffers. Drupal really likes buffers and buffers everything all over the place. Check the result of:
echo "<pre>\nBuffering level: ";
. ob_get_level() .
. "\nBuffer status:\n"
. var_dump(ob_get_status(TRUE))
. "\n</pre>";
If you've got nested buffers, then I suspect ob_flush() will do nothing for you: it just appends the contents of your inner buffer into the next outermost layer of buffering.
Nested buffers can come from Drupal itself (which the above will show), or from the settings for zlib-output-compression and output_buffering (try twiddling those, see if it changes anything).
If your buffers are not nested, and the above settings do not help, then you may also want to split the operation into pieces, and run the profiler there, to see which part is taking the time:
$data = ob_get_contents(); // Return the contents of the output buffer.
ob_clean(); // Clean (erase) the output buffer.
ob_end(); // Close the buffer.
echo($data); // Output our data - only works if there's no outer buffer!
ob_start(); // Start our buffer again.
The question then becomes, though, "what are you trying to accomplish?" What do you think ob_flush() is doing here? Because if the answer is "I want to push everything I've done so far to the browser"... then I'm afraid that ob_flush() just isn't the right way.

SET
output_buffering = Off
in php.ini

use
<?ob_start();?>
at the beginning of the page and
<?ob_flush();?>
at the end of the page, to solve this problem.

Related

What is the use of the ob_get_length() method?

i know those methods related to output buffering:
<?php
ob_start();
// some code
ob_end_flush();
ob_end_clean();
but i can't figure out why will i need the length of the output buffer. there is one question here is SOF about measuring the bandwidth of the user ,although that calculation will need to measure pictures and other files which is not addressed.
i did check the PHP manual and the "why" is not there.
Answering "why to use it". In order to answer this, we must first understand why we need to use ob_start.
Usually it is used for two purpose:
When we want to send HTTP headers, but we are not sure, that there is no rendering before(the first output will trigger header sending, so if you use, echo for example, before header, the later won't work)
When we want to send our output by chunks for performance. (your code can be written with a lot of echo or print, and usually they outputing only small data, so you are sending small portions of data back to browser, which is affecting performance.)
So now you can start to guess, why we need to use ob_get_length(). For example: i want to send my output by large chunks, so i am enabling output buffering and with the help of ob_get_lengthi can control how many data i can write to buffer, before sending it.
ob_get_length will return the length of the contents in the output buffer..
Here is simple example..
<?php
ob_start();
echo "Hello ";
$len1 = ob_get_length();
echo "World";
$len2 = ob_get_length();
ob_end_clean();
echo $len1 . ", ." . $len2;
?>
The above example will output: 6, 11
Updated:
ob_get_length() is helpful if you want to send a custom HTTP Content-Length header - although that is for advanced users only!

ob_get_contents + ob_end_clean vs ob_get_clean

Is there any difference between these two pieces of PHP?
ob_start();
//code...
$pageContent = ob_get_contents();
ob_end_clean();
someFunction($pageContent);
vs
ob_start();
//code...
$pageContent=ob_get_clean();
someFunction($pageContent);
I am currently using the first block, but I would like to use the second instead if it is functionally equivalent, since it is a bit more concise.
To answer your question:
ob_get_clean() essentially executes both ob_get_contents() and ob_end_clean().
Yes. It is functionally equivalent.
Case 1:
ob_get_contents() + ob_end_clean():
ob_get_contents — Return the contents of the output buffer
ob_end_clean — Clean (erase) the output buffer and turn off output buffering
So, basically, you're storing the contents of the output buffer to a variable and then clearing it with ob_end_clean().
Case 2:
ob_get_clean — Get current buffer contents and delete current output buffer
You're storing the buffer contents to a variable and then the output buffer is deleted.
What you're doing is essentially the same. So, I don't see anything wrong with using the second code-block here, since they're both doing the same thing.
ob_get_contents() can be used to continue the output buffering.
Example:
ob_start();
echo 'Something!';
$html1 = ob_get_contents();
echo 'More to say!';
$html2 = ob_get_contents();
ob_end_clean();
At the end the vars have this content:
$html1 = 'Something!';
$html2 = 'Something!More to say!';
There is one teeny difference between
$stuff = ob_get_clean();
and
$stuff = ob_get_contents();
ob_end_clean();
which is that the latter will throw an E_NOTICE if there is no active output buffer at the time that you call it, and the former won't. Throwing the notice actually seems like the saner behaviour to me, since if you're calling these functions without an output buffer then you're probably doing something wrong!
That the two approaches are pretty much equivalent is explicitly documented on php.net, which says:
ob_get_clean() essentially executes both ob_get_contents() and ob_end_clean().
The warning-throwing behaviour of ob_end_clean is also documented:
If the function fails it generates an E_NOTICE.
Note that there is no similar sentence in the docs of ob_get_contents or ob_end_clean.
If you really want to assure yourself there are no further differences between these functions (there aren't), you can dive into the definitions of ob_get_contents, ob_end_clean and ob_get_clean in the source. There's some weird error handling for impossible cases in ob_get_clean that should never get reached, but besides that, you can see that the behaviours are as described.
Based on the documentation,
ob_get_contents() + ob_end_clean()
is supposed to work the same as:
ob_get_clean()
However, because of a bug in PHP, it doesn't. Roland from nextendweb filed a bug report:
https://bugs.php.net/bug.php?id=76563
If you use ob_start with callback, the callback does not run, if you use ob_get_clean() on the same output buffer. The callback get skipped, which gives unexpected results. I think it is a bug.
So, if you're passing a callback to ob_start(), you'll need to use
$content = ob_get_contents();
ob_clean();
instead of:
$content = ob_get_clean();
Testing on sandbox, you will notice that it affects all PHP versions.

How does ob_get_contents work in Php?

This is a sample code from the book I am reading:
ob_start();
include("{$path}.ini");
$string = ob_get_contents();
ob_end_clean();
$pairs = parse_ini_string($string);
My question is, how does ob_get_contents() know what to get contents from? ({$path}.ini in this situation)?
ob_get_contents simply gets the contents of the output buffer since you called ob_start(). Essentially, an output buffer in PHP catches anything that would have been output to the browser (excluding headers). It's useful in cases where you may need to filter some output, or you're using a PHP method (such as var_dump) that writes output directly to screen, and you would instead like the return value of the method in a string.
In this case, because you're include()ing the .ini file, it's contents will be essentially output to screen, and ob_get_contents() will get the content of the file.
If you were to put echo "I'm a little teapot short and stout"; underneath the include, this would also be included in $string after the body of the .ini file.
In your specific case, however, output buffering is an unnecessary overhead, simply use file_get_contents on the .ini file. I'm not sure why a book would even have this code in it at all.
The "ob" stands for "output buffer". When you call ob_start(), PHP reroutes all output (using echo, etc) to the output buffer. Then you can use the other ob_* functions to retrieve and/or clear the buffer contents.
In your example, it will buffer any output generated by the file referenced by "{$path}.ini". When you include it, its output is added to the buffer, and when you call ob_get_contents(), it retrieves the contents of the buffer.
From PHP:
ob_start — Turn on output buffering
ob_get_contents — Return the contents of the output buffer
ob_end_clean — Clean (erase) the output buffer and turn off output buffering
Now, ob_get_contents can collect all buffer that outputted.
[1] http://www.php.net/manual/en/book.outcontrol.php
ob_get_contents() is getting everything that is echoed after calling ob_start() function, so there is not anything special about {$path}.ini - you are required to echo data you want to collect (yes, even outputs of simple echo or print_r calls will be collected - sometimes useful for debugging simple scripts).
You may understand ob_start() function as a simple redirection from screen to (invisible) PHP internal buffer which is later read by ob_get_contents(). So you will be able to redirect anything that you may see on the screen without calling ob_start() function (even the whole web pages).

PHP Timer usage

Firstly, I want to echo text and ,after 5 seconds,I want to echo another text.
So I write...
<?php
echo 'Text';
flush();
sleep(5);
flush();
echo 'Another Text';
?>
But I see both of (Text Another Text ) after 5 seconds.How can I do for this?
From documentation
Several servers, especially on Win32, will still buffer the output from your script until it terminates before transmitting the results to the browser.
So you see both TextAnother Texttogether.
Take a look at output buffering.
Have you started output buffering at some time? If so, you need to use ob_end_flush() to flush.
Switch off output buffering if you have it on or call ob_flush() too. Any output compressing (like gzip) will also mess it up. If it doesn't work try modifying these two php.ini directives to:
output_buffering = off
zlib.output_compression = off

Blocking file-read in php?

I want to read everything from a textfile and echo it. But there might be more lines written to the text-file while I'm reading so I don't want the script to exit when it has reached the end of the file, instead I wan't it to wait forever for more lines. Is this possible in php?
this is just a guess, but try to pass through (passthru) a "tail -f" output.
but you will need to find a way to flush() your buffer.
IMHO a much nicer solution would be to build a ajax site.
read the contents of the file in to an array. store the number of lines in the session. print the content of the file.
start an ajax request every x seconds to a script which checks the file, if the line count is greater then the session count append the result to the page.
you could use popen() inststed:
$f = popen("tail -f /where/ever/your/file/is 2>&1", 'r');
while(!feof($f)) {
$buffer = fgets($f);
echo "$buffer\n";
flush();
sleep(1);
}
pclose($f)
the sleep is important, without it you will have 100% CPU time.
In fact, when you "echo" it, it goes to the buffer. So what you want is "appending" the new content if it's added while the browser is still receiving output. And this is not possible (but there are some approaches to this).
I solved it.
The trick was to use fopen and when eof is reached move the cursor to the previous position and continue reading from there.
<?php
$handle = fopen('text.txt', 'r');
$lastpos = 0;
while(true){
if (!feof($handle)){
echo fread($handle,8192);
flush();
$lastpos = ftell($handle);
}else{
fseek($handle,$lastpos);
}
}
?>
Still consumes pretty much cpu though, don't know how to solve that.
You may also use filemtime: you get latest modification timestamp, send the output and at the end compare again the stored filemtime with the current one.
Anyway, if you want the script go at the same time that the browser (or client), you should send the output using chunks (fread, flush), then check any changes at the end. If there are any changes, re-open the file and read from the latest position (you can get the position outside of the loop of while(!feof())).

Categories