首頁  >  文章  >  後端開發  >  关于 eval 的优化,基于使用eval这个方法实现效率低下的问题

关于 eval 的优化,基于使用eval这个方法实现效率低下的问题

WBOY
WBOY原創
2016-06-23 14:03:231242瀏覽

需求:
    根据一些指定的计算公式去获得期待值。

例子:

 

//提供的数据源$row = array(            'pv'        =>  50,            'uv'        =>  6,            'st'        =>  650,            'nuv'       =>  2);//需求公式,可能有些量不存在:如no$gx = '(pv+uv)/(uv-nuv+1)*10+nuv-uv+no/0+3.5';$gx = preg_replace('/[a-z][a-z_\d]+/i', ' $row[\'${0}\'] ', $gx);//处理过后公式$str = "@\$s = $gx;";//合法php语句try{    @eval($str);//str和eval前使用@确保不显示错误,如某个变量不存在,或除数为0等}catch(Exception $e){}//这个方结果可求出


这个方法,可能大家都想到,还有一些这个方法的变异:
1,使用 preg_replace_callback
2,preg_replace('//ie')使用e修正符,其实与1一样
3,使用sql来执行公司,"select 格式化后的公式",但这个方法不能处理no这个变量,还有除数为0时,会返回null


//以上是我目前的方法
循环1w次,0.25秒左右,
如果10w次,就2秒多了。

这个效率目前还接受不了。

哥们还有什么好办法没????


回复讨论(解决方案)


都来讨论一下。。。。

先支持一下楼主

还想怎么快,没法再快了。你直接用数据值计算:
echo ( $row['pv'] + $row['uv'] )/( $row['uv'] - $row['nuv'] +1)*10+ $row['nuv'] - $row['uv'] + $row['no'] /0+3.5;
速度应该是最快的了吧,但测试结果也一样。

第二种e 的效率测试了没有,感觉会快点呢。

还想怎么快,没法再快了。你直接用数据值计算:
echo ( $row['pv'] + $row['uv'] )/( $row['uv'] - $row['nuv'] +1)*10+ $row['nuv'] - $row['uv'] + $row['no'] /0+3.5;
速度应该是最快的了吧,但测试结果也一样。
你还没看清需求吧,如果公式变了呢?
有几百个公式呢?

第二种e 的效率测试了没有,感觉会快点呢。
基本一样,e修正符就是把replace当成eval来执行了

//提供的数据源,需要先进行排序,将字符数多的键排前面$row = array(        'nuv'       =>  2,        'pv'        =>  50,        'uv'        =>  6,        'st'        =>  650,);$search  = array_keys($row);$replace = array_values($row);function cal(){    global $search, $replace;    //需求公式,可能有些量不存在:如no    $gx = '(pv+uv)/(uv-nuv+1)*10+nuv-uv+no/0+3.5';    $gx = str_replace($search, $replace, $gx);// 改用str_replace替代preg_replace,效率会高一些    $str = "@\$s = $gx;";//合法php语句    try{        @eval($str);//str和eval前使用@确保不显示错误,如某个变量不存在,或除数为0等    }catch(Exception $e){}}$t1 = microtime(true);for ($i = 0; $i < 10000; $i++){    cal();}echo microtime(true) - $t1;// output: 0.18727397918701

PHP code?123456789101112131415161718192021222324252627282930313233//提供的数据源,需要先进行排序,将字符数多的键排前面$row = array(        'nuv'       =>  2,        'pv'        =>  50,        'uv'        =>  6,  ……

多谢你的回答。

你这个方法我也试用过,但会出现一些问题的
$gx = str_replace($search, $replace, $gx);

$row = array(   'uv' => 50,   'nuv' => 60);$gx = 'uv+nuv+uv';$gx = str_replace($search, $replace, $gx);//输出:50+n50+50

但主要的效率存在于 eval 这里,str_replace 替换 preg 这个方式,提升的效率不太理想

一万次 0.25 秒已经够快了

eval 时有一个语法分析过程,比较耗时
分别测试了正则和eval的耗时,preg_replace 占 30%多点,eval 占 60% 多点
仅从代码层面是不能解决问题的
你或许应考虑预编译到程序文件或phar

引用 7 楼 ustb 的回复:PHP code?123456789101112131415161718192021222324252627282930313233//提供的数据源,需要先进行排序,将字符数多的键排前面$row = array(        'nuv'       =>  2,        'pv'        =>  50,        'uv'……

第一行就说了需要先排序的。。。

引用 8 楼 yangball 的回复:引用 7 楼 ustb 的回复:PHP code?123456789101112131415161718192021222324252627282930313233//提供的数据源,需要先进行排序,将字符数多的键排前面$row = array(        'nuv'       =>  2,        'pv'       ……
哦,不好意思,没留意着。
先排序是能解决。

一万次 0.25 秒已经够快了

eval 时有一个语法分析过程,比较耗时
分别测试了正则和eval的耗时,preg_replace 占 30%多点,eval 占 60% 多点
仅从代码层面是不能解决问题的
你或许应考虑预编译到程序文件或phar
暂时就没有更好的办法了。暂时先用着这方法。
看来需要写扩展来实现比较靠谱了

够快了吧,要多快,要啥自行车啊!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn