Description:
The test script below works fine for 10 iterations but crashes (Segmentation fault) for 400000 iterations while it shouldn't crash.
Uses Php 7.2 on docker (Version 17.09.0-ce-mac35 (19611))
with no extension.
Test script:
<?php
class Lim {
public $id;
public $inv;
public $fi;
function __construct($id) {
$this->id = $id;
$this->inv = new Inv($this);
}
};
class Inv {
public $inv;
public $fi;
function __construct($inv) { $this->inv = $inv; }
}
$max = 400000;
//$max = 10;
$lim0 = new Lim(0);
$limp = $lim0;
for ($i=1; $i<$max; $i++) {
$lim = new Lim($i);
$lim->fi = $limp->inv;
$limp->inv->fi = $lim;
$limp = $lim;
}
Does anyone have an idea why ?
Thanks
You are creating a new $lim but not destroying the old one. So you are running out of memory.
add this
unset($lim);
after
$limp = $lim;
Related
I have created two classes:
class TestClass
{
public $id;
public $name;
public $time;
}
class TestClassCtor
{
public $id;
public $name;
public $time;
public function __construct()
{
}
}
Now I run a simple code:
$tt = microtime(true);
$data = array();
for ($i = 0; $i < 10000; $i++)
{
$t = new TestClass();
$t->id = rand();
$t->name = rand();
$t->time = rand();
$data[] = $t;
}
echo microtime(true) - $tt;
echo "\n";
$tt = microtime(true);
$data1 = array();
for ($i = 0; $i < 10000; $i++)
{
$t = new TestClassCtor();
$t->id = rand();
$t->name = rand();
$t->time = rand();
$data1[] = $t;
}
echo microtime(true) - $tt;
Now, the second code with TestClassCtor is around 30% slower. Why? (tested with PHP 5.6 and 7.1).
Edit:
The similar difference can be spotted with (in this case, I can understand it - passing arguments to method may be slower).
class TestClassCtorFill
{
public $id;
public $name;
public $time;
public function __construct($id, $name, $time)
{
$this->id = $id;
$this->name = $name;
$this->time = $time;
}
}
In this case, I can create class in one line as
for ($i = 0; $i < 10000; $i++)
{
$data1[] = new TestClassCtorFill(rand(), rand(), rand());
}
Yes, this is safer, because user must set all three parameters and he wont forget to set something.
However, when I use this inside my internal framework class, I can omit the ctor entirely and set members directly as with TestClass to save some time. For a few instances, this wont be a much of a difference. But if I create tousands of them, it could be.
Edit 2
I know about cost of a function call. However, constructor is called upon new, so if I write or not one, some constructor should be called. If there is no constructor provided by user a default one is caled. Memory for object must be allocated either way.
I've got a class that is used in a few functions independently from one another. So my question is: is it faster to pass the initiated class as a parameter to the function or to create a new instance every time the function is called upon?
Like this:
$class_a = new Class_a;
function rnd_fun($class_a){
... do stuff...
}
Or like this:
function rnd_fun(){
$class_a = new Class_a;
... do stuff...
unset($class_a);
}
I tried to do a benchmark and these are the results by using this
very creative class
class Class_a {
public $first_name = "";
public $age = "";
public function setVar($first_name, $age){
$this->first_name = $first_name;
$this->age = $age;
}
public function wasteTime(){
$i = 0;
while($i < 100){
$this->age = $this->age * $i;
$this->age = $this->age / pi();
$i++;
}
}
}
By passing the class as a parameter I got something around 0.46s using this code:
$class_a = new Class_a;
$i = 0;
while($i < 10000){
test($class_a);
$i++;
}
function test($class_a){
$class_a->setVar("Geronimo", "72.1");
$class_a->wasteTime();
}
This is by initiating a new class inside the function:
$i = 0;
while($i < 10000){
test();
$i++;
}
function test(){
$class_a = new Class_a;
$class_a->setVar("Geronimo", "72.1");
$class_a->wasteTime();
unset($class_a);
}
I have to point out though that the second method took a slightly higher time to execute (around 0.47s).
However I believe that the difference between the two is negligible since both run at around the same speed for this many iteration and their delay won't be noticeable in an average piece of code.
I am running 4 threads running in same time. (Threads are running work() function in same time in this case)
global $i;
$i = 1;
function work($address) {
while($i < 1000) {
$i++;
----
if($i == something) some job...
----
}
}
For some reason this don't do the job.
Threads do sometimes same circle in while, so I have later some duplicate values. (probably they have some critical section)
Any idea how to fix this ?
The counter object must be thread safe, it must also employ synchronized methods.
Follows is an example of such code:
<?php
class Counter extends Threaded {
public function __construct($value = 0) {
$this->value = $value;
}
/** protected methods are synchronized in pthreads **/
protected function increment() { return ++$this->value; }
protected function decrement() { return --$this->value; }
protected $value;
}
class My extends Thread {
/** all threads share the same counter dependency */
public function __construct(Counter $counter) {
$this->counter = $counter;
}
/** work will execute from job 1 to 1000, and no more, across all threads **/
public function run() {
while (($job = $this->counter->increment()) <= 1000) {
printf("Thread %lu doing job %d\n",
Thread::getCurrentThreadId(), $job);
}
}
protected $counter;
}
$counter = new Counter();
$threads = [];
while (($tid = count($threads)) < 4) {
$threads[$tid] = new My($counter);
$threads[$tid]->start();
}
foreach ($threads as $thread)
$thread->join();
?>
work() seems superfluous, this logic should be in the ::run function most likely.
I have run into a situation with pthreads.Consider the following script:
<?php
class W extends \Worker {
public function run()
{
echo "worker started\n";
}
}
clasds S extends \Stackable {
public function run()
{
echo "stackable executed\n";
}
}
class x{
protected $workers;
protected $i;
public function __construct()
{
$this->workers = array();
$this->i = 0;
}
public function go()
{
$thread = $this->spawn();
$j = new S;
$thread->stack($j);
//$thread->shutdown();
}
public function spawn()
{
$this->i !== 0 ? $n=$this->i++ : $n=$this->i;
$thread = new W;
$this->workers[$n] = $thread;
$thread->start();
return $thread;
}
}
$exe = new x;
$exe->go();
php crashes.2 ways to solve the issue, either:
uncommenting
$w->shutdown();
which means the workers one creates are not reusable, or commenting out
$this->c[$n] = $w;
which means not saving workers in an array.
I do not understand what is going on here.must one call shutdown on a worker?why does attempting to store
the worker in an array lead to a crash?
I'm trying to make an array of Spells.
My current code
class Spell
{
public $bomb = 0;
public $fire = 0;
function Spell()
{
$this->bomb =0;
$this->fire =0;
}
}
And I declare the object spell on my game class like this
class game
{
public $Spell=array();
function Game()
{
$this->Spell[0] = new Spell();
}
function s()
{
$this->Spell[1]->$bomb = $load($x)
$this->Spell[1]->$fire = $load($x);
$this->Spell[2]->$bomb = $load($y)
$this->Spell[3]->$bomb = $load($z)
}
}
It returns this error -- Warning: Creating default object from empty value in...
I guess this isn't the best way to create an array of objects. How to do it properly?
EDIT:
x y z, just return strings
The problem is that you have not created objects for $this->Spell[1], $this->Spell[2] and $this->Spell[3]. If you change your Game() constructor to this:
function Game()
{
for ($i = 1; $i <= 3; $i++) {
$this->Spell[$i] = new Spell();
}
}
It should probably work fine.
You seem to have more than just one problems in your code.
However, I will discuss the one you have asked the question for.
Instead of
$this->Spell[1]->$bomb = something;
Use
$this->Spell[1]->bomb = something;
Second, What do you intend to do by using $load($y)?
If you're using a function named "load", use load($y)
you must create object, then use it, look:
class Spell
{
public $bomb = 0;
public $fire = 0;
function __construct()
{
$this->bomb =0;
$this->fire =0;
}
}
class game
{
public $Spell=array();
function s()
{
$this->Spell[1] = new Spell();
$this->Spell[1]->bomb = 0 ; //or other value
}
}
<?php
class Spell
{
public $bomb = 0;
public $fire = 0;
function Spell()
{
$this->bomb =0;
$this->fire =0;
}
}
class game
{
public $Spell=array();
function Game($index)
{
$this->Spell[$index] = new Spell();
echo 'constructer called';
}
function s()
{
$this->Spell[1]->bomb = $load($x);
$this->Spell[1]->fire = $load($x);
$this->Spell[2]->bomb = $load($y);
$this->Spell[3]->bomb = $load($z);
}
}
$ob = new game();
//$ob->Game(1); to pass the index for array.
?>
You are using lots of undefined stuff, I would say the half of your script is missing.
I just added the comments down here:
class game
{
public $Spell=array();
function Game()
{
$this->Spell[0] = new Spell();
}
function s()
{
/**
down here you are using these undefined "variables":
$bomb
$load
$x
$y
$z
undefined means, you are using a varible which was not declared. so it´s just null.
I tried to fix it:
**/
$x = 1;
$y = 2;
$z = 3;
$this->Spell[1] = new Spell();
$this->Spell[2] = new Spell();
$this->Spell[3] = new Spell();
$this->Spell[1]->bomb = load($x); // add ;
$this->Spell[1]->fire = load($x);
$this->Spell[2]->bomb = load($y)
$this->Spell[3]->bomb = load($z)
}
}
function load($v)
{
return $v * 2;
}