2

I am creating a script to simulate a hockey game. All games will be simulated once per day. However when I run my simulator, after about 50 game simulations, I get an error that says

PHP Fatal error: Allowed memory size of 268435456 bytes exhausted

I tried using the unset() function to clear the memory after each game simulates but it doesn't seem to help. What can I be missing here? Should I be using some kind of destructor or are there any other php functions that can help clean up memory?

class GameSimulatorHelper extends Model
{
    public function run()
    {
        // Get all the games from the database.
        $games = Game::all();

        // Simulate each game.
        foreach ($games as $g) {
            $sim = new GameSimulator();
            $sim->run($g);
            unset($sim);
        }
    }
}

class GameSimulator extends Model
{
    public $homeGoals = 0;
    public $awayGoals = 0;
    // A bunch of other class variables here.

    public function run($game)
    {
        $this->simulate($game);
        // This function just resets all the class variables for the next game to be simulated.
        $this->resetSimulator();
        echo 'MEMORY USAGE: '.memory_get_usage(true) . "\n";
    }

    public function simulate()
    {
        $maxPeriods = 3;
        for ($p=1; $p <= $maxPeriods; $p++) {
            for ($i=1; $i <= 1200; $i++) {
                // Do many things here like get and set data in database.
            }
        }
    }
    // Many other functions below.
}
fvuong
  • 167
  • 1
  • 3
  • 13
  • I wouldn't say this is marked as duplicate, but a solution to his problem would be to use a for loop instead of foreach in this case... class GameSimulatorHelper extends Model { public function run() { // Get all the games from the database. $games = Game::all(); $gamesCount = count($games); // Simulate each game. for ($i = 0; $i < $gamesCount; $i++) { $sim = new GameSimulator(); $sim->run($games[$i]); } } } – giolliano sulit Oct 17 '17 at 22:24
  • @giollianosulit What makes you say that a `for` loop would consume less memory - if all games are loaded up front it shouldn't matter, should it? I think it's far more likely there's a leak in the "Do many things" or "Many other functions" bits... – Mikk3lRo Oct 17 '17 at 22:36
  • See here for `for` vs `foreach`. https://stackoverflow.com/questions/3430194/performance-of-for-vs-foreach-in-php – fubar Oct 17 '17 at 23:11
  • Maybe try a singleton instead of instansiating the `GameSimulator` class each time? – Camilo Oct 17 '17 at 23:20
  • Also, what ever you are doing inside the last `for` inside `simulate()` can have a great impact on the memory used. – Camilo Oct 17 '17 at 23:24
  • @fubar Nothing in that questions answers suggests that a `for` loop consumes less memory than a `foreach`...? *If* the game (ie. `$g`) was modified inside the loop then using a `for` loop or a reference **might** be faster and / or more memory efficient. But since it's *not modified* the content is never copied (because php uses copy-on-write). If anything, all answers to that question confirm that foreach should be the preferred method. fvuong: Have you tried re-using the same instance of the `GameSimulator` class: `$sim = new GameSimulator();foreach($games as $g){ $sim->run($g); }` ? – Mikk3lRo Oct 18 '17 at 06:02
  • @Mikk3lRo I don’t recall saying which to use either way. I was citing the question as a source of information for people who have already had a similar discussion. – fubar Oct 18 '17 at 06:23
  • @fubar Oh... I guess you're right ;) I read it as "this is the reason why `for` is better", but I guess you didn't actually say that. – Mikk3lRo Oct 18 '17 at 06:43

0 Answers0