Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

acacha's avatar

How to improve performance when calling same view multiple times

Imagine a code like:

Route::get('/testperformance', function () {

    $ouputString  = "";
    for ($i = 1; $i <= 10000; $i++) {
        $ouputString = $ouputString . View::make('hello')->render();
    }

    echo $ouputString;
});

You can test how performance is linear affected by incrementing loop size (for example using 20000 tooks double time to execute page http://myapp.app//testperformance ).

The question is: any way to increment performance in this case?

I think the problem is time spent in I/O disk operations reading the view file. Taking into account is always the same field it could not be cached in any way?

0 likes
9 replies
acacha's avatar

NOTE: I know I can put View::make('hello')->render() outside the loop and call it only once. The example is a toy example but when I use some libraries like https://github.com/sleeping-owl/admin sometimes a lot of views are called so is interesting knowing in any alternative way.

phildawson's avatar

How many views is sleeping owl calling? Number of views aren't usually an issue. The bottleneck is usually database and inefficient queries. And then lack of caching.

Taking into account is always the same field it could not be cached in any way?

Well you can cache anything and if you use a memory based caching (Redis or Memcached) it'll be near instant. Also if you are needing to make loads of commands you can also pipeline them into one operation.

acacha's avatar

@phildawson did you try my example /testperformance ? The views have only a div with any dynamic data and when I tried with 5000 loops execution time is 4.86s ans with 10000 it tooks 9.6s. It seems a lot of time for me.

And this code:

Route::get('/testperformance', function () {

    $ouputString  = "";
    $test = View::make('hello')->render();
    for ($i = 1; $i <= 10000; $i++) {
        $ouputString = $ouputString . $test;
    }

    echo $ouputString;
});

It takes only milliseconds so I'm sure my bottleneck is View::make.

With Sleeping Owl using datatables display with 322 with 11 rows it tooks at least (322x11=3542) actually a more with headers and other views (in my case exactly 3698 views). In this case it tooks (20 seconds with debugbar enabled and 9.7 seconds without still a lot). In any case performance is becoming linear worse with number of rows. I also use with() method and Eager Loading reducing the number of queries to a reasonably number (14 queries)

I never use before a cache system. Could you give me and example how to cache the View::make applied to "toy example" I've proposed?

jekinney's avatar

Was just reading about performance of arrays vs objects and for loops vs for each.

I haven't tested personally, but most posted results show a for loop taking twice as long to execute vs a for each.

Secondly, I don't see you outputting or logging any time (micro time) to see if the loop execution or view make method is the issue.

Now I have tested the form helpers vs typical html inputs and that proved html was 70% faster time. Obviously the Form::close() just to output I consider a waste of time. Loops percentage continues to improve.

Bottom line the more work PHP has to do will negatively effect performance. The leaner and simpler the code by caching, efficient queries, and minimizing what PHP has to do equals better performance.

phildawson's avatar
Level 26

@jekinney

I haven't tested personally, but most posted results show a for loop taking twice as long to execute vs a for each.

for is quicker than foreach but we are talking about a ten thousandths of a difference over the whole 10,000 not each loop.

In this case its getting view files a fuck-of-a-lot of times. When most apps have ~1-5 views being loaded per page this seems to be looping for each row turning it into thousands.

@acacha I'd expect it to be linear.

Forgetting Laravel for a moment if you did this I'd expect it to be 10s alone from 10,000 calls.

$start = microtime(true);
for ($i = 1; $i <= 10000; $i++) {
    file_get_contents('your-file');
}
echo microtime(true) - $start;

(It's actually calling file_get_contents behind the scenes when you View::make)

So the issue is why is it calling the same views over and over. That seems to be a bug in the Sleeping Owl to me.

Whilst caching will help, thats covering the actual issue. The Application load should be in ms. If a page is taking more than 1 second to load its a sure sign something is wrong.

As you say if you have something where the view that's being loaded is outside the loop.

That 10 seconds for 10,000 turns into 0.001 seconds for 1.

$start = microtime(true);
$file = file_get_contents('your-file');
for ($i = 1; $i <= 10000; $i++) {
    echo $file;
}
echo microtime(true) - $start;
1 like
acacha's avatar

@phildawson Forgetting Laravel for a moment if you did this I'd expect it to be 10s alone from 10,000 calls.

I tested your example and you are Right. Is not a a problem in make:view. There are to many I/O read file operations (moreover my example is running in homestead a virtual machine with and additional penalty in I/O operations)

@phildawson So the issue is why is it calling the same views over and over. That seems to be a bug in the Sleeping Owl to me.

I agree with you the only possible improvement is hacking Sleeping Owl to avoid repeating same operation again and again.

Thanks!

phildawson's avatar

@acacha Have you got any code that you can show which is causing the slowdown, or even better the steps to recreate a slow setup? Is anything on github/bitbucket that can be cloned?

It might be worth sending a email/PM to the creator of Sleepy Owl to see what they get from the same setup.

acacha's avatar

I answer to myself. I know is a stupid example but I've implemented and tested using Laravel cache. For reference maybe could help somebody:


Route::get('/testperformance', function () {

    $ouputString  = "";

    $test = Cache::get("hello_view",null);

    for ($i = 1; $i <= 10000; $i++) {
        if ($test == null) {
            $test = View::make('hello')->render();
            Cache::add("hello_view",$test, 10);
        }

        $ouputString = $ouputString . $test;
    }

    echo $ouputString;
});

This executes really fast.

acacha's avatar

@phildawson I write and Issue to Sleeping Owl:

https://github.com/sleeping-owl/admin/issues/237

but if I found a solution will try to make a PR.

My example is in a private github repo. But Sleeping Own code is:

https://github.com/sleeping-owl/admin-lte-template/blob/master/src/views/default/display/datatables.blade.php

This is the main view for datatables display. As you can see

@foreach ($collection as $instance)
                <tr>
                    @foreach ($columns as $column)
                        <?php
                            $column->setInstance($instance);
                        ?>
                        {!! $column !!}
                    @endforeach
                </tr>
            @endforeach

With that if you have 100 rows an 10 columns 1000 loops are executed on code line:

{!! $column !!}

Not every column is the same type and different dinamic values applies for same type columns. If columns if of type String:

https://github.com/sleeping-owl/admin/blob/development/src/SleepingOwl/Admin/Columns/Column/String.php

This line of code executes the code:

/**
     * @return string
     */
    function __toString()
    {
        return (string)$this->render();
    }

at parent String class:

https://github.com/sleeping-owl/admin/blob/development/src/SleepingOwl/Admin/Columns/Column/BaseColumn.php

And render is calling make:view:

/**
     * @return View
     */
    public function render()
    {
        $params = [
            'value'  => $this->getValue($this->instance, $this->name()),
            'append' => $this->append(),
        ];
        return view(AdminTemplate::view('column.string'), $params);
    }

see https://github.com/sleeping-owl/admin/blob/development/src/SleepingOwl/Admin/Columns/Column/String.php

where column.string is a simple view:

<td>{{ $value }} {!! $append !!}</td>

Please or to participate in this conversation.