PHP SPL标准库 SplFixedArray 介绍及和Array的性能测试

 更新时间:2016年11月25日 16:18  点击:1841
SPL - Standard PHP Library ,标准PHP类库,本文我们来看看SPL标准库之数据结构SplFixedArray,及SplFixedArray和Array的性能测试对比。

SplFixedArray主要是处理数组相关的主要功能,与普通php array不同的是,它是固定长度的,且以数字为键名的数组,优势就是比普通的数组处理更快。

看看我本机的Benchmark测试:

ini_set('memory_limit','12800M');

for($size = 10000; $size < 10000000; $size *= 4) {
    echo PHP_EOL . "Testing size: $size" . PHP_EOL;
    for($s = microtime(true), $container = Array(), $i = 0; $i < $size; $i++) $container[$i] = NULL;
    echo "Array(): " . (microtime(true) - $s) . PHP_EOL;

    for($s = microtime(true), $container = new SplFixedArray($size), $i = 0; $i < $size; $i++) $container[$i] = NULL;
    echo "SplArray(): " . (microtime(true) - $s) . PHP_EOL;
}


结果如下:

Testing size: 10000
Array(): 0.004000186920166
SplArray(): 0.0019998550415039

Testing size: 40000
Array(): 0.017001152038574
SplArray(): 0.0090007781982422

Testing size: 160000
Array(): 0.050002098083496
SplArray(): 0.046003103256226

Testing size: 640000
Array(): 0.19701099395752
SplArray(): 0.16700983047485

Testing size: 2560000
Array(): 0.75704312324524
SplArray(): 0.67303895950317


通常情况下SplFixedArray要比php array快上20%~30%,所以如果你是处理巨大数量的固定长度数组,还是强烈建议使用。

SplFixedArray类摘要如下:

SplFixedArray  implements Iterator   , ArrayAccess   , Countable   {
    /* 方法 */
    public __construct  ([ int $size  = 0  ] )
    public int count  ( void )
    public mixed current  ( void )
    public static SplFixedArray fromArray  ( array $array  [, bool $save_indexes  = true  ] )
    public int getSize  ( void )
    public int key  ( void )
    public void next  ( void )
    public bool offsetExists  ( int $index  )
    public mixed offsetGet  ( int $index  )
    public void offsetSet  ( int $index  , mixed  $newval  )
    public void offsetUnset  ( int $index  )
    public void rewind  ( void )
    public int setSize  ( int $size  )
    public array toArray  ( void )
    public bool valid  ( void )
    public void __wakeup  ( void )
}


 使用SplFixedArray:

$arr = new SplFixedArray(4);
$arr[0] = 'php';
$arr[1] = 1;
$arr[3] = 'python';

//遍历, $arr[2] 为null
foreach($arr as $v) {
    echo $v . PHP_EOL;
}

//获取数组长度
echo $arr->getSize(); //4

//增加数组长度
$arr->setSize(5);
$arr[4] = 'new one';

//捕获异常
try{
    echo $arr[10];
} catch (RuntimeException $e) {
    echo $e->getMessage();
}




SplFixedArray和Array的性能测试

PHP文档专门说明:

The SplFixedArray class provides the main functionalities of array. The main differences between a SplFixedArray and a normal PHP array is that the SplFixedArray is of fixed length and allows only integers within the range as indexes. The advantage is that it allows a faster array implementation.

所以在处理大型的、以数字为索引的数组时,应该用SplFixedArray来代替普通Array。

下面是测试代码:

<?php
function pr() {
    $params = func_get_args();
    $env = php_sapi_name();
    if ("cli" == $env) {
        foreach ($params as $key => $value) {
            echo $value;
        }
    } else {
        foreach ($params as $key => $value) {
            echo "<pre>";
            print_r($value);
            echo "</pre>";
        }
    }
} // 用来打印输出结果


<?php
require dirname(__FILE__)."/function.php";

for ($size=1000; $size<=50000000; $size*=2) {
    pr(PHP_EOL . "Testing size: $size" . PHP_EOL);
    for($s = microtime(true), $container = Array(), $i = 0; $i < $size; $i++) {
        $container[$i] = NULL;
    }
    pr( "Array(): " . (microtime(true) - $s) . PHP_EOL);

    for($s = microtime(true), $container = new SplFixedArray($size), $i = 0; $i < $size; $i++) {
        $container[$i] = NULL;
    }
    pr("SplArray(): " . (microtime(true) - $s) . PHP_EOL);
}

但是在我的测试机器上,这段代码出现了非常诡异的结果:

http://img.my.csdn.net/uploads/201304/13/1365855461_6895.jpg
暂时想不出来是什么原因:难道是因为虚拟机内存太小,导致最后的SplFixedArray插入时需要不断GC才导致时间太长?

