High memory usage in template

6 years ago

dimkalinux
Member | 24
+
0
-

Hi, im use Nette 2.0.11 and PHP 5.3.3 with Zend OPcache v7.0.2.

Simple layout and 1 template (get.latte). To get.latte i pass one variable $code.
If $code have 1 char – memory usage is around 4.5 mb, but if i pass long string for example $code is 4.5 mb length memory usage is around 27 mb. i look at code and “problem” seem to be in FileTemplate::render() method – its pass my big variable $code at least twice – for rendering get.latte and for rendering @layout.latte

Is exists any method for drop memory usage in this case (big content)?

Last edited by dimkalinux (2013-08-30 19:38)

6 years ago

dimkalinux
Member | 24
+
0
-

Problem resolved.

Instead of passing $code as variable – im passing object that return $code with lazy loading. Now memory usage drops to 12 Mb from 27.

6 years ago

enumag
Member | 2128
+
0
-

This is wierd. I thought that PHP only copies the values of variables when necessary (lazily).

6 years ago

dimkalinux
Member | 24
+
0
-

Templates use extract() method in many places and maybe in many scopes. And every extract in other scope create new my big variable. I make tracing with xdebug and memory raised by 4.5 Mb after every extract() in templates.

Last edited by dimkalinux (2013-08-30 16:07)

6 years ago

enumag
Member | 2128
+
0
-

That's probably a PHP bug. The extract function apparently doesn't use the copy-on-write approach.

Last edited by enumag (2013-08-30 17:26)

6 years ago

dimkalinux
Member | 24
+
0
-
//
// block content
//
if (!function_exists($_l->blocks['content'][] = '_lb2cc6cb6c47_content')) { function _lb2cc6cb6c47_content($_l, $_args) { extract($_args)
?><div class="row">
        <div class="row">
            <div class="small-12 text-left column">
                <div class="snippet"><?php echo $code ?></div>
            </div>
        </div>
    </div>
</div>
<?php
}}

Maybe $code not exists in scope function _lb2cc6cb6c47_content() {} and thats why it created on extract.

6 years ago

Majkl578
Moderator | 1379
+
0
-

One option may be to use:

foreach ($_args as $k => $v) { $$k = $v; }

instead of extract.

6 years ago

dimkalinux
Member | 24
+
0
-

This modification drop memory usage from 27 to 15 Mb. Its LimitedScope::load() method.

/**
 * Includes script in a limited scope.
 * @param  string  file to include
 * @param  array   local variables or TRUE meaning include once
 * @return mixed   the return value of the included file
 */
public static function load(/*$file, array $vars = NULL*/)
{
    if (func_num_args() > 1) {
        self::$vars = func_get_arg(1);
        if (self::$vars === TRUE) {
            return require func_get_arg(0);
        }
        // extract(self::$vars);
        foreach (self::$vars as $k => $v) { $$k = $v; }
    }
    return require func_get_arg(0);
}

6 years ago

enumag
Member | 2128
+
0
-

Well in this case extract(self::$vars, EXTR_REFS); should actually also be safe.

6 years ago

dimkalinux
Member | 24
+
0
-

Not helping, memory usage 27

extract(self::$vars, EXTR_REFS);

BTW, founded in code

. (PHP_VERSION_ID > 50208 ? 'extract($_args)' : 'foreach ($_args as $__k => $__v) $$__k = $__v') // PHP bug #46873

Last edited by dimkalinux (2013-08-30 18:11)

6 years ago

dimkalinux
Member | 24
+
0
-

This patch make memory usage 12 mb (from 27) https://gist.github.com/…59597e6f518e
Maybe need create issue on github for investigation?

6 years ago

enumag
Member | 2128
+
0
-

@dimkalinux: The patch is not safe. I've tried the same already half an hour ago on Nette-dev but it broke some tests. I have no idea why. The tests are passing when I revert the commit.

EDIT: The tests failed because the compiled PHP output was compared against some regular expression. The patch is ok.

Last edited by enumag (2013-08-30 19:28)

6 years ago

dimkalinux
Member | 24
+
0
-

Ok.

Last edited by dimkalinux (2013-08-30 18:44)