Processing large data sets via AJAX brings no speed benefits
I have several time consuming database queries to run. Each has been built to be triggered from an option chosen on a web page. I thought I was being quite cunning by firing off the work via several AJAX requests.
I presumed that multiple requests would be split over multiple processes/threads meaning the work would be completed relatively quickly for the user.
However, the requests seem to be processed in serial, meaning that no speed benefit is felt by the user.
Worse still, AJAX requests to update the page also wait in line, meaning they fail to respond until the previous requests have all completed.
I have read that this may be caused by the PHP sessions being locked.
What is the usual approach for this kind of issue?
- Is there a way to force AJAX requ开发者_C百科ests to work asynchronously?
- Can I stop PHP from locking the sessions?
- Should I use a seperate process via cron to fire background workings?
Thanks!
NB This project has been built using the symfony framework.
AJAX uses jQuery
// Get the content
$.get('/ajax/itemInformation/slug/'+slug, function(data) {
$('#modal-more-information').html(data);
});
If you are using sessions at all during any of the given AJAX requests, they will effectively execute serially, in order of request. This is due to locking of the session data file at the operating system level. The key to getting those requests to be asynchronous is to close (or never start) the session as quickly as possible.
You can use session_write_close
(docs) to close the session as soon as possible. I like to use a couple of helper functions for this, the set_session_var
function below will open the session, write the var, then close the session - in and out as quickly as possible. When the page loads, you can call session_start
to get the $_SESSION
variable populated, then immediately call session_write_close
. From then on out, only use the set function below to write.
The get function is completely optional, since you could simply refer to the $_SESSION
global, but I like to use this because it provides for a default value and I can have one less ternary in the main body of the code.
function get_session_var($key=false, $default=null) {
if ($key == false || strlen($key) < 0)
return false;
if (isset($_SESSION[$key]))
$ret = $_SESSION[$key];
else
$ret = $default;
return $ret;
}
function set_session_var($key=false, $value=null) {
if ($key == false || strlen($key) < 0)
return false;
session_start();
if ($value === null)
unset($_SESSION[$key]);
else
$_SESSION[$key] = $value;
session_write_close();
}
Be aware that there are a whole new set of considerations once the AJAX requests are truly asynchronous. Now you have to watch out for race conditions (you have to be wary of one request setting a variable that can impact another request) - for you see, with the sessions closed, one request's changes to $_SESSION
will not be visible to another request until it rebuilds the values. You can help avoid this by "rebuilding" the $_SESSION
variable immediately before a critical use:
function rebuild_session() {
session_start();
session_write_close();
}
... but this is still susceptible to a race condition.
精彩评论