下面我们来看一篇关于php性能分析之php-fpm的慢执行日志slow log文章,希望文章对各位有帮助


众所周知,mysql有slow query log,根据慢查询日志,我们可以知道那些sql语句有性能问题。作为mysql的好搭档,php也有这样的功能。如果你使用php-fpm来管理php的话,你可以通过如下选项开启。

PHP 5.3.3 之前设置如下:

<value name=”request_slowlog_timeout”>5s</value>
<value name=”slowlog”>logs/php-fpm-slowlog.log</value>
PHP 5.3.3 之后设置以下如下:
request_slowlog_timeout = 5s
slowlog = /usr/local/php/log/php-fpm-slowlog.log

说明:

request_slowlog_timeout是脚本超过多长时间 就可以记录到日志文件
slowlog 是日志文件的路径
开启后,如果有脚本执行超过指定的时间,就会在指定的日志文件中写入类似如下的信息:

[19-Dec-2013 16:54:49] [pool www] pid 18575
script_filename = /home/admin/web/htdocs/sandbox_canglong/test/tt.php
[0x0000000003a00dc8] curl_exec() /home/admin/web/htdocs/sandbox_canglong/test/tt.php:2
[0x0000000003a00cd0] exfilter_curl_get() /home/admin/web/htdocs/sandbox_canglong/test/tt.php:6

日志说明:

script_filename 是入口文件

curl_exec() : 说明是执行这个方法的时候超过执行时间的。
exfilter_curl_get() :说明调用curl_exec()的方法是exfilter_curl_get() 。
每行冒号后面的数字是行号。

开启后,在错误日志文件中也有相关记录。如下:

[19-Dec-2013 15:55:37] WARNING: [pool www] child 18575, script ‘/home/admin/web/htdocs/sandbox_canglong/test/tt.php’ (request: “GET /test/tt.php”) executing too slow (1.006222 sec), logging
[19-Dec-2013 15:55:37] NOTICE: child 18575 stopped for tracing
[19-Dec-2013 15:55:37] NOTICE: about to trace 18575
[19-Dec-2013 15:55:37] NOTICE: finished trace of 18575

本文我们来看看PHP自带的session隐患,session文件独占锁引起阻塞的问题,session文件阻塞会影响性能,下面来看看我们的解决方案。

在PHP中,P默认的会话处理器是session.save_handler = files(即文件)。如果同一个客户端同时并发发送多个请求(如ajax在页面同时发送多个请求),且脚本执行时间较长,就会导致session文件阻塞,影响性能。因为对于每个请求,PHP执行session_start(),就会取得文件独占锁,只有在该请求处理结束后,才会释放独占锁。这样,同时多个请求就会引起阻塞。解决方案如下:

(1)修改会话变量后,立即使用session_write_close()来保存会话数据并释放文件锁。

session_start();
 
$_SESSION['test'] = 'test';
session_write_close();
 
//do something



(2)利用session_set_save_handler()函数是实现自定义会话处理。

function open($savePath, $sessionName)
{
    echo 'open is called';
    return true;
}
 
function close()
{
    echo 'close is called';
    return true;
}
 
function read($sessionId)
{
    echo 'read is called';
    return '';
}
 
function write($sessionId, $data)
{
    echo 'write is called';
    return true;
}
 
function destroy($sessionId)
{
    echo 'destroy is called';
    return true;
}
 
function gc($lifetime)
{
    echo 'gc is called';
    return true;
}
 
session_set_save_handler("open", "close", "read", "write", "destroy", "gc");
register_shutdown_function ( 'session_write_close' );
 
session_start();
 
$_SESSION['foo'] = "bar";



当然,在 php 5.4.0之后,你可以通过实现 SessionHandlerInterface 接口或继承 SessionHandler 类来使用。

class MySessionHandler extends SessionHandler  {
 
    public function __construct()
    {
    }
 
    public function open($save_path, $session_id)
    {
    }
 
    public function close()
    {
 
    }
 
    public function create_sid()
    {
    }
 
    public function read($id)
    {
    }
 
    public function write($id, $data)
    {
    }
 
    public function destroy($id)
    {
    }
}
 
$handler = new MySessionHandler();

 
//第2个参数将函数 session_write_close()  注册为 register_shutdown_function()  函数。
session_set_save_handler($handler, true);


你可以对上面的代码进行具体实现和封装,利用mysql或其它内存数据库来管理会话数据。还能解决使用集群时,session数据共享问题。

对于这个php自带的隐患,相信官方过一段时间会有很好的解决办法。

有时我们为了网站安全考虑,我们不允许直接跨域提交form表单数据,如果我们自己有这个需求呢?下面我们来介绍两种跨域的方法解决直接跨域问题。

下面我们来看看两种php跨域提交form的方法

一,通过php curl

    function curlPost($url,$params) 
    { 
     $postData = ''; 
     foreach($params as $k => $v) 
     { 
     $postData .= $k . '='.$v.'&'; 
     } 
     rtrim($postData, '&'); 
     $ch = curl_init(); 
     curl_setopt($ch,CURLOPT_URL,$url); 
     curl_setopt($ch,CURLOPT_RETURNTRANSFER,true); 
     
     curl_setopt($ch,CURLOPT_HEADER, false); 
     curl_setopt($ch, CURLOPT_POST, count($postData)); 
     curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);  
     
     $output=curl_exec($ch); 
     
     curl_close($ch); 
     return $output; 
    } 
     
    echo curlPost("http://test.com",array('name'=>"tank")); 

以前很多人用curl来抓,邮箱的通讯录,不过现在已经不可以了。哈哈。

二,利用jquery form,ajax提交

1,下载jquery.form.js

2,js代码

    $('#testform').submit(function() { 
     $(this).ajaxSubmit({ 
     type: 'post', // 提交方式 get/post 
     dataType:"json",//数据类型 
     url: 'your url', // 需要提交的 url 
     success: function(data) { // data 保存提交后返回的数据,一般为 json 数据 
     // 此处可对 data 作相关处理 
     alert('提交成功!'); 
     } 
     $(this).resetForm(); // 提交后重置表单 
     }); 
     return false; // 阻止表单自动提交事件 
    }); 

3,php代码

    header("Access-Control-Allow-Origin:*"); //跨域权限设置,允许所有 
     
    header("Access-Control-Allow-Origin:http://www.test.com"); //只允许test.com跨域提交数据 

Open Flash Chart多报表我们在许多的网站都会看到这个功能了,今天小编就来为各位介绍Open Flash Chart多报表使用方法吧


将生成好的JSON数据传递给前端,前端通过JS来实现切换效果

例子。

<?php
//
// This is the MODEL section:
//
include '../php-ofc-library/open-flash-chart.php';
$title = new title( date("D M d Y") );
$bar = new bar();
$bar->set_values( array(9,8,7,6,5,4,3,2,1) );
$chart_1 = new open_flash_chart();
$chart_1->set_title( $title );
$chart_1->add_element( $bar );

// generate some random data
srand((double)microtime()*1000000);
$tmp = array();
for( $i=0; $i<9; $i++ )
  $tmp[] = rand(1,10);
$bar_2 = new bar();
$bar_2->set_values( $tmp );
$chart_2 = new open_flash_chart();
$chart_2->set_title( new title( "Chart 2 :-)" ) );
$chart_2->add_element( $bar_2 );

//
// This is the VIEW section:
//
?>
<html>
<head>
<script type="text/javascript" src="js/json/json2.js"></script>
<script type="text/javascript" src="js/swfobject.js"></script>
<script type="text/javascript">
swfobject.embedSWF("open-flash-chart.swf", "my_chart", "350", "200", "9.0.0");
</script>
<script type="text/javascript">
function ofc_ready()
{
    alert('ofc_ready');
}
function open_flash_chart_data()
{
    alert( 'reading data' );
    return JSON.stringify(data_1);
}
function load_1()
{
  tmp = findSWF("my_chart");
  x = tmp.load( JSON.stringify(data_1) );
}
function load_2()
{
  alert("loading data_2");
  tmp = findSWF("my_chart");
  x = tmp.load( JSON.stringify(data_2) );
}
function findSWF(movieName) {
  if (navigator.appName.indexOf("Microsoft")!= -1) {
    return window[movieName];
  } else {
    return document[movieName];
  }
}
    
var data_1 = <?php echo $chart_1->toPrettyString(); ?>;
var data_2 = <?php echo $chart_2->toPrettyString(); ?>;
</script>

</head>
<body>
<p>Open Flash Chart</p>

<div id="my_chart"></div>
<br>
<a href="javascript:load_1()">display data_1</a> || <a href="javascript:load_2()">display data_2</a>
<p>
Don't forget to 'view source' to see how the Javascript JSON data is loaded.
</p>
</body>
</html>

[!--infotagslink--]

相关文章

  • 解决@SpringBootTest 单元测试遇到的坑

    这篇文章主要介绍了解决@SpringBootTest 单元测试遇到的坑,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-10-14
  • DWVA上传漏洞挖掘的测试例子

    DVWA (Dam Vulnerable Web Application)DVWA是用PHP+Mysql编写的一套用于常规WEB漏洞教学和检测的WEB脆弱性测试程序。包含了SQL注入、XSS、盲注等常见的一些安全漏洞...2016-11-25
  • PHP测试成功的邮件发送案例

    mail()函数的作用:连接到邮件服务器,利用smtp协议,与该服务器交互并投邮件。注意:1、mail函数不支持esmtp协议,---即,只能直投,不能登陆2、由上条,我们只能直投至最终的收件服务器地址.而该地址,又是在PHP.ini中指定的,所...2015-10-30
  • 用VirtualBox构建MySQL测试环境

    宿主机使用网线的时候,客户机在Bridged Adapter模式下,使用Atheros AR8131 PCI-E Gigabit Ethernet Controller上网没问题。 宿主机使用无线的时候,客户机在Bridged Adapter模式下,使用可选项里唯一一个WIFI选项,Microsoft Virtual Wifi Miniport Adapter也无法上网,故弃之。...2013-09-19
  • 带你了解PHP7 性能翻倍的关键

    20岁老牌网页程序语言PHP,最快将在10月底释出PHP 7新版,这是十年来的首次大改版,最大特色是在性能上的大突破,能比前一版PHP 5快上一倍,PHP之父Rasmus Lerdorf表示,甚至能比HHVM虚拟机下的PHP程序性能更快。HHVM 是脸书为自...2015-11-24
  • 利用 Chrome Dev Tools 进行页面性能分析的步骤说明(前端性能优化)

    这篇文章主要介绍了利用 Chrome Dev Tools 进行页面性能分析的步骤说明(前端性能优化),本文给大家介绍的非常想详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-02-24
  • JavaScript提高网站性能优化的建议(二)

    这篇文章主要介绍了JavaScript提高网站性能优化的建议(二)的相关资料,需要的朋友可以参考下...2016-07-29
  • 提升jQuery的性能需要做好七件事

    这篇文章主要介绍了提升jQuery的性能需要做好的七件事,希望真的帮助大家提升jQuery性能,需要的朋友可以参考下...2016-01-14
  • PHP测试成功的邮件发送案例

    mail()函数的作用:连接到邮件服务器,利用smtp协议,与该服务器交互并投邮件。注意:1、mail函数不支持esmtp协议,---即,只能直投,不能登陆2、由上条,我们只能直投至最终的收件服务器地址.而该地址,又是在PHP.ini中指定的,所...2015-10-30
  • php测试性能代码

    php测试性能代码 function microtime_float () { list ($usec, $sec) = explode(" ", microtime()); return ((float) $usec + (float) $sec); } functio...2016-11-25
  • phpmyadmin写入一句话木马的测试

    下面我们一起来看看一篇关于phpmyadmin写入一句话木马的测试教程,希望此教程能够对各位有帮助。 方法一,一句话木马偶尔拿到一个config中,发现是root,且还有phpmyadmi...2016-11-25
  • css中空路径对页面性能影响的解决方案

    文章介绍了css中空路径对页面性能影响的解决方案,这个可能很多美工朋友不会去注意这一点,下面我们来看看吧。 在写 CSS 的时候,用 background:url(#) 还是会对页面进...2017-07-06
  • 如何用Node.js编写内存效率高的应用程序

    这篇文章主要介绍了如何用Node.js编写内存效率高的应用程序,对Node.js感兴趣的同学,可以参考下...2021-05-01
  • python自动化测试selenium执行js脚本实现示例

    这篇文章主要为大家介绍了python自动化测试selenium执行js脚本的实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步...2021-11-13
  • Redis 执行性能测试

    这篇文章主要介绍了Redis 执行性能测试的方法,文中讲解非常细致,帮助大家更好的理解和学习redis,感兴趣的朋友可以了解下...2021-01-15
  • js简单网速测试方法完整实例

    这篇文章主要介绍了js简单网速测试方法,以完整实例形式分析了JavaScript基于网页图片下载进行测试网速的实现技巧,需要的朋友可以参考下...2015-12-17
  • 浅析Mysql Join语法以及性能优化

    一.Join语法概述join 用于多表中字段之间的联系,语法如下:复制代码 代码如下:... FROM table1 INNER|LEFT|RIGHT JOIN table2 ON conditionatable1:左表;table2:右表。JOIN 按照功能大致分为如下三类:INNER JOIN(内连接,或...2014-05-31
  • JavaWeb实战之编写单元测试类测试数据库操作

    这篇文章主要介绍了JavaWeb实战之编写单元测试类测试数据库操作,文中有非常详细的代码示例,对正在学习javaweb的小伙伴们有很大的帮助,需要的朋友可以参考下...2021-04-22
  • Springboot 使用具体化类和配置来缩短单元测试时间

    这篇文章主要介绍了Springboot 使用具体化类和配置来缩短单元测试时间,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-11-05
  • oracle索引的测试实例代码

    这篇文章主要给大家介绍了关于oracle索引测试的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-01-17