shm get var返回拷貝還是引用?

2021-09-22 07:10:55 字數 2072 閱讀 5945

本文目的

本文**了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)))

$nvarkey = 1;

if(!shm_put_var($nshmid, $nvarkey, $arr))

if(!($arr1 = shm_get_var($nshmid, $nvarkey)))

array_pop($arr1);

if(!($arr2 = shm_get_var($nshmid, $nvarkey)))

if ($arr != $arr2) else

if(!shm_remove($nshmid))

?>

執行結果如下:

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

原始**

為什麼會返回copy呢?可以看看shm_get_var的c**實,檔案位置php_src/ext/sysvshm/sysvshm.c,如下:

/* 

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)

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_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?

錯誤處理的返回 異常還是返回值

推薦使用異常 因為異常設計就是為了決解 什麼出了錯?在哪齣的錯?為什麼出錯?1.通過使用異常可以明確 錯誤的型別,錯誤的原因,錯誤出現的地方並且呼叫者強制處理,這提高程式的健壯性 robust 而返回值方式需要呼叫者主動去處理。2.使用異常可以使 更加優雅 可讀性提高。不用寫各種if else判斷情...

丟擲異常還是約定返回值

b 具體場景如下 b 現在要執行乙個業務操作方法,這個業務方法執行要有n個前置條件滿足才能執行 現在使用統一mvc架構,呼叫者要收到反饋,知道沒ok,根據反饋進行一些列的後續操作,比如通知使用者去哪完善,怎麼完善 那麼怎麼處理?第一種 n個前置條件的檢驗,放到action裡面做,如果不滿足返回相關頁...

php介面返回資料 用echo 還是return

今天在ci框架中用 return 返回 josn encode資料 給前台ajax 前台獲取始終為空。原生php return也為空 改為echo後就可以獲取到。本人之前用tp的時候一直用return就能獲取到。最終看了別人的一些ci 這種情況也是用的echo return 作為函式返回值或結束語句...