silverstripe / silverstripe-framework

Silverstripe Framework, the MVC framework that powers Silverstripe CMS
https://www.silverstripe.org
BSD 3-Clause "New" or "Revised" License
721 stars 822 forks source link

5.1: Eagerloading performance is bad for many_many relations #10847

Closed GuySartorelli closed 1 year ago

GuySartorelli commented 1 year ago

In this specific set up, eager loading is really really really bad for performance. ~1second page load without eager loading, execution time of 30seconds is hit and PHP times out with eager loading.

Here's what I've got running:

Edit: I've simplified this based on my findings - so long as you're using the 5 branch of framework the composer dependencies are irrelevant so I've removed that snippet entirely.

Team.php

<?php

use SilverStripe\ORM\DataObject;

class Team extends DataObject
{
    private static $db = [
        'Name' => 'Text'
    ];

    private static $many_many = [
        'Players' => Player::class
    ];
}

Player.php

<?php

use SilverStripe\ORM\DataObject;

class Player extends DataObject
{
    private static $db = [
        'Name' => 'Text',
    ];

    private static $belongs_many_many = [
        'Teams' => Team::class,
    ];
}

_config.php

<?php
// // Create fixtures - 1000 teams, 10 players per team for a total of 10,000 players
// $count = Team::get()->count();
// for ($x = $count; $x < 1000; $x++) {
//     $team = Team::create(['Name' => $x]);
//     $team->write();
//     for ($y = 0; $y < 10; $y++) {
//         $player = Player::create(['Name' => $x . '_' . $y]);
//         $player->write();
//         $team->Players()->add($player);
//     }
// }

$teams = Team::get();
$teams = $teams->eagerLoad('Players');

foreach ($teams as $team) {
   foreach ($team->Players() as $player) {
        echo ''; // just need something here to ensure PHP doesn't optimise out the loops
   }
}

PRs

emteknetnz commented 1 year ago

Linked PR has been merged