PHP class and var memory size confusion - php

i've written this code to test the size of some objects in PHP
<?php
class MyClass
{
public $string1="first string";
public $string2="second string";
public $string3="third string";
public function __toString() {
return $this->string;
}
}
function mem() {
return memory_get_usage(false);
}
$before = mem();
$class = new MyClass;
var_dump("new object size: ".(mem() -$before));
$before=mem();
$string = "test";
var_dump("string size: ".(mem() -$before));
$before=mem();
$objcopy = $class;
var_dump("object copy size: ".(mem() -$before));
$before=mem();
$objref = &$class;
var_dump("object reference size: ".(mem() -$before));
and this is the output in my system:
string(20) "new object size: 188"
string(15) "string size: 80"
string(20) "object copy size: 44"
string(25) "object reference size: 72"
i'm quite confusing now, why do we have: $class>$string>$objref>$objcopy
shouldn't be instead : $class=$objcopy>$string>$objref ?
$objcopy in fact contains 3 strings inside, instead $string is a single one..
could someone explain me how php handle memory with this kind of object?
thanks in advance.

You're observations base on wrong assumptions.
First of all, your $objcopy is a reference to the same instance as $class, because Instances are not cloned when assigning them to another variable. Check the manual or add this to your code:
$objcopy->string1 = 'a';
echo $class->string1, "\n";
Second, even if the assignment operator would effectively make them point to different objects, PHP would probably not allocate new memory because it uses copy-on-write optimization, see http://php.net/manual/en/internals2.variables.intro.php.
Finally, you can't expect precise memory informations returned by PHP. It may allocate more than the current statement requires and may implicitly free memory by the garbage collector. (Well, at least you can turn that off.)

Yes my question was based on wrong knowledge derived by C++ and other languages reference point of view.
So , after long research , i've created a post on my blog about this argument where i explain in depth how php handle memory.
http://hyperweb2.com/home/blog/2013/10/11/php-reference-vs-copy-vs-clone/

Related

Why get_memory_peak_usage() is greater than get_memory_usage()

I'm trying to figure out this: if get_memory_usage() prints memory, used by script when this function was called, then every time this memory count should always increase or shouldn't change (actually, this is happening when I'm trying to get this usage multiple times after some lines of my code). And I've noticed that get_memory_peak_usage() is greater than the last result of get_memory_usage(), and how can it be if get_memory_usage() fixes already used memory, so this value can't decrease?
Script:
echo "\n" . 'Used: '.memory_get_usage().' bytes';
$array = array("1" => "value", "foo" => "bar",);
echo "\n" . 'Used: '.memory_get_usage().' bytes';
echo "\n" . 'Peak: '.memory_get_peak_usage().' bytes';
PHP has dynamic memory management that frees memory that is no longer needed.
The currently required memory (get_memory_usage()) changes during the execution of a PHP script. get_memory_peak_usage() always gets the maximum memory required.
Therefore get_memory_peak_usage() is always greater than get_memory_usage().
The memory is also used by PHP statements, functions, classes, etc.
Sufficiently large arrays must be used to demonstrate how memory management works.
Let's look at the following code:
function printMemUse(string $comment){
printf('%s : %dk/%dk<br>',
$comment,
memory_get_usage()/1024,
memory_get_peak_usage()/1024
);
}
function proc1(){
$arr = array_fill(0,6000,'a string');
return $arr[2000];
}
printMemUse('start');
$arr = array_fill(0,6000,'a string');
printMemUse('first array filled');
proc1();
printMemUse('after function called');
$arr2 = array_fill(0,6000,'a string');
printMemUse('secondarray2 filled');
$arr = null;
printMemUse('first arr set null');
$arr2 = null;
printMemUse('arr2 set null');
Output:
start : 376k/413k
first array filled : 637k/637k
after function called : 637k/897k
secondarray2 filled : 897k/897k
first arr set null : 637k/897k
arr2 set null : 377k/897k
The first value is memory_get_usage() as kByte, the second memory_get_peak_usage() kByte.
Variables in a function are released again after the end. We're just seeing a new maximum (after function called). This memory is then used by the 2nd array. The maximum value does not increase. With the assignment of NULL, the memory for the arrays is also no longer required.
Try a little yourself in the PHP sandbox.

Arrow operator in PHP vs C

I am a PHP programmer trying to learn more of the theory behind PHP, but having trouble connecting the dots between PHP and C. For example, is the arrow operator exactly the same in PHP and C?
Here's what I came up when I researched it:
In C, -> is just an alias, a->b is the same as (*a).b. The arrow operator is just dereferencing a pointer so you interact with the address variable.
In PHP, -> is a reference. It "references the attributes of an instantiated object" (Unknown). But is that the same thing as C?
Note: Today, I learned what pointers are in C.
In PHP, -> is used to access members of a class. C does not have classes.
The closest thing is a struct.
In PHP
class Animal {
public $color;
public $age;
}
$fido = new Animal;
$fido->color = 'white';
$fido->age = 3;
$kitty = new Animal;
$kitty->color = 'brown';
$kitty->age = 5;
// output
echo 'Fido is ' . $fido->color . "age=". $fido->age . "\n";
echo 'Kitty is ' . $kitty->color . "age=". $kitty->age . "\n";
Output is:
Fido is white age=3
Kitty is brown age=5
You can do something similar in C using structs. It's a bit more involved.
Excuse my C. It's quite rusty
struct Animal {
int age;
char color[50];
};
int size = sizeof(struct Animal);
struct Animal * fido = malloc(size);
struct Animal * kitty = malloc(size);
fido->age = 3;
strcpy(fido->color, "white");
kitty->age = 5;
strcpy(kitty->color, "brown");
printf("Fido is %s age=%d\n", fido->color, fido->age);
printf("Kitty is %s age=%d\n", kitty->color, fido->age);
Unless you really want to get into the underlying details, don't overthink PHP references. What that means is that they don't pass around the actual values when doing function calls etc.
Don’t try too hard to find equivalence between the two languages. Their semantics are simply too different, so this will fail.
That said, the dereference operator -> in PHP was likely chosen to visually resemble the member access operator -> in C, and the semantics are somewhat similar, in that both allow you to access a member of a dereferenced object.
I’m not sure what you mean by “In C, -> is just an alias”: The C language has a concept of “alias”, but it’s completely unrelated with the topic at hand.
Rather, -> is an operator, and the expression a->b is defined to be equivalen to (*a).b, as you said correctly. But unlike you said, the object doesn’t need to be allocated on the heap, it can be anywhere in memory. Consider the following:
struct foo {
int i;
};
int main(void) {
struct foo f = {42};
struct foo *pf = &f;
printf("f.i = %d\n", pf->i);
}
Here, pf->i is equivalent to f.i (or (*pf).i). In no case is i allocated on the heap.
In php arrow -> is used to access function of a class.
class A{
function funA(){
return "Hello World";
}
}
$object1 = new A();
$object1->funA;
Object will be
Hello World
You can also access nested objects by arrow operator in PHP.
We will convert string to object. Here is my string:
{
"id":"123456",
"msg":"Have a Nice Day",
"is_active":false,
"total_count":1
}
IF i encode it to JSON
$obj = json_decode($json, false);
I can easily get object value by -> operator
$obj->msg;
OutPut will be
Have a Nice Day
You can do similar in C by using structs.

Executing MySQL Queries and Creating Instances several Times within Loop

I have an Web Application that requires SELECT and INSERT Querying to MySQL database and Instantiating a PHP class using new operator almost more that thousand times within a loop. May be there are alternatives to my present logic, but my point is that is there any harm if I carry on this logic?. I don't bother about the time complexity associated with the algorithm presently but **worrying much about if anything goes wrong during transaction or memory usage. I am giving the piece of code for reference
$stm_const = "select ce.TIMETAKEN, qm.QMATTER as STRING1, ce.SMATTER as STRING2 from w_clkexam ce, clkmst cm, qsmst qm where ce.QID=qm.QID and cm.ROLLNO=ce.ROLLNO";
for ($c=0; $c < count($rollnos); $c++) {
$stm3 =$stm_const." "."and ce.ROLLNO='$rollnos[$c]'";
$qry3 = mysql_query($stm3) or die("ERROR 3:".mysql_error());
while($row1 = mysql_fetch_array($qry3)) {
echo $string1=$row1['STRING1'];
echo $string2=$row1['STRING2'];
$phpCompareStrings=new PhpCompareStrings($string2, $string1);
$percent=$phpCompareStrings->getSimilarityPercentage();
$percent2=$phpCompareStrings->getDifferencePercentage();
echo '$string1 and $string2 are '.$percent.'% similar and '.$percent2.'% differnt<br/>';
}// end while
}// end for
Please help, I am waiting for opinions from you so that I can move further. Thanks in advance.
I don't see any problem there. You just get all the rows from database and for each row compare the strings. As you assign the object to the same variable each time, the old object is destroyed before the new object is created. So you have only one instance of the object in memory at all times. The question is what you want to do with the results? Only print them as in your example, or to store the results for further processing?
Anyway, I think it is not possible to optimize your code without modifying the class. If you are using this class, you can try to modify it so that it can accept multiple strings. Using this, you can create only 1 instance of the class and you avoid destroying/creating the object for every row. It will save you some CPU time, but not memory (as at all times, only 1 instance of the class is active).
Untested modification below:
Modify this function inside the class:
function __construct($str1,$str2){
$str1=trim($str1);
$str2=trim($str2);
if($str1==""){ trigger_error("First parameter can not be left blank", E_USER_ERROR); }
elseif($str2==""){ trigger_error("Second parameter can not be left blank", E_USER_ERROR); }
else{
$this->str1=$str1;
$this->str2=$str2;
$this->arr1=explode(" ",$str1);
$this->arr2=explode(" ",$str2);
}
}
To these 2 functions:
function init($str1,$str2){
$str1=trim($str1);
$str2=trim($str2);
if($str1==""){ trigger_error("First parameter can not be left blank", E_USER_ERROR); }
elseif($str2==""){ trigger_error("Second parameter can not be left blank", E_USER_ERROR); }
else{
$this->str1=$str1;
$this->str2=$str2;
$this->arr1=explode(" ",$str1);
$this->arr2=explode(" ",$str2);
}
}
function __construct($str1,$str2){ $this->init($str1,$str2); }
Then create the object outside the loop and only call $phpCompareStrings->init($string2,$string1) inside the loop.

How do you debug php "Out of Memory" issues?

I've had some issues lately with PHP memory limits lately:
Out of memory (allocated 22544384) (tried to allocate 232 bytes)
These are quite the nuisance to debug since I'm not left with a lot of info about what caused the issue.
Adding a shutdown function has helped
register_shutdown_function('shutdown');
then, using error_get_last(); I can obtain information about the last error, in this case, the "Out of memory" fatal error, such as the line number, and the php file name.
This is nice and all, but my php program is heavily object oriented. An error deep in the stack doesn't tell me much about the control structure or the execution stack at the moment of the error. I've tried debug_backtrace(), but that just shows me the stack during shutdown, not the stack at the time of the error.
I know I can just raise the memory limit using ini_set or modifying php.ini, but that doesn't get me any closer to actually figuring out what is consuming so much memory or what my execution flow looks like during the error.
Anyone have a good methodology for debugging memory errors in advanced Object Oriented PHP programs?
echo '<pre>';
$vars = get_defined_vars();
foreach($vars as $name=>$var)
{
echo '<strong>' . $name . '</strong>: ' . strlen(serialize($var)) . '<br />';
}
exit();
/* ... Code that triggers memory error ... */
I use this to print out a list of currently assigned variables just before a problem section of my code, along with a (very) rough estimate of the size of the variable. I go back and unset anything that isn't needed at and beyond the point of interest.
It's useful when installing an extension isn't an option.
You could modify the above code to use memory_get_usage in a way that will give you a different estimate of the memory in a variable, not sure whether it'd be better or worse.
Memprof is a php extension that helps finding those memory-eaters snippets, specially in object-oriented codes.
This adapted tutorial is quite useful.
Note: I unsuccessfully tried to compile this extension for windows. If you try so, be sure your php is not thread safe. To avoid some headaches I suggest you to use it under *nix environments.
Another interesting link was a slideshare describing how php handles memory. It gives you some clues about your script's memory usage.
I wonder is perhaps your thinking regards methodology is flawed here.
The basic answer to your question - how do I find out where this error is occurring? - has already been answered; you know what's causing that.
However, this is one of those cases where the triggering error isn't really the problem - certainly, that 232 byte object isn't your problem at all. It is the 20+Megs that was allocated before it.
There have been some ideas posted which can help you track that down; you really need to look "higher level" here, at the application architecture, and not just at individual functions.
It may be that your application requires more memory to do what it does, with the user load you have. Or it may be that there are some real memory hogs that are unnecessary - but you have to know what is necessary or not to answer that question.
That basically means going line-by-line, object-by-object, profiling as needed, until you find what you seek; big memory users. Note that there might not be one or two big items... if only it were so easy! Once you find the memory-hogs, you then have to figure out if they can be optimized. If not, then you need more memory.
Check the documentation of the function memory_get_usage() to view the memory usage in run time.
Website "IF !1 0" provides a simple to use MemoryUsageInformation class. It is very useful for debugging memory leaks.
<?php
class MemoryUsageInformation
{
private $real_usage;
private $statistics = array();
// Memory Usage Information constructor
public function __construct($real_usage = false)
{
$this->real_usage = $real_usage;
}
// Returns current memory usage with or without styling
public function getCurrentMemoryUsage($with_style = true)
{
$mem = memory_get_usage($this->real_usage);
return ($with_style) ? $this->byteFormat($mem) : $mem;
}
// Returns peak of memory usage
public function getPeakMemoryUsage($with_style = true)
{
$mem = memory_get_peak_usage($this->real_usage);
return ($with_style) ? $this->byteFormat($mem) : $mem;
}
// Set memory usage with info
public function setMemoryUsage($info = '')
{
$this->statistics[] = array('time' => time(),
'info' => $info,
'memory_usage' => $this->getCurrentMemoryUsage());
}
// Print all memory usage info and memory limit and
public function printMemoryUsageInformation()
{
foreach ($this->statistics as $satistic)
{
echo "Time: " . $satistic['time'] .
" | Memory Usage: " . $satistic['memory_usage'] .
" | Info: " . $satistic['info'];
echo "\n";
}
echo "\n\n";
echo "Peak of memory usage: " . $this->getPeakMemoryUsage();
echo "\n\n";
}
// Set start with default info or some custom info
public function setStart($info = 'Initial Memory Usage')
{
$this->setMemoryUsage($info);
}
// Set end with default info or some custom info
public function setEnd($info = 'Memory Usage at the End')
{
$this->setMemoryUsage($info);
}
// Byte formatting
private function byteFormat($bytes, $unit = "", $decimals = 2)
{
$units = array('B' => 0, 'KB' => 1, 'MB' => 2, 'GB' => 3, 'TB' => 4,
'PB' => 5, 'EB' => 6, 'ZB' => 7, 'YB' => 8);
$value = 0;
if ($bytes > 0)
{
// Generate automatic prefix by bytes
// If wrong prefix given
if (!array_key_exists($unit, $units))
{
$pow = floor(log($bytes) / log(1024));
$unit = array_search($pow, $units);
}
// Calculate byte value by prefix
$value = ($bytes / pow(1024, floor($units[$unit])));
}
// If decimals is not numeric or decimals is less than 0
// then set default value
if (!is_numeric($decimals) || $decimals < 0)
{
$decimals = 2;
}
// Format output
return sprintf('%.' . $decimals . 'f ' . $unit, $value);
}
}
Use xdebug to profile memory usage.

Does PHP copy variables when retrieving from shared memory?

If I run an shm_get_var(), will it return a "reference", keeping the data in shared memory?
I'm wanting to keep an array about 50MB in size in shared memory so that it can be used by multiple processes without having to keep multiple copies of this 50MB array hanging around. If shared memory isn't the answer, does anyone have another idea?
This is the relevant C code snippet from sysvsem.c in PHP 5.2.9 :
/* setup string-variable and serialize */
/* get serialized variable from shared memory */
shm_varpos = php_check_shm_data((shm_list_ptr->ptr), key);
if (shm_varpos < 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "variable key %ld doesn't exist", key);
RETURN_FALSE;
}
shm_var = (sysvshm_chunk*) ((char *)shm_list_ptr->ptr + shm_varpos);
shm_data = &shm_var->mem;
PHP_VAR_UNSERIALIZE_INIT(var_hash);
if (php_var_unserialize(&return_value, (const unsigned char **) &shm_data, shm_data + shm_var->length, &var_hash TSRMLS_CC) != 1) {
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "variable data in shared memory is corrupted");
RETURN_FALSE;
}
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
PHP will have to unserialize the entire value every time you call shm_get, which, on a 50MB array, is going to be really really slow.
How about breaking it up into individual values?
Also you might want to consider using APC's variable cache, which will handle all of the shared memory and locking for you (and will also use a hash table for key lookups)
I'm no expert on this, but would it be possible to write a quick test for this something like the following?
$key = 1234;
//put something small into shared memory
$identifier = shm_attach($key, 1024, 0777);
shm_put_var($identifier, $key, 'shave and a hair cut');
$firstVar = shm_get_var($identifier, $key);
$firstVar .= 'Test String of Doom';
$secondVar = shm_get_var($identifier, $key);
if ($firstVar == $secondVar) {
echo 'shm_get_var passes by reference';
} else {
echo 'shm_get_var passes by value';
}
form the wording of the documentation
shm_get_var() returns the variable
with a given variable_key , in the
given shared memory segment. The
variable is still present in the
shared memory.
I would say yes it's a reference to the shared memory space.
you can use shm_remove()
Check this out: http://php.net/manual/en/function.shm-remove.php

Categories