zoukankan      html  css  js  c++  java
  • shm_get_var返回拷贝还是引用?

    本文目的

    本文探讨了php标准扩展sysvshm库中的函数shm_get_var返回变量的copy还是reference

    问题背景

    php标准扩展中的sysvshm提供了php访问共享内存的能力,而且数据的最小粒度是变量,这样可以免去手动变量序列化和反序列化,比另一个标准扩展shmop好使用。但是,如果假设有一个50M的数组放到共享内存中,反复的访问此变量,是否会影响系统性能?如果shm_get_var返回的是变量引用,那么性能开销不大,因为每次返回的都只是内存的“指针”,不会拷贝真实数据。如果返回的是copy呢?那么每访问一次,就需要拷贝50M左右的内存,如果访问频率过大,那么就会导致性能瓶颈。

    验证

    到底返回什么,通过下面的代码,可以得到验证:

    <?php
    $arr = array(0,1,2,3,4,5,6);
    
    if(!($nShmID = shm_attach(ftok(__FILE__, 'i'), 1024))) {
    	die("create shared memory failed.\n");
    }
    
    $nVarKey = 1;
    if(!shm_put_var($nShmID, $nVarKey, $arr)) {
    	die("failed to put var\n");
    }
    
    
    if(!($arr1 = shm_get_var($nShmID, $nVarKey))) {
    	die("failed to get arr1\n");
    }
    array_pop($arr1);
    
    
    if(!($arr2 = shm_get_var($nShmID, $nVarKey))) {
    	die("failed to get arr2\n");
    }
    
    
    if ($arr != $arr2) {
    	echo "get a copy\n";
    } else {
    	echo "get a reference\n";
    }
    
    
    if(!shm_remove($nShmID)) {
    	die("failed to remove shared memory\n");
    }
    ?>

    执行结果如下:

    clip_image002

    所以,很明显,返回的是copy而不是reference。

    原始代码

    为什么会返回copy呢?可以看看shm_get_var的c代码实,文件位置PHP_SRC/ext/sysvshm/sysvshm.c,如下:

    /* {{{ proto mixed shm_get_var(resource id, int variable_key)
    Returns a variable from shared memory */
    PHP_FUNCTION(shm_get_var)
    {
    	zval *shm_id;
    	long shm_key;
    	sysvshm_shm *shm_list_ptr;
    	char *shm_data;
    	long shm_varpos;
    	sysvshm_chunk *shm_var;
    	php_unserialize_data_t var_hash;
    
    
    	if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &shm_id, &shm_key)) {
    		return;
    	}
    	SHM_FETCH_RESOURCE(shm_list_ptr, shm_id);
    
    	/* setup string-variable and serialize */
    	/* get serialized variable from shared memory */
    	shm_varpos = php_check_shm_data((shm_list_ptr->ptr), shm_key);
    
    	if (shm_varpos < 0) {
    		php_error_docref(NULL TSRMLS_CC, E_WARNING, "variable key %ld doesn't exist", shm_key);
    		RETURN_FALSE;
    	}
    
    	shm_var = (sysvshm_chunk*) ((char *)shm_list_ptr->ptr + shm_varpos);
    	shm_data = &shm_var->mem;
    
    
    	PHP_VAR_UNSERIALIZE_INIT(var_hash);
    	if (php_var_unserialize(&return_value, (const unsigned char **) &shm_data, (unsigned char *) shm_data + shm_var->length, &var_hash TSRMLS_CC) != 1) {
    		php_error_docref(NULL TSRMLS_CC, E_WARNING, "variable data in shared memory is corrupted");
    		RETVAL_FALSE;
    	}
    	PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
    }
    /* }}} */

    从上面的代码,可以知道shm_get_var的内部实现会调用php_var_unserialize进行反序列化,也就表示变量其实还是以序列化后的字节流形式存放在共享内存中,这样必然无法返回变量引用,只能返回拷贝。shm_get_var只是为我们做了反序列化工作,本质上与shmop_read一样。

    结论

    由于php_get_var返回的是变量拷贝,如果需要反复访问共享内存中的较大的变量时,最好换一种存储策略,因为共享内存会重复拷贝数据,造成不必要的性能开销。

    参考资料

    stackOverflow: Does PHP copy variables when retrieving from shared memory?

  • 相关阅读:
    (转载)VS2010/MFC编程入门之三十七(工具栏:工具栏的创建、停靠与使用)
    (转载)VS2010/MFC编程入门之三十五(菜单:菜单及CMenu类的使用)
    (转载)VS2010/MFC编程入门之三十三(常用控件:标签控件Tab Control 下)
    (转载)VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)
    ubuntu下格式化u盘
    Android笔记之AppWidget
    Android笔记之ViewPager实现滑动页面
    Android笔记之获取布局中的多个子控件
    Android笔记之Actionbar制作选项卡(可滑动)
    Android笔记之Actionbar使用(二)
  • 原文地址:https://www.cnblogs.com/bourneli/p/2623939.html
Copyright © 2011-2022 走看看