Keeping in mind of server load, I want to know whether each call to session is a separate call to server which increases server load?
Let me explain it little bit. Suppose in each php page, I have to set 10 session data and have to call 10 session data also like this:
$_SESSION['a']=1;
$_SESSION['b']=2;
$_SESSION['c']=3;
$_SESSION['d']=4;
$_SESSION['e']=5;
$_SESSION['f']=6;
$_SESSION['g']=7;
$_SESSION['h']=8;
$_SESSION['i']=9;
$_SESSION['j']=10;
echo $_SESSION['a'];
echo $_SESSION['b'];
echo $_SESSION['c'];
echo $_SESSION['d'];
echo $_SESSION['e'];
echo $_SESSION['f'];
echo $_SESSION['g'];
echo $_SESSION['h'];
echo $_SESSION['i'];
echo $_SESSION['j'];
setting of above 10 sessions and outputting the same, will these be 20 separate calls to server or by session_start(), whole session data is loaded at once during page loading?
Also want to know how to store multidimensional associative array in session? Suppose I want to set the above 10 session data like this:
$_SESSION['mydata']=array(
a=>1,
b=>2,
c=>3,
d=>4,
e=>5,
f=>6,
g=>7,
h=>8,
i=>9,
j=>10
)
echo $_SESSION['mydata']['a'];
By the above example I can reduce server loads if each session call is separate call to server.
Anyone clear me what's going on when we set and get session data?
Here is the breakdown of a session
session_start(); either creates a session file on the hard drive or accesses one if it is already there. It is a serialized array
This array gets loaded into memory and is manipulated within memory until the script finishes executing or you can force it to re-write the file with session_write_close()
You can add/remove as much data as you wish after you have started the session because it is no different than manipulating an array.
The heavy lifting is done at session_start and session_write_close because that is when PHP actually has to access the hard drive
In theory each user can have a 4GB session file on a FAT32 server, or larger on NTFS server, but I am sure you can imagine the horrendous performance issues that would arise.
The whole execution of your script is done in one request. By setting $_SESSION['foo']='bar' and $_SESSION['baz']='biz' you don't set two different sessions but rather two session variables.
So the whole session is loaded on script start, not page load (that's a client-side term).
It's all being done with cookies.
EDIT, to answer your comment:
As others mentioned (see Mark Baker's comment) the session is loaded once, right before the script kicks off, and stored once after script end (unless you explicitly call session_write_close())
Sure, size matters. Apparently, the bigger the session the longer it will take to be loaded/stored. But that would be the last thing you would bother to optimize.
Benchmark for session
For $_SESSION['mydata']['key'] = 'value' :
session_start();
$time_begin = microtime(true);
$mem_start = memory_get_usage();
for ($i=0; $i < 100000; $i++) {
$_SESSION['mydata']["a$i"] = $i;
}
foreach ($_SESSION['mydata'] as $key => $value) {
$r = $value;
}
$mem_end = memory_get_usage();
$time_end = microtime(true);
echo "Time :";
echo $time_end - $time_begin;
echo "<br>";
echo "Memory :";
echo $mem_end - $mem_start;
My result about $_SESSION['mydata']['key']:
Time :0.57849311828613
Memory :464
For $_SESSION['key'] = 'value' :
<?php
session_start();
$time_begin = microtime(true);
$mem_start = memory_get_usage();
for ($i=0; $i < 100000; $i++) {
$_SESSION["a$i"] = $i;
}
for ($i=0; $i < 100000; $i++) {
$r = $_SESSION["a$i"];
}
$mem_end = memory_get_usage();
$time_end = microtime(true);
echo "Time :";
echo $time_end - $time_begin;
echo "<br>";
echo "Memory :";
echo $mem_end - $mem_start;
My result about $_SESSION['mydata']:
Time :0.47217416763306
Memory :176
EDITED : In the first PHP Script memory spented by the mydata array and the other mydata's keys.So, second way is greater again.
So , using $_SESSION['key'] = 'value' is greater than $_SESSION['my']['key'] = 'value'.
This can be a reason that when you want to set a value to $_SESSION['my']['key'], php should get $_SESSION['my'] and after that it can be create new var. in the $_SESSION['my']['key']
Related
I am writing a PHP script which, upon a request, will make a call to a SOAP service with various parameters, some of which are taken from the request.
However, the particular SOAP service I am using requires that each request includes a unique ID, which in this case needs to increment for each request. It must not be based on time, and must be unique for each request, however it does not matter if values are skipped.
Using a MySQL data base to store a single value seems massively overkill. I have thought about storing and loading it into a file, but the issue of race conditions springs to mind.
I do have complete access to the server, which will be some kind of Linux flavour dedicated to this task.
Is there a simple way this can be achieved?
Before any new request get incremental value using PHP's time() function, since time will be unique for each request.
$increment_id = time();
If your application is single server you can try to store incremental ID in APC using:
$key = 'soap_service_name';
if (!apc_exists($key)) {
apc_store($key, 0);
}
$id = apc_inc($key);
You need to check if a key exists in APC cache and set 0, otherwise apc_inc fails and returns false
If you have multiserver application you can store incremental id in Memcache/Redis (that needs to run additional service):
$key = 'soap_service_name';
$memcache = memcache_connect('memcache_host', 11211);
if (!empty(memcache_exists($memcache, $key))) {
memcache_set($memcache, 0);
}
$id = memcache_increment($memcache, $key);
Same situation as APC if you call memcache_increment it will fail if key doesn't exists yet.
If that incremental ID should be stored persistently Redis would be more usefull because it has disk write of all data. It's kind of Memcache with disk write.
This is how I achieved this in the end. After considering the various options, databases and the various caching options seemed a bit overkill. In addition, caching, cookies and sessions seem to be designed to be relatively temporary, whereas I was really looking for a non-volatile solution.
This is what I came up with - a simple file locking solution. I hadn't realised PHP could deal with file locks but on discovering this, it seems the best way to go.
This example acquires an exclusive lock on the file, before reading and updating the value. If it hits max int, it resets. Then it waits for 5 seconds. If the script is called a few times in quick succession, observe that each request will wait for the lock to be release from the previous before continuing.
What's nice is, as this is PHP, non-existent file, invalid contents etc, will just cause the value to default to zero.
<?php
$f = fopen('sequence_num.txt', 'r+');
echo "Acquiring lock<br />\n";
flock($f, LOCK_EX);
echo "Lock acquired, updating value<br />\n";
$num = intval(fread($f, strlen(PHP_INT_MAX)));
echo "Old val = " . $num;
if ($num >= PHP_INT_MAX) {
$num = 0;
} else {
$num++;
}
echo " New val = " . $num;
echo "<br />Waiting 5 seconds<br />\n";
rewind($f);
ftruncate($f, 0);
fwrite($f, $num);
sleep(5);
echo "Releasing lock<br />\n";
flock($f, LOCK_UN);
fclose($f);
If you're happy to use a float as a unique value use:
$unique_id = microtime(true);
If you wish to simply increment, you may do so using a session var:
/**
* Get session increment.
*
* #param string $id
* #param int $default
* #return int
*/
function get_increment($id, $default = 0)
{
if (array_key_exists($id, $_SESSION)) $_SESSION[$id] += 1;
else $_SESSION[$id] = $default;
return $_SESSION[$id];
}
var_dump(get_increment('unique_id'));
I have a php file(ext.php) which has the PHP code as:
<?php
$i = 0;
while($i < 1000){
echo $i;
ob_flush();
flush();
sleep(1);
$i++;
}
?>
I have to include ext.php into my application's index.php, my consideration is:
$i should be assigned with 0 only once through application
You mean once in execution or one even if you have multiple requests? You can use include_once.php for execution problem, or save $i in session for multiple requests problem.
I have a .php script that I use for creating the list of my products.
I am on shared hosting, so I can't do a lot of queries otherwise I get a blank page.
This is how I use my script now:
script.php?start=0&end=500&indexOfFile=0 ->> make a product0.txt file with first 500 products
script.php?start=501&end=1000&indexOfFile=1 ->> product1.txt file with another 500 products
script.php?start=1001&end=1500&indexOfFile=2 ->> product2.txt file with last 500 products
How can I modify the script so it will make all these files automatically, so that I don't have to change each time the link manually?
I would like to click a button which will do this:
make the product0.txt file with the first 500 products
wait 5 seconds
make the product1.txt file with with another 500 products
wait 5 seconds
make the product2.txt file with the last 500 products
use:
sleep(NUMBER_OF_SECONDS);
before starting your actions, use
sleep(5);
or:
usleep(NUMBER_OF_MICRO_SECONDS);
In Jan2018 the only solution worked for me:
<?php
if (ob_get_level() == 0) ob_start();
for ($i = 0; $i<10; $i++){
echo "<br> Line to show.";
echo str_pad('',4096)."\n";
ob_flush();
flush();
sleep(2);
}
echo "Done.";
ob_end_flush();
?>
i use this
$i = 1;
$last_time = $_SERVER['REQUEST_TIME'];
while($i > 0){
$total = $_SERVER['REQUEST_TIME'] - $last_time;
if($total >= 2){
// Code Here
$i = -1;
}
}
you can use
function WaitForSec($sec){
$i = 1;
$last_time = $_SERVER['REQUEST_TIME'];
while($i > 0){
$total = $_SERVER['REQUEST_TIME'] - $last_time;
if($total >= 2){
return 1;
$i = -1;
}
}
}
and run code =>
WaitForSec(your_sec);
Example :
WaitForSec(5);
OR
you can use sleep
Example :
sleep(5);
I am on shared hosting, so I can't do a lot of queries otherwise I get a blank page.
That sounds very peculiar. I've got the cheapest PHP hosting package I could find for my last project - and it does not behave like this. I would not pay for a service which did. Indeed, I'm stumped to even know how I could configure a server to replicate this behaviour.
Regardless of why it behaves this way, adding a sleep in the middle of the script cannot resolve the problem.
Since, presumably, you control your product catalog, new products should be relatively infrequent (or are you trying to get stock reports?). If you control when you change the data, why run the scripts automatically? Or do you mean that you already have these URLs and you get the expected files when you run them one at a time?
In https://www.php.net/manual/es/function.usleep.php
<?php
// Wait 2 seconds
usleep(2000000);
// if you need 5 seconds
usleep(5000000);
?>
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Headers already sent by PHP
Below is a simple example of my PHP code which (I hope so) is self explanatory. What I try to do is to update the session variable. But the output of the script is as follows:
Warning: session_start()
[function.session-start]: Cannot send
session cookie - headers already sent
by (output started at
/Library/WebServer/Documents/facebook/test.php:8)
in
/Library/WebServer/Documents/facebook/test.php
on line 11
The warning is caused by the echo statements in line 8 and 9, of course. Is there any simple solution to stop this warning.
Thanks for any pointers, Andrej
<?php
session_start();
$_SESSION['percent'] = 0;
$iterations = 50;
for ($i = 0; $i <= iterations; $i++) {
$percent = ($i / $iterations) * 100;
echo "Hello World!";
echo "<br />";
// update session variable
session_start();
$_SESSION['percent'] = number_format($percent, 0, '', '');
session_commit();
}
?>
The only solution that works (i.e. updates the session variable) for me is:
<?php
ob_start();
session_start();
$_SESSION['percent'] = 0;
$iterations = 50;
for ($i = 0; $i <= 50; $i++) {
$percent = ($i / $iterations) * 100;
echo "Hello World!";
echo "<br />";
// update session variable
session_start();
$_SESSION['percent'] = number_format($percent, 0, '', '');
session_commit();
}
ob_flush();
?>
It's ugly, while it buffers the output first...
Remove the session_start() from inside the for loop.
Put the session_commit() outside the for loop at the very end.
Both these functions should only be called once in a script.
It's not possible to set cookies (or send any other headers) after output is started. You could add ob_start() at line 1 to buffer the output.
The right solution is to separate logic from the output. Check out e.g.
http://www.paragoncorporation.com/ArticleDetail.aspx?ArticleID=21
If you don't have any previeus output before the session-start() statement,then try to resave your .php file as an ansi-file or as utf-8 without BOM file.
that's bc in some cases the editor itself writes things as an output in the file.
It worked for me
You have to execute the session_start() function only once. So just drop the one within the loop.
Also you don't have to do the session_commit() manually, in most cases PHP handles this for you automatically.
As the others have stated, the cause of the error is the second session_start() you are using. However, the actual reason it's throwing an error is because you are trying to set a header after you've already sent output. Since the session_start() function sets the session cookie, it tried to set the cookie header, which is after you already echo content.
Presumably there's some tiny performance hit, but beyond that?
As of PHP 4.3.3, calling session_start() while the session has already been started will result in an E_NOTICE warning. The second call to session_start() will simply be ignored.You could check if the session has been started first or not with:
if (session_id() == "")
session_start();
From the docs:
As of PHP 4.3.3, calling session_start() after the session was previously started will result in an error of level E_NOTICE. Also, the second session start will simply be ignored.
So no, it won't "cause harm", but it'll throw an error. And the fact that it's happening is probably an indicator that you're doing something incorrectly, and might need to re-think how your code is laid out.
Calling session_start(); can harm the performance of your application.
The following code will trigger an E_NOTICE, but won't harm that much performance wise
<?php
session_start();
session_start();
?>
But calling the following will harm the performance!
But it's still useful. If you have a script that takes like 3 minutes to run and is called with XHR (js).
In this case it's useful to use the session_write_close. otherwise the request to the server is blocked until the sessions are released. It could happen that you want to use the sessions at the start of the script and at the end of the script.
<?php
session_start();
session_write_close();
session_start();
?>
But, when you call the session_start(); all information is deserialized, and when you call session_write_closed() it's serialized.
So if you have a lot of data it can be really slow!
The following test shows how much impact it has.
1.0130980014801 sesion_start + close with empty session
1.0028710365295 normal loop without session
12.808688879013 a lot data in the session with start + close
1.0081849098206 normal loop again (useless kinda)
<?php
//start and clear first session
session_start();
session_destroy();
session_write_close();
//test one
if(true) {
//test loop one
$start = microtime(true);
for($i = 0; $i < 1000; $i++) {
session_start();
usleep(100);
session_write_close();
}
$end = microtime(true);
echo($end - $start);
//test loop 2
echo('<br />');
$start = microtime(true);
for($i = 0; $i < 1000; $i++) {
usleep(100);
}
$end = microtime(true);
echo($end - $start);
}
//fill the array with information so serialization is needed
session_start();
$_SESSION['test'] = array();
for($i = 0; $i < 10000; $i++) {
$_SESSION['test'][$i] = chr($i);
}
session_write_close();
echo('<br />');
//test two
if(true) {
//test loop one
$start = microtime(true);
for($i = 0; $i < 1000; $i++) {
session_start();
usleep(100);
session_write_close();
}
$end = microtime(true);
echo($end - $start);
//test loop 2
echo('<br />');
$start = microtime(true);
for($i = 0; $i < 1000; $i++) {
usleep(100);
}
$end = microtime(true);
echo($end - $start);
}
?>
Reading the docs for session_start, all I can see is:
As of PHP 4.3.3, calling session_start() after the session was previously started will result in an error of level E_NOTICE. Also, the second session start will simply be ignored.
So, you'll get an E_NOTICE and be ignored.
I usually put a session start statement in an include file that I require_once. But I don't think there should be an issue with multiple calls.
If it produces an error, odds are that the developers didn't intend for that particular action to occur. So yes, despite what you're shown by W3Schools, it's technically a 'bad' thing to do.
So, rather than play it safe and try to set the session on each page, why not first check to see if the session exists before you move forward?
if ( !isset($_SESSION) ) session_start();
Personally, I'd check for the existence of the session's cookie first.
If the session is already open, then it will return an error notice, and the new session will be ignored. So no harm is done, but you will have a pesky error.
But... if you are finding the need to do this then it could be a symptom that your code is not organized well. It would probably be in your benefit to see how you can keep yourself from repeating redundant tasks like starting a session.