Forum Moderators: open

Message Too Old, No Replies

EventSource instance, should I free the MySQL result?

         

csdude55

5:26 am on Nov 11, 2022 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I have an EventSource persistent connection set up like this (not the whole thing, just the important parts for brevity):

if (typeof(EventSource) !== 'undefined') {
var source = new EventSource(membersSSE);

source.onmessage = function(e) {
mIconVal.html(e.data);
if (e.id == 'CLOSE') { source.close(); }
};
}

Then the PHP script at "membersSSE" looks like this:

header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

echo 'data: ';

$user ??= $_COOKIE['user'] ?? false;

if ($user) {
// do MySQL select query and print results

mysqli_free_result($mysql_results);
}

flush();

The question is, should I be using mysqli_free_result() at the end there, or am I defeating the purpose since it's an event stream? The results of the select query could change at any time and I'd want to show the updated info, so I THINK that I should free it to ensure a fresh query result? But I wanted to make sure.

While we're at it, do I need to add ob_end_flush(), too? I saw this in the example, but I really don't get the difference:

while (ob_get_level() > 0) { ob_end_flush(); }
flush();

if (connection_aborted()) break;

sleep(1);

[developer.mozilla.org...]

not2easy

12:23 pm on Nov 24, 2022 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



Did you get this worked out?

csdude55

6:19 pm on Nov 24, 2022 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I don't have an answer yet, no. The script works, I'm just trying to make it faster. When it goes live and starts having 20,000 people with a persistent connection, I want to make sure that it's efficient enough to not crash.

I'm kinda confused about the "persistent connection" thing, anyway. When I run this and look in the console, I see the script running over and over with a process time of about 100ms each. Does this mean that it's running a MySQL query 10 times per second? If so, should I add a sleep(10); or something?

robzilla

8:52 pm on Nov 24, 2022 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



This is more of a PHP question than Javascript/AJAX, and I'm confused about your PHP code. Is that script meant to run continuously (and missing those bits in your sample) or only once (which is what the above code implies)? In other words, is it actually streaming?

so I THINK that I should free it to ensure a fresh query result

A "fresh query result" has nothing to do with mysqli_free_result(). The query result is "fresh" whenever you execute the query (overwriting some variable, presumably) and flush/stream the results to the client.

mysqli_free_result() frees up the memory used to store the query results. If you were to make the script sleep for 10 seconds between runs, and the result set is significant enough (or the number of simultaneous users large enough), then yes it might make sense to free up the memory before sleep.

Does this mean that it's running a MySQL query 10 times per second? If so, should I add a sleep(10); or something?

If your script is indeed running in a while loop without sleep (eek!) then for each streaming client it would constantly be firing mysql queries until the server goes bust. With 20,000 users that would be like suicide, a self-DDOS. So yes, a bit of sleep might be good in that scenario.

May I ask why you're streaming and not polling?

csdude55

4:37 am on Nov 25, 2022 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



This is more of a PHP question than Javascript/AJAX

I debated on whether to post it here, PHP, or SQL! I guess it's technically a MySQL question since I'm asking about free_result(), but I posted here because I thought that the answer might be specific to EventSource.

Is that script meant to run continuously (and missing those bits in your sample) or only once (which is what the above code implies)? In other words, is it actually streaming?

I don't have a loop coded in the PHP, no, it's pretty much exactly what I have here. It does work to immediately show when something is updated in MySQL, though, which I guess is through the magic of the persistent connection? But like I said, I'm not entirely clear on how that works.

May I ask why you're streaming and not polling?

After I upgraded servers, I finally had access to HTTP/2. This was one of those cool new features that I could finally use, so I thought it might improve the user experience if I didn't have to reload the connection every time.

Before, I just used setTimeout() to refresh the ajax every 15 seconds.

So yes, a bit of sleep might be good in that scenario.

I tried adding sleep(15) to the end of the PHP script, but that resulted in a delay of 15 seconds before it displayed the first result! I'm going to have to play with that one a bit, I think.

robzilla

11:05 am on Nov 26, 2022 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



If you don't have a loop, the script is not running continuously server-side, so how can it stream to the client? I don't know what's happening in the browser right now if PHP keeps closing the connection when script execution ends, maybe it's constantly setting up the "stream" anew? That would amount to the same as constantly polling.

So to actually stream, I'd think you'd need a while loop that keeps the script running and sending data. Then make sure you put sleep() after flush(). If it's not flushing, you may need to adjust some server settings.

PHP is not a great choice for streaming, by the way. Each client would keep a thread occupied on the server, you may run out of available workers and/or memory quite quickly. Polling is probably less expensive since there are no sleeping processes.