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
Related
Consider this piece of code
$from = 486745904951485151;
$to = 486745904951485157;
$val = 486745904951485155;
for($i=$from; $i<=$to;$i++) {
if($i == $val) {
return true;
}
}
I need to do 8 iterations total, but because the $i does not equal 486745904951485151 but rather it is retyped to float so $i=4.8674590495149E+17 what I end up is getting infinite(-ish) loop, because the iteration condition never gets there to end the loop, because the $to is still integer.
I suppose this is some internal restriction of for iteration of php (docs were of no help), what is the best possible solution to handle the issue? I was thinking of didiving all the values by some factor of 10, so I artifically decrease the actual number, but was wondering if someone has some better idea to tackle this issue?
Additional info: yes, I am using 32bit PHP and version 5.6.3 (legacy app)
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';
}
I'm looking for a way to measure the amount of data stored in a PHP array. I'm not talking about the number of elements in the array (which you can figure out with count($array, COUNT_RECURSIVE)), but the cumulative amount of data from all the keys and their corresponding values. For instance:
array('abc'=>123); // size = 6
array('a'=>1,'b'=>2); // size = 4
As what I'm interested in is order of magnitude rather than the exact amount (I want to compare the processing memory and time usage versus the size of the arrays) I thought about using the following trick:
strlen(print_r($array,true));
However the amount of overhead coming from print_r varies depending on the structure of the array which doesn't give me consistent results:
echo strlen(print_r(array('abc'=>123),true)); // 27
echo strlen(print_r(array('a'=>1,'b'=>2),true)); // 35
Is there a way (ideally in a one-liner and without impacting too much performance as I need to execute this at run-time on production) to measure the amount of data stored in an array in PHP?
Does this do the trick:
<?php
$arr = array('abc'=>123);
echo strlen(implode('',array_keys($arr)).implode('',$arr));
?>
Short answer: mission impossible
You could try something like:
strlen(serialize($myArray)) // either this
strlen(json_encode($myArray)) // or this
But to approximate the true memory footprint of an array, you will have to do a lot more than that. If you're looking for a ballpark estimate, arrays take 3-8x more than their serialized version, depending on what you store in them and how many elements you have. It increases gradually, in bigger and bigger chunks as your array grows. To give you an idea of what's happening, here's an array estimation function I came up with, after many hours of trying, for one-level arrays only:
function estimateArrayFootprint($a) { // copied from one of my failed quests :(
$size = 0;
foreach($a as $k=>$v) {
foreach([$k,$v] as $x) {
$n = strlen($x);
do{
if($n>8192 ) {$n = (1+($n>>12)<<12);break;}
if($n>1024 ) {$n = (1+($n>> 9)<< 9);break;}
if($n>512 ) {$n = (1+($n>> 8)<< 8);break;}
if($n>0 ) {$n = (1+($n>> 5)<< 5);break;}
}while(0);
$size += $n + 96;
}
}
return $size;
}
So that's how easy it is, not. And again, it's not a reliable estimation, it probably depends on the PHP memory limit, the architecture, the PHP version and a lot more. The question is how accurately do you need this value.
Also let's not forget that these values came from a memory_get_usage(1) which is not very exact either. PHP allocates memory in big blocks in order to avoid a noticeable overhead as your string/array/whatever else grows, like in a for(...) $x.="yada" situation.
I wish I could say anything more useful.
We like to store database values in array. But we do not know the maximum size of an array which is allowed in PHP?
There is no max on the limit of an array. There is a limit on the amount of memory your script can use. This can be changed in the 'memory_limit' in your php.ini configuration.
Array size is limited only by amount of memory your server has. If your array gets too big, you will get "out of memory" error.
It seems to me to be the 16-bit signed integer limit. (2^15)
$ar = [];
while (array_push($ar, null)) {
print 'a';
}
Length of output: 32768
If, like me, you need to use a huge array in a class in PHP 5.6.40 and have found that there is a limit to the size of class arrays so that they get overflowed and overwritten when surpassing 32768 elements, then here is the solution I found to work.
Create a public function with the huge array in it as a local variable. Then assign that local variable to the class variable. Call this function right in the constructor. You will see that it prints the correct size of the array instead of the overflow leftover size.
class Zipcode_search {
public $zipcodes;
public function __construct() {
$this->setHugeArray();
print "size is ".sizeof($this->zipcodes). "<br />";
}
public function setHugeArray(){
$zipcodes=[too much stuff];//actual array with +40,000 elements etc.
$this->zipcodes = $zipcodes;
}
}
2,147,483,647 items, even on 64-bit PHP. (PHP 7.2.24)
In PHP, typedef struct _hashtable is defined with uint values for nTableSize and nNumOfElements.
Because of this, the largest array you can create with array_fill() or range() appears to be 2^32-1 items. While keys can be anything, including numbers outside that range, if you start at zero, with a step size of 1, your highest index can be 2147483646.
If you are asking this question, you have likely seen an error like:
# php -r 'array_fill(0, 2147483648, 0);'
PHP Warning: array_fill(): Too many elements in Command line code on line 1
or even:
# php -r 'array_fill(0, 2147483647, 0);'
Segmentation fault (core dumped)
...or, most likely, the error which explicitly refers to the "maximum array size":
php -r 'range(0,2147483647);'
PHP Warning: range(): The supplied range exceeds the maximum array size:
start=0 end=2147483647 in Command line code on line 1
A caution for those reading this question:
The most common place you'll run into this, is through misuse/abuse of the range() operator, as if it was an iterator. It is in other languages, but in PHP it is not: it is an array-filling operator, just like array_fill().
So odds are good that you can avoid the array use entirely. It is unsafe to do things like:
foreach (range($min, $max, $step)) { ... stuff ... }
Instead do:
for ($i = $min; $i <= $max; $i += $step) { ... stuff ... }
Equally, I've seen people doing:
// Takes 3 minutes with $min=0, $max=1e9, $step=1.
// Segfaults with slightly larger ranges.
$numItems = count(range($min, $max, $step));
Which can instead be rewritten in a more secure, idiomatic and performant way:
// Takes microseconds with $min=0, $max=1e9, $step=1.
// Can handle vastly larger numbers, too.
$numItems = ($max - $min) % $step;
If you are running into errors about array size, odds are good that you are doing crazy stuff that you probably should avoid.
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.