比eval更快的替代方案?

par*_*sim 11 perl performance eval

我正在处理一个使用本土模板系统的Web应用程序,该系统允许将Perl代码嵌入到HTML中.这些语句由模板解析器在运行时使用执行eval EXPR.

这非常灵活,但这些陈述遍布各地,并且执行得很多.eval EXPR(相反eval BLOCK)需要Perl每次启动解释器,我的分析显示它们是减速的一个相当重要的来源.

许多嵌入式Perl语句非常简单.例如,模板可能有这样的行:

<p>Welcome, <!--E: $user->query('name') -->.
Run Code Online (Sandbox Code Playgroud)

要么:

<p>Ticket number <!--E: $user->generate_ticket_number() --> has been generated.
Run Code Online (Sandbox Code Playgroud)

也就是说,他们只是调用对象方法.但是,也有更复杂的问题.

我希望能够优化这一点,到目前为止有两个想法,这两个想法都很糟糕.首先是重写所有模板替换标记一样简单的调用USER:NAMEUSER:GENERATETICKETNUMBER,其中解析器将然后扫描,并调用合适的对象方法.但是,我没有处理混合HTML和Perl的模板,而是使用混合HTML,Perl和令牌的模板.

第二个想法是尝试解析嵌入的Perl,弄清楚语句想要做什么,如果它足够简单,通过符号引用调用适当的对象方法.这显然是疯了.

我有什么逻辑解决方案可以忽略吗?

dus*_*uff 9

尝试采用类似于mod_perl编译CGI的方法:

  1. 将模板转换为Perl代码.例如,您的第一个示例可能会转换为:

    print "<p>Welcome, ";
    print $user->query('name');
    print ".\n";
    
    Run Code Online (Sandbox Code Playgroud)
  2. 围绕该代码包装sub {... }以及一些解包参数的代码(例如,对于$user样本中的内容).

  3. eval那段代码.请注意,它返回一个coderef.

  4. 重复调用该coderef.:)

  • 一种相关的方法是将生成的代码写入`.pm`文件,然后加载该模块.这样,模板只需要在更改时重新解析.哪种方式更好取决于应用程序实现方式的详细信息. (5认同)