<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 3.5 運行時緩存 在本節開始之前我們先分析一個例子: ```php class my_class { public $id = 123; public function test() { echo $this->id; } } $obj = new my_class; $obj->test(); $obj->test(); ... ``` 這個例子定義了一個類,然后多次調用同一個成員方法,這個成員方法功能很簡單:輸出一個成員屬性,根據前面對成員屬性的介紹可以知道其查找過程為:"首先根據對象找到所屬zend_class_entry,然后再根據屬性名查找`zend_class_entry.properties_info`哈希表,得到`zend_property_info`,最后根據屬性結構的offset定位到屬性值的存儲位置",概括一下這個過程就是:zend_object->zend_class_entry->properties_info->屬性值,那么問題來了:每次執行`my_class::test()`時難道上面的過程都要完整走一遍嗎? 我們再仔細看下這個過程,字面量"id"在"$this->id"此條語句中就是用來索引屬性的,不管執行多少次它的任務始終是這個,那么有沒有一種辦法將"id"與查找到的zend_class_entry、zend_property_info.offset建立一種關聯關系保存下來,這樣再次執行時直接根據"id"拿到前面關聯的這兩個數據,從而避免多次重復相同的工作呢?這就是本節將要介紹的內容:運行時緩存。 在執行期間,PHP經常需要根據名稱去不同的哈希表中查找常量、函數、類、成員方法、成員屬性等,因此PHP提供了一種緩存機制用于緩存根據名稱查找到的結果,以便再次執行同一opcode時直接復用上次緩存的值,無需重復查找,從而提高執行效率。 開始提到的那個例子中會緩存兩個東西:zend_class_entry、zend_property_info.offset,此緩存可以認為是opcode操作的緩存,它只屬于"$this->id"此語句的opcode:這樣再次執行這條opcode時就直接取出上次緩存的兩個值。 所以運行時緩存機制是在同一opcode執行多次的情況下才會生效,特別注意這里的同一opcode指的并不是opcode值相同,而是指內存里的同一份數據,比如:`echo $a; echo $a;`這種就不算,因為這是兩條opcode。 那么緩存是如何保存和索引的呢?執行opcode時如何知道緩存的位置? 實際上運行時緩存是基于所屬opcode中CONST操作數存儲的,也就是說只有包含IS_CONST類型的操作數才有可能用到此機制,其它類型都不會用到,這是因為只有CONST操作數是固定不變的,其它CV、VAR等類型值都不是固定的,既然其值是不固定的那么緩存的值也就不是固定的,所以不會針對CONST以外類型的opcode操作進行緩存,還是以開始那個例子為例,比如:`echo $this->$var;`這種,操作數類型是CV,其正常查找時的zend_property_info是隨$var值而變的,所以給他們建立一種不可變的關聯關系,而:`echo $this->id;`中"id"是固定寫死的,它索引到zend_property_info始終是不變的。 緩存的存儲格式是一個數組,用于保存緩存的數據指針,而指針在數組中的起始存儲位置則保存在CONST操作數對應的`zval.u2.cache_slot`中(前面講過,CONST操作數對應值的zval保存在zend_op_array->literals數組中)。上面那個例子對應的緩存結構: ![](https://box.kancloud.cn/36016b30e86e50297683a4b522454628_503x275.png) * __(1)__ 第一次執行`echo $this->id;`時首先根據$this取出zend_class_entry,然后根據“id”查找zend_class_entry.properties_info找到屬性zend_property_info,取出此結構的offset,第一次執行后將zend_class_entry及offset保存到了test()函數的zend_op_array->run_time_cache中,占用16字節,起始位置為0,這個值記錄在“id”的zval.u2.cache_slot中; * __(2)__ 之后再次執行`echo $this->id;`時直接根據opline從zend_op_literals中取出“id”的zval,得到緩存數據保存位置:0,然后去zend_op_array->run_time_cache取出緩存的zend_class_entry、offset。 這個例子緩存數據占用了16字節(2個sizeof(void*))大小的空間,而有的只需要8字節,取決于操作類型: * 8字節:常量、函數、類 * 16字節:成員屬性、成員方法、類常量 另外一個問題是這些操作數的緩存位置(zval.u2.cache_slot)是在什么階段確定的呢?實際上這個值是在編譯階段確定的,通過zend_op_array.cache_size記錄緩存可用起始位置,編譯過程中如果發現當前操作適用緩存機制,則根據緩存數據的大小從cache_size開始分配8或16字節給那個操作數,cache_size向后移動對應大小,然后將起始位置保存于CONST操作數的zval.u2.cache_slot中,執行時直接根據這個值確定緩存位置。 具體緩存的讀寫通過以下幾個宏完成: ```c //設置緩存 CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1/2)), ptr); //ptr: 緩存的數據指針 //讀取緩存 CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1/2))); //EX_CONSTANT(opline->op1/2)是取當前IS_CONST操作數對應數據的zval ``` 展開后: ```c ((void**)((char*)execute_data->run_time_cache + (num)))[0] ``` `execute_data->run_time_cache`緩存的`zend_op_array->run_time_cache`。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看