将字符串转换为函数(可调用)并将其缓存


Convert a string to function (callable) and keep it cached

我正在尝试编写一个小的基准测试脚本,在其中我可以输入简短的代码片段,以便快速评估我的预期。我认为它类似于jsPerf(但出于安全原因有密码保护)。

主循环应该像这样:

  public function run(&$t, $count) {
    //Run setup function
    if(is_callable($this->setup))
      call_user_func($this->setup);
    //Save inital time
    $t($this->name);
    //THE MAIN LOOP
    for($i=0; $i<$count; $i++) {
        call_user_func($this->fn);
    }
    //Save end time
    $t($this->name."_end");
    //return time difference
    return $t[$this->name."-".$this->name."_end"];
  }

但是,这只适用于静态方法——在编写脚本时定义的函数:

//New instance of tester
$b = new Benchmarker();
$b->add(
  //Name
  "touch",
  //closure
  function() {
    touch("file.txt");
  },
  //Code seen in final reports
  "touch()"
);

如你所见,我用call_user_func,而不是eval。除了它本质上是一个邪恶的函数之外,出于性能原因,我想避免使用它。如果我测试的代码需要大约10ns来处理,而评估需要大约100ns,那么我的结果将是相当随机的。

这就是为什么我正在寻找一种方法来转换字符串到一个可调用的对象。您可以把它看作是一次性的eval。

$callable = string_to_callable("function() {echo '"Hello world!'";}");
$b->add(
  //Name
  "echo",
  //callable object
  $callable,
  //Code seen in final reports
  "echo '"...'""
);

这可能吗?

<子>注意:

我可以看到有趣的解决方案使用include:

//Code received from the user
$code = "echo '"Hello world!'";";
//Random name for a new function
$rndname = "fn_".rand(0,100000);  //There are smarter ways to do this of course
//String of the new function
$func = "function $rndname() {{$code}}";
//Define a filename
$f = $rndname.".php";
//Put the code in the file
file_put_contents($f, "<?php'n$func'n?".">");
//Include the new script
include $f;
//Call the function
call_user_func($rndname);
//Delete the file
unlink($f);

我真的希望不需要上面的代码!

除了创建一个新文件,可能还有一个闭包技巧:

function string_to_callable($string) {
  return eval("return function() {{$string}};");
}