旧答案见下文。
在 IRC 上讨论了 Grinnz 的机智之后,我将这个答案的发现变成了一个插件,并在 CPAN 上以 Mojolicious::Plugin::Renderer::WithoutCache 发布,他们鼓励发布。
你可以这样使用它:
use Mojolicious::Lite;
plugin 'Renderer::WithoutCache';
它将创建一个不执行任何操作的新 Cache 对象,并将其全局安装到渲染器中。这样,就不需要像我下面的初始答案那样每次都创建它。
理论上,这应该比Grinnz' approach 快(这更明智),并且由于您明确不想缓存,您显然希望事情尽可能快,对吧?它应该更快,因为真正的 Mojo::Cache 仍然需要去尝试设置缓存,但随后因为没有更多的空闲键而中止,并且它还会尝试每次都从缓存中查找值。
我用Dumbbench 和Benchmark 对此进行了基准测试。两者都显示出微不足道的结果。我分别运行了几次,但它们波动很大,不清楚哪个更快。我包括了我的实现速度更快的运行输出,但它仍然显示了差异是多么微小。
使用 Dumbbench 进行基准测试:
use Dumbbench;
use Mojolicious::Renderer;
use Mojolicious::Controller;
use Mojolicious::Plugin::Renderer::WithoutCache::Cache;
my $controller = Mojolicious::Controller->new;
my $renderer_zero_keys = Mojolicious::Renderer->new;
$renderer_zero_keys->cache->max_keys(0);
my $renderer_nocache = Mojolicious::Renderer->new;
$renderer_nocache->cache( Mojolicious::Plugin::Renderer::WithoutCache::Cache->new );
my $bench = Dumbbench->new(
target_rel_precision => 0.005,
initial_runs => 5000,
);
$bench->add_instances(
Dumbbench::Instance::PerlSub->new(
name => 'max_keys',
code => sub {
$renderer_zero_keys->render( $controller, { text => 'foobar' } );
}
),
Dumbbench::Instance::PerlSub->new(
name => 'WithoutCache',
code => sub {
$renderer_nocache->render( $controller, { text => 'foobar' } );
}
),
);
$bench->run;
$bench->report;
__END__
max_keys: Ran 8544 iterations (3335 outliers).
max_keys: Rounded run time per iteration: 5.19018e-06 +/- 4.1e-10 (0.0%)
WithoutCache: Ran 5512 iterations (341 outliers).
WithoutCache: Rounded run time per iteration: 5.0802e-06 +/- 5.6e-09 (0.1%)
使用 Benchmark 进行基准测试:
use Benchmark 'cmpthese';
use Mojolicious::Renderer;
use Mojolicious::Controller;
use Mojolicious::Plugin::Renderer::WithoutCache::Cache;
my $controller = Mojolicious::Controller->new;
my $renderer_zero_keys = Mojolicious::Renderer->new;
$renderer_zero_keys->cache->max_keys(0);
my $renderer_nocache = Mojolicious::Renderer->new;
$renderer_nocache->cache( Mojolicious::Plugin::Renderer::WithoutCache::Cache->new );
cmpthese(
-5,
{
'max_keys' => sub {
$renderer_zero_keys->render( $controller, { text => 'foobar' } );
},
'WithoutCache' => sub {
$renderer_nocache->render( $controller, { text => 'foobar' } );
},
}
);
__END__
Rate max_keys WithoutCache
max_keys 190934/s -- -2%
WithoutCache 193846/s 2% --
我在一个有很多调用的重负载环境中进行侦察,它最终会有所作为,但这很难证明。所以如果你不想考虑缓存的内部结构,这个插件可能会很有用。
旧答案:
查看Mojolicious::Plugin::EPRenderer发现有一个cache。这是一个Mojo::Cache 实例,它具有get、set 和max_keys 方法,并继承自Mojo::Base(可能就像Mojolicious 中的所有内容一样)。
::EPRenderer gets a $renderer,即Mojolicious::Renderer。它拥有 Mojo::Cache 实例。我查看了$c 和Data::Printer,发现有一个$c->app 包含所有这些。
知道了这一点,您就可以轻松地创建自己的缓存类,而不会执行任何操作。
package Renderer::NoCache;
use Mojo::Base -base;
sub get {}
sub set {}
sub max_keys {}
现在你把它贴到$c。
package Foo;
use Mojolicious::Lite;
get '/' => sub {
my $c = shift;
$c->app->renderer->cache( Renderer::NoCache->new );
$c->render(template => 'foo', name => 'World');
};
app->start;
__DATA__
@@ foo.html.ep
Hello <%= $name =%>.
现在对get 或set 缓存的每一次尝试都不会执行任何操作。它会尝试缓存,但永远找不到任何东西。
当然,每次都制作一个新对象并不是很好。最好在启动时制作一次该对象并将其放入app 的内部永久版本中。你有 CGI,所以它可能没有什么不同。
您也可以只对get 从Mojo::Cache 进行修补。这种更 hacky 的方法会做同样的事情:
package Foo;
use Mojolicious::Lite;
*Mojo::Cache::get = sub { };
get '/' => sub {
my $c = shift;
$c->render(template => 'foo', name => 'World');
};
app->start;
但要注意:我们刚刚禁用了从您使用 Mojo::Cache 的应用程序中的每个缓存获取。这可能不是你想要的。