Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[9.x] Makes blade components blazing fast ⛽️ #44487

Merged
merged 32 commits into from
Oct 12, 2022

Conversation

nunomaduro
Copy link
Member

@nunomaduro nunomaduro commented Oct 6, 2022

Technical Details

This pull request addresses the performance of blade view components, and it mainly performs:

  1. Components are only resolved from the IOC container if necessary. This is done by checking if the component $data matches exactly the Component::__construct() method parameters names, and if not, we proxy for the container.

  2. The computation of the Component::render, when using inline components, is only computed once. So, assuming that the return is components.button, we only check if components.button is a view once, and following calls will use this cached result.

  3. We provide a new method, called Component::view, that should be documented instead of having people using the simple view helper.

  4. Events on views, related to creators and composers, are only fired if there is actually creators or composers for the given view.

  5. Checking if views are expired, only happens once for the given view, during the lifecycle of the Application instance.

How To Test This Pull Request

If you would like to test this pull request locally, simply run the command above.

composer require laravel/framework:"dev-feat/view-components-performance as 9.34" --with-all-dependencies
php artisan clear
php artisan view:clear

After, run your test suite, navigate in your application, and see if things are working as normal.

Results

Anonymous components — up to 52% faster:

@for ($number = 0; $number < $numberOfComponents; $number++)
    <x-button: :$number /> 
@endfor

Before:
- 100 components: 7.203ms
- 1000 components: 67.764ms
- 10000 components: 666.120ms
After:
- 100 components: 3.649ms
- 1000 components: 34.204ms
- 10000 components: 326.806ms

Class View components - up to 39% faster:

@for ($number = 0; $number < $numberOfComponents; $number++)
    <x-button: :$number /> 
@endfor

class Button extends Component
{
    function __construct(public $number) {}

    function render() {
        return 'components.button';
    }
}

Before:
- 100 components: 6.946ms
- 1000 components: 69.657ms
- 10000 components: 670.511ms
After:
- 100 components: 4.441ms
- 1000 components: 42.266ms
- 10000 components: 413.125ms

Class Inline components — up to 92% faster:

@for ($number = 0; $number < $numberOfComponents; $number++)
    <x-button: :$number /> 
@endfor

class Button extends Component
{
    function __construct(public $number) {}

    function render() {
        return '{{ $number }}';
    }
}

Before:
- 100 components: 66.426ms
- 1000 components: 560.284ms" // 0.5 seconds ..
- 10000 components: 5,080.315ms" // 5 seconds ..
After:
- 100 components: 4.499ms
- 1000 components: 41.834ms
- 10000 components: 413.493ms

Dynamic components ( that renders anonymous components ) — up to 72% faster:

@for ($number = 0; $number < $numberOfComponents; $number++)
    <x-dynamic-component :component="'button'" :$number />
@endfor

Before:
- 100 components: 239.325ms
- 1000 components: 1,033.402ms
- 10000 components: 6,994.827ms

After:
- 100 components: 185.298ms
- 1000 components: 416.685ms
- 10000 components: 1,994.571ms

Dynamic components ( that renders inline class components ) — up to 83% faster:

@for ($number = 0; $number < $numberOfComponents; $number++)
    <x-dynamic-component :component="'button'" :$number />
@endfor

class Button extends Component
{
    function __construct(public $number) {}

    function render() {
        return '{{ $number }}';
    }
}

Before:
- 100 components: 287.660ms
- 1000 components: 1,331.259ms
- 10000 components: 12,439.949ms

After:
- 100 components: 69.568ms
- 1000 components: 227.673ms
- 10000 components: 2,216.089ms

@nunomaduro nunomaduro self-assigned this Oct 6, 2022
@JayBizzle
Copy link
Contributor

JayBizzle commented Oct 6, 2022

Just tested this again against the issue we were having blade-ui-kit/blade-icons#190

Based on the repo in that issue we are seeing the following improvement when rendering 10,000 icons with this PR in place (M1 Mac Studio)

730.799ms   // component without params <x-heroicon-o-arrow-right/>
1,233.669ms // component with params <x-heroicon-o-arrow-left class="w-6 h-6 text-gray-500"/>

After this PR applied

272.211ms  // component without params <x-heroicon-o-arrow-right/>
273.206ms  // component with params <x-heroicon-o-arrow-left class="w-6 h-6 text-gray-500"/>

👍

@garygreen
Copy link
Contributor

garygreen commented Oct 7, 2022

This PR is quite large. Please could we have a better understanding of what parts of this PR contribute to the speed increase?

It looks like there are 3 main areas that are being targeted here to improve speed:

What parts of those contribute most to the speed increase? Are they all necessary, or could some of them be micro optimizations?

@ErikBernskiold
Copy link

ErikBernskiold commented Oct 10, 2022

Love this! I just tried this on a project which relies heavily on data tables where tables, tr, td and th are all anonymous components. The experience has been sluggish on render, so much so that we've had to aggressively paginate to have a tolerable experience. (1k-10k components). While I couldn't do the proper benchmarking at the moment, the difference is night and day and very noticeable. Blazing fast!

@nunomaduro nunomaduro marked this pull request as ready for review October 11, 2022 17:01
@taylorotwell taylorotwell merged commit 331bf9c into 9.x Oct 12, 2022
@taylorotwell taylorotwell deleted the feat/view-components-performance branch October 12, 2022 14:44
@browner12
Copy link
Contributor

browner12 commented Oct 18, 2022

Just an FYI, this breaks the "View" tab of Laravel Debugbar.

barryvdh/laravel-debugbar#1354

Screen Shot 2022-10-18 at 11 06 06 AM

@jhoanborges
Copy link

BRAVO!!! @nunomaduro

@hoRacy
Copy link

hoRacy commented Oct 28, 2022

A beautiful change and colossal speed difference. Thank you very much for your contribution to the project! <3 @nunomaduro

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.