PHP memory limit on line running foreach - php

Is there a more efficient way to set JSON array values than this?
for($i=0;$i<sizeOf($json['activity']);$i++){
$json['activity'][$i]['active'] = 'false';
}
I want to set all sub keys named 'active' to 'false'
The arrays are not huge, they are multi-dimension with about 8-10 sub arrays and I am running on XAMPP localhost.
I am getting
Allowed memory size of 134217728 bytes exhausted (tried to allocate 32 bytes)
error briefly and then the rest of the code runs OK on a setInterval. I have looked at ways to set the memory limit but suspect there must be a cleaner way to set the array keys.
Thank you

If I understand this correctly, you created an infinite loop since everytime it runs, your array gets one more value, same as your $i-counter. Try getting the count of the array first in a seperate variable and then run the loop with that
$c = sizeOf($json['activity']); for($i=0;$i<$c;$i++){
$json['activity'][$i]['active'] = 'false';
}

Related

Simple array push in PHP exceeds allowed memory. (Allowed memory size of 33554432 bytes exhausted (tried to allocate 33554440 bytes) )

This code is part of a bigger program but I identified this as the problem. I simply need to get the same values at the same indexes of arrays and this is the code I have written:
$a1=array(1,1,2);
$a2=array(1,2);
$a3=array(1,1);
$a4=array(1,1,3);
$a5=array(1,1,1,1);
$same= array();
for($i=0; $i<3; $i++){
while($a1[$i]==$a2[$i] && $a1[$i]==$a3[$i] && $a1[$i]==$a4[$i] && $a1[$i]==$a5[$i]){
array_push($same, $a1[$i]);
}
}
print_r($same);
and it gives me this error:
Allowed memory size of 33554432 bytes exhausted (tried to allocate 33554440 bytes)
Adding more memory here is not an option.
The problem is that you while loop runs infinitely
while($a1[$i]=$a2[$i]=$a3[$i]){
You see the equal sign? You just assign one value to another from right to left. If you want to check if all of them are equal you can do:
while($a1[$i] == $a2[$i] && $a1[$i] == $a3[$i] && $a2[$i] == $a3[$i]){
Overall, I think the code can & should be improved. You should not limit your for loop to a hardcoded number. Rather, limit it to the smallest array length. There are many ways to fix this issue.
Edit:
Your while loop runs infinitely because when index $i is zero, all values are equal and it gets stuck in the while loop. Replace the while loop with if. This will solve the memory size error, but you should also check if the keys exist before comparing them.

Why PHP Allowed memory size of 134217728 bytes exhausted?

I'm going over some problems from CodeEval and running into this strange error in PHP. I haven't run into anything like this with other languages, so I'm at a loss as to why this would happen. Without including the whole answer (and please don't help me find the solution, other than why PHP is acting this way), here's where I'm running into problems:
for ($j = 0; $j < count($beauty); $j++) {
$temp = $beauty[$j];
$beauty[$j] = $beauty[$j+1];
$beauty[$j+1] = $temp;
}
Essentially I've gotten a count of each individual letter and am now going to sort the array holding those values so I can determine the "beauty" of the string. Strange thing is I get the error:
Allowed memory size of 134217728 bytes exhausted
When running the above block of code. Even stranger, when I take out that final line in the for loop I stop getting the error.
for ($j = 0; $j < count($beauty); $j++) {
$temp = $beauty[$j];
$beauty[$j] = $beauty[$j+1];
}
Will work just fine, I just can't solve the problem that way. I was thinking maybe there was some strange thing, like PHP was passing the values in the array by reference, or passing values of variables in general by reference and maybe that was causing problems, but I don't see that that's the case. I can't see why setting the value of the following array position to the value I've stored in $temp would cause the program to eat up that much memory. The loop in this case is only for an array with a count of 19. I can't imagine how 19 integers are taking up 128Mb of space in memory, even if we're doing a swap on each pass.
Anyone know why this is happening?
You are creating an infinite loop at this line:
$beauty[$j+1] = $temp;
since in every iteration of the $beauty loop you are adding a new element your loop will never complete

Fatal error: Allowed memory size of 536870912 bytes exhausted

Im trying to build an array that needs to be passed to a report. Some of the data returned has similar field names so im using the function below to add a prefix to the array key names before merging the arrays, however i get an out of memory exception "Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 44 bytes) in ..", is there another way of adding prefix to array keys in an array that will not use alot of memory?
function prefixArrayKeys(&$_array,$prefix){
foreach($_array as $k=>$v){
$nk = $prefix.$k;
$nv = $v;
array_push($_array, array($nk=>$nv));
unset($_array[$k]);
}
var_dump($_array);
}
The call to the function:
$aSQL = "select sex, a_number, to_char(b_dtm, 'DD/MM/YYYY') b_dtm from atable where a_id = ".$ped_array[1]['D']."";
execute_sql($aSQL,$rsGTYPE);
prefixArrayKeys(&$rsGTYPE[0],"D");
if(count($rsGTYPE) > 0) $rowdata[0] = array_merge($rowdata[0],$rsGTYPE[0]);
Within your foreach loop, you are using array_push.
You are adding to the array you are iterating through, this is an infinite loop.
May be if you try to unset your $_array[$k] before to set the new one would makes it work?
Although I doubt that changes anything, except if the entry in huge...

Free PDO statement result from memory in loop

I am using the following code in an application based on ZF1:
$select = $db->select()->from('table', array('id', 'int', 'float'))->limit(10000, (($i - 1) * 10000));
$data = $select->query();
while ($row = $data->fetch()) {
# ...
}
This operation is happening in a foreach loop for some 800 times. I output the memory usage for each pass and can see it increasing by about 5MB per pass. I suppose that is because Zend apparently does not free the result from the query once the pass is complete. A simple unset didn't solve the issue. Using fetchAll also did not improve (or change) the situation.
Is there any way to free the result from a Zend_Db_Statement_PDO thus freeing the memory used by it? Or do you suspect another reason?
I believe you want to do this:
$sql = "SELECT something FROM random-table-with-an-obscene-large-amount-of-entries";
$res = $db->query($sql);
while ($row = $res->fetch(Zend_Db::FETCH_NUM)) {
// do some with the data returned in $row
}
Zend_Db::FETCH_NUM - return data in an array of arrays. The arrays are indexed by integers, corresponding to the position of the respective field in the select-list of the query.
Since you overwrite $row on each loop, the memory should be reclaimed. If you are paranoid you can unset($row) at the bottom of the loop I believe. I've not tested this myself recently, but I ran into a batch problem about a year ago that was similar, and I seem to recall using this solution.
Actually the problem was hidden somewhere else:
Inside the loop some integer results were stored in an array for modification at a later planned stage in the workflow.
While one might expect PHP arrays to be small, that is not the case: Arrays grow big really fast and a PHP array is on average 18 times larger than it is to be 'expected'. Watch out while working with arrays, even if you only store integers in them!
In case the linked article disappears sometime:
In this post I want to investigate the memory usage of PHP arrays (and values in general) using the following script as an example, which creates 100000 unique integer array elements and measures the resulting memory usage:
$startMemory = memory_get_usage();
$array = range(1, 100000);
echo memory_get_usage() - $startMemory, ' bytes';
How much would you expect it to be? Simple, one integer is 8 bytes (on a 64 bit unix machine and using the long type) and you got 100000 integers, so you obviously will need 800000 bytes. That’s something like 0.76 MBs.
Now try and run the above code. This gives me 14649024 bytes. Yes, you heard right, that’s 13.97 MB - eightteen times more than we estimated.

Problems with PHP when trying to create big array

Here is my code, which creates 2d array filled with zeros, array dimensions are (795,6942):
function zeros($rowCount, $colCount){
$matrix = array();
for ($rowIndx=0; $rowIndx<$rowCount; $rowIndx++){
$matrix[] = array();
for($colIndx=0; $colIndx<$colCount; $colIndx++){
$matrix[$rowIndx][$colIndx]=0;
}
}
return $matrix;
}
$matrix = zeros(795,6942);
And here is the error that I receive:
Allowed memory size of 134217728 bytes exhausted (tried to allocate 35 bytes)
Any ideas how to solve this?
As a quick calculation, you are trying to create an array that contains :
795*6942 = 5,518,890
integers.
If we consider that one integer is stored on 4 bytes (i.e. 32 bits ; using PHP, it not be less), it means :
5518890*4 = 22,075,560
bytes.
OK, quick calculation... result is "it should be OK".
But things are not that easy, unfortunatly :-(
I suppose it's related to the fact that data is stored by PHP using an internal data-structure that's much more complicated than a plain 32 bits integer
Now, just to be curious, let's modify your function so it outputs how much memory is used at the end of each one of the outer for-loop :
function zeros($rowCount, $colCount){
$matrix = array();
for ($rowIndx=0; $rowIndx<$rowCount; $rowIndx++){
$matrix[] = array();
for($colIndx=0; $colIndx<$colCount; $colIndx++){
$matrix[$rowIndx][$colIndx]=0;
}
var_dump(memory_get_usage());
}
return $matrix;
}
With this, I'm getting this kind of output (PHP 5.3.2-dev on a 64bits system ; memory_limit is set to 128MB -- which is already a lot !) :
int 1631968
int 2641888
int 3651808
...
...
int 132924168
int 133934088
Fatal error: Allowed memory size of 134217728 bytes exhausted
Which means each iteration of the outer for-loop requires something like 1.5 MB of memory -- and I only get to 131 iterations before the script runs out of memory ; and not 765 like you wanted.
Considering you set your memory_limit to 128M, you'd have to set it to something really much higher -- like
128*(765/131) = 747 MB
Well, even with
ini_set('memory_limit', '750M');
it's still not enough... with 800MB, it seems enough ;-)
But I would definitly not recommend setting memory_limit to such a high value !
(If you have 2GB of RAM, your server will not be able to handle more than 2 concurrent users ^^ ;; I wouldn't actually test this if my computer had 2GB of RAM, to be honest)
The only solution I see here is for you to re-think your design : there has to be something else you can do than use this portion of code :-)
(BTW : maybe "re-think your design" means using another language PHP : PHP is great when it comes to developping web-sites, but is not suited to every kind of problem)
The default PHP array implementation is very memory-intensive. If you are just storing integers (and lots of them), you probably want to look at SplFixedArray. It uses a regular contiguous memory block to store the data, as opposed to the traditional hash structure.
You should try increasing the amount of memory available to PHP:
ini_set('memory_limit', '32M');
in your PHP file.

Categories