比較的乾燥したこの部分では、独自のミネラルウォーターをご持参ください
トピックを説明するための第6条ポイント
- PHP運用のメカニズムと原則
- PHP基本となる可変データ構造
- の値によってPHPの割り当てCOW機能
- PHPのガベージコレクションメカニズム
- 基礎となる分析におけるPHPの配列
- PHPの配列関数の分類
PHP運用のメカニズムと原則
スキャン - >パース - >コンパイル - >実行 - >出力
ステップ
- スキャニング
コードの構文と字句解析、切断された断片の内容(トークン)
- 解決
コードスニペットは、スペースや他のコメントを選別、トークンの残りの部分は、意味のある表情に変わります
- コンパイル
中間コードにコンパイルされた式(オペコード)
- 実行
中間コード実行部
- 輸出
実行結果がバッファに出力されます。
コードカッティング
$code = <<<EOF
<?php
echo 'hello world'l;
$data = 1+1;
echo $data;
EOF;
print_r(token_get_all($code));
結果
Array
(
[0] => Array
(
[0] => 376
[1] => <?php
[2] => 1
)
[1] => Array
(
[0] => 319
[1] => echo
[2] => 2
)
[2] => Array
(
[0] => 379
[1] =>
[2] => 2
)
[3] => Array
(
[0] => 318
[1] => 'hello world'
[2] => 2
)
[4] => Array
(
[0] => 310
[1] => l
[2] => 2
)
[5] => ;
[6] => Array
(
[0] => 379
[1] =>
[2] => 2
)
[7] => =
[8] => Array
(
[0] => 379
[1] =>
[2] => 3
)
[9] => Array
(
[0] => 308
[1] => 1
[2] => 3
)
[10] => +
[11] => Array
(
[0] => 308
[1] => 1
[2] => 3
)
[12] => ;
[13] => Array
(
[0] => 379
[1] =>
[2] => 3
)
[14] => Array
(
[0] => 319
[1] => echo
[2] => 4
)
[15] => Array
(
[0] => 379
[1] =>
[2] => 4
)
[16] => ;
)
上記の情報は、次の3つの観察することができます
- そのようなスペース、キャリッジリターンなどのトークンIDが379であります
- トークン文字列
- 行番号
で定義されたトークンIDは、Zendのトークンに対応する内部コードでありますzend_language_parser.h
PHPの効率を向上させます
- 圧縮されたコード、不要なコメントや空白文字を削除する(jquery.min.js)
- 組み込み関数や拡張機能PHPを使用してみてください
- APC / XCacheと/ opcacheと、このようなPHPのオペコードキャッシュとして
- キャッシュの複雑で時間のかかる操作の結果
- 電子メールの送信など、非同期処理を同期することはできません
- HHVMなぜ速いです
(javaのに似ている)仮想マシンを実行するために、直接PHPバイナリバイトコードに変換し、常に実行時に解決するために行っていません。
PHP基本となる可変データ構造
zvalのストレージ構造を使用して、以下のコードがZend/zend.h
定義されています
typedef union _zvalue_value
{
/* 下面定义描述了PHP的8大数据类型 */
long lval; // 长整型 布尔型
double dval; // 浮点型
struct { // 字符串型
char *val;
int len; // strlen 返回这个值
} str; // NULL 类型表示本身为空
HashTable *ht; // 数组使用哈希表实现
zend_object_value obj; // 对象类型
} zvalue_value;
struct _zval_struct
{
zvalue_value value; /* 变量的值 */
zend_uint refcount__gc;
zend_uchar type; /* 变量的类型 */
zend_uchar is_ref__gc
};
typedef struct _zval_struct zval;
可変型定義は、次のコードがZend/zend_types.h
定義されています
typedef unsigned int zend_uint;
typedef unsigned char zend_uchar;
統一を介してデータのPHP 8つの主要なタイプzvalue_value
のストレージのコモンウェルス
联合体自身为空 描述 null
long 描述 int bool
double 描述 float
str 描述 string
HashTable 描述 数字数组和关联数组
zend_object_value 描述 对象和资源
PHPの変数の型は、使用説明zend_uchar type
説明
#define IS_NULL 0
#define IS_LONG 1
#define IS_DOUBLE 2
#define IS_BOOL 3
#define IS_ARRAY 4
#define IS_OBJECT 5
#define IS_STRING 6
#define IS_RESOURCE 7
#define IS_CONSTANT 8
#define IS_CONSTANT_ARRAY 9
例えば、$a=3
構造は、(擬似)以下
struct {
zvalue_value = 3;
refcount__gc = 1;
type = IS_LONG;
is_ref__gc = 0;
}
$a
上記構造体へのポインタのような
の値によってPHPの割り当てCOW機能
内_zval_struct
のデータ構造と同様に、次の二つの部材
- zend_uint refcount__gcは、引用された回数だけ、各時間基準+1を表します
- zend_uchar通常変数または参照変数を表しis_ref__gc
メカニズムを理解するためにコードを書くことにより、以下の引用文
ここで私はphp5.4を使用しています、あなたは可変基準xdebugのを見るためにインストールする必要があります
参照の数が0であったであろう時にphp7.2テストの使用を注意してください
コンパイルされたxdebug.so
yum -y install php-devel
tar xf xdebug-2.8.0alpha1.tgz
cd xdebug-2.8.0alpha1
phpize
find /usr/ -name "php-config"
./configure --with-php-config=/usr/bin/php-config
make && make install
ls /usr/lib64/php/modules/
設定xdebugの
php --ini
echo 'zend_extension=/usr/lib64/php/modules/xdebug.so' >> /etc/php.ini
systemctl restart php72-php-fpm.service
php -m | grep xdebug
テストコードを書きます
$a = 3;
xdebug_debug_zval('a');
輸出
A:(参照カウント= 1、is_ref = 0)= 3
refcount
参照番号1is_ref
0は、通常の変数を示し=3
図3は、値を表します
引用開始
$a = 3;
$b = $a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
輸出
A:(参照カウント= 2、is_ref = 0)= 3
B:(参照カウント= 2、is_ref = 0)= 3
新しい価値を考えます
$a = 3;
$b = $a;
$b = 5;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
輸出
A:(参照カウント= 1、is_ref = 0)= 3
B:(参照カウント= 1、is_ref = 0)= 5
配信アドレス
$a = 3;
$b = &$a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
輸出
A:(参照カウント= 2、is_ref = 1)= 3
B:(参照カウント= 2、is_ref = 1)= 3
共通可変基準変数に変数から転送is_ref
新しい価値を考えます
$a = 3;
$b = &$a;
$c = $a;
$b = 5;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
xdebug_debug_zval('c');
A:(参照カウント= 2、is_ref = 1)5 =
(参照カウント= 2、is_ref = 1)= 5:B
C:(参照カウント= 1、is_ref = 0)= 3
概要
変数の値は、新しいスペースを開くリソースを節約することなく、代入形式の間で参照によって渡されます
変数の値が変更された場合、それは、コピーオンライトとして知られる新しい価値、間接参照を保存するためにコピーします(COW)
参照変数は、COWをトリガしません。
PHPのガベージコレクションメカニズム
ゴミは何ですか
上海の人々:あなたは何を数えるゴミ?
いいえ変数の参照、それzvalの場合、それはゴミです
?:(参照カウント= 0、is_ref = 0)= 5
なぜゴミをクリーンアップするのでしょうか?
一部の人々はそのスレッドの終了時にすべてのPHP変数を破壊するであろうと言う、近くにはすべてのリソースを処理し、ない自動の事、なぜクリーンアップする必要があります
- リサイクルなしに処理(例えば、映画1Gなど)PHP短いハンドル複数の大きなファイルは、次のものを継続した場合、メモリのオーバーフローになり
- PHPスクリプトは、デーモンまたは長時間実行、ないゴミがある場合は、ゆっくりとメモリオーバーフローとなり、蓄積
ゴミをクリーンアップする方法
- ごみを探して
- 取り除きます
- ごみを探して
get_defined_vars
定義されているすべての変数を表示します
基礎となるコードは、zend_globals.h
すべての変数を格納するための2つのハッシュテーブルを定義します
struct _zend_executor_globals {
...
HashTable *active_symbol_table; //局部变量符号表
HashTable symbol_table; //全局变量符号表
...
}
すべての定義された変数を見つけた後、どのような変数の参照番号0見つけます
struct _zval_struct{
...
zend_uint refcount__gc;
zend_uchar is_ref__gc;
...
}
- 酷いです
以上のように、変数0 refcount__gcクリアランス、アイデアはPHP5.2バージョンの前に練習することです
PHP5.3使用後引用计数系统中同步周期回收
アルゴリズムを削除します
実際には、新しいアルゴリズムを回復さrefcount__gcに基づいているので、なぜそれのための新しいアルゴリズムを使うのか?
refcount__gc 0はゴミでなければならない私たちを知っています
しかし、すべてのゴミrefcount__gc 0です
Refcount__gcもないスパム、以下の実験は、0 0スパムを生成することが
例
$a = ['a'];
$a[] = &$a; //引用自己
xdebug_debug_zval('a');
輸出
A:(参照カウント= 2、is_ref = 1)=配列(
0 =>(参照カウント= 1、is_ref = 0)= ''、
1 =>(参照カウント= 2、is_ref = 1)= ...
)
第二の要素:代表的な再帰...、参照番号2は、ポインタ参照変数であります
公式写真提供
この時点で、$ aを削除
$a = ['a'];
$a[] = &$a;
unset($a);
xdebug_debug_zval('a');
出力
A:いいえ、そのようなシンボル
$ aが削除されるので、Xdebugのプリントが出てこないので、次のようにこの時間は理論が構成されているので、
(参照カウント= 1、is_ref = 1)=配列(
0 =>(参照カウント= 1、is_ref = 0)= ''、
1 =>(参照カウント= 1、is_ref = 1)= ...
)
この時点で、このzvalのは何のシンボル(記号)が引用されていない、しかし、その独自の引用の自分は、参照カウントは1であるので、それはゴミの素晴らしい作品です
最後はスペースを取るだろうこの場合のPHPスクリプトの終わりには、自動的にクリア
だから、前5.2へのごみのアイデアのバージョンは、このケースをカバーすることはできません
参照カウントシステム同期回復サイクルアルゴリズム(システム参照カウントでの同時サイクルコレクション)
一例として、上記のコードを続行
新しいアルゴリズムの説明:
$a
疑いのジャンク変数として、削除(refcount--)をシミュレートし、その後の回復をシミュレートするために、復元条件は、値があれば(++参照カウント)シミュレートされた回復参照他の変数があります
このような成功は、それは削除することができ、ゴミを復元することができません。
上記のごみ素晴らしい例:
(参照カウント= 1、is_ref = 1)=配列(
0 =>(参照カウント= 1、is_ref = 0)= ''、
1 =>(参照カウント= 1、is_ref = 1)= ...
)
シミュレーションを削除した後次のようになります。
(参照カウント= 0、is_ref = 1)=配列(
0 =>(参照カウント= 0、is_ref = 0)= ''、
1 =>(参照カウント= 0、is_ref = 1)= ...
)
その後、回復をシミュレートします:
そのようなシンボルがzvalをを取るために同様のポイントが$されていないので、それがに復元されていません
ときにクリア
上記のアルゴリズムによってスパムがエリア(のRCP)に格納される可能性があり、唯一の完全なゴミの直後にクリアされます。前提はオープンガベージコレクションであることに注意してください
二つの方法で開くガベージコレクション
php.iniの下では
zend.enable_gc = On
デフォルトで有効になってよる
gc_enable()
とgc_disable()
開いたり閉じガベージコレクション
それは次のように使用することができるgc_collect_cycles()
強制回復期間の機能
最後に、そんなに、実際には、唯一の関与の原則を理解する必要があり、全体のプロセスが参加するPHP開発者を必要としないと述べ、ちょうどgc_enable呼び出し()またはgc_collect_cycles()を自動的に回収することができます
基礎となる分析におけるPHPの配列
プロパティの配列を確認するには
PHPの配列の主な機能
$arr = [
1 => 'a',
'1' => 'b',
1.5 => 'c',
true => 'd',
];
print_r($arr);
アレイ
(
[1] => D
)
キーは、整数または文字列のいずれかになります
値は任意の型を指定できます
キーは、次のような特徴を持っています
- 数値文字列を整数に変換する「1」=> 1
- 1.3 =「1に変換、浮動小数点および整数ブール
- 空の文字列として扱われますヌルヌル=>「」
- キー名は、オブジェクトや配列を使用することはできません
- 同じキー名の後ろのフロントカバー
アクセス配列の要素
- $のARR [キー]
- $ arrの{キー}
次のように5.4バージョンを使用することができた後、
function getArr(){ return [1,2,3,4]; }
echo getArr()[2];
配列要素を削除します。
$a = [1,2,3,4];
foreach ($a as $k => $v) {
unset($a[$k]);
}
$a[] = 5;
print_r($a);
アレイ
(
[4] => 5
)
- インデックスをリセットしません削除
アレイトラバーサル
- にとって
- foreachの
- あるarray_walk
- array_mapを
- 現在の和次
内部配列を達成
実装は、次の2つの構造を使用HashTable
し、bucket
- ハッシュテーブルは何ですか
ハッシュテーブルは、データ構造は、キーワードによって直接メモリ記憶場所にアクセスします。
(1)、検索、挿入、変更、削除Oで完了さ:キーワードの位置が、そのようなマッピングテーブルを得るために、ハッシュ関数によって計算されます
次のコード Zend/zend_types.h
typedef struct _zend_array HashTable;
struct _zend_array {
zend_refcounted_h gc;
union {
struct {
ZEND_ENDIAN_LOHI_4(
zend_uchar flags,
zend_uchar nApplyCount,
zend_uchar nIteratorsCount,
zend_uchar consistency)
} v;
uint32_t flags;
} u;
uint32_t nTableMask;
Bucket *arData;
uint32_t nNumUsed;
uint32_t nNumOfElements;
uint32_t nTableSize;
uint32_t nInternalPointer;
zend_long nNextFreeElement;
dtor_func_t pDestructor;
};
古い構造
typedef struct _hashtable {
uint nTableSize;
uint nTableMask;
uint nNumOfElements;
ulong nNextFreeElement;
Bucket *pInternalPointer;
Bucket *pListHead;
Bucket *pListTail;
Bucket **arBuckets;
unsigned char nApplyCount;
};
メンバー | 説明 |
---|---|
nTableSize | バケットサイズ、2倍の増加に8の最小 |
nTableMask | インデックスチューニングnTableSize-1 |
nNumOfElements | count()関数を使用して、要素の数は、直接に返します |
nNextFreeElement | foreachのを使用して次のインデックス位置 |
pInternalPointer | 現在の反復ポインタ、より高速な理由のためのよりforeachのは、現在の関数の使い方をリセット |
pListHead | 存储数组头部指针 |
pListTail | 存储数组尾部指针 |
arBuckets | 实际存储容器 |
arData | Bucket数据 |
nApplyCount | 记录被递归次数,防止死循环递归 |
typedef struct bucket
{
ulong h;
uint nKeyLength;
void *pData;
void *pDataPtr;
struct bucket *pListNext;
struct bucket *pListLast;
struct bucket *pNext;
struct bucket *pLast;
const char *arKey;
};
成员 | 说明 |
---|---|
h | 对char *key进行hash后的值,或是用户指定数字索引值 |
nKeyLength | 哈希关键字长度,若为索引数字则为0 |
pData | 指向value 一般是用户数据的副本,若为指针数据则指向指针 |
pDataPtr | 如果是指针数据,指针会指向真正value,上面指向此 |
pListNext | 整个hash表下个元素 |
pListLast | 整个hash表上个元素 |
pNext | 同一个hash的下一个元素 |
pLast | 同一个hash的上一个元素 |
arKey | 保存当前key对应的字符串 |
foreach 遍历先从 HashTable 的 pListHead -> pListNext
pNext
和 pLast
用于hash冲突同一个hash不同个bucket之间指针
PHP数组函数分类
建议体验一下下面的函数,不用记住,只是留个印象,当你需要用的时候会联想起来的,而不用自己去实现
遍历
- prev
- next
- current
- end
- reset
- each
排序
- sort
- rsort
- asort
- ksort
- krsort
- uasort
- uksort
查找
- in_array
- array_search
- array_key_exists
分合
- array_slice
- array_splice
- implode
- explode
- array_combine
- array_chunk
- array_keys
- array_values
- array_columns
集合
- array_merge
- array_diff
- array_diff_*
- array_intersect
- array_intersect_*
队列/栈
- array_push
- array_pop
- array_shift
其他
- array_fill
- array_flip
- array_sum
- array_reverse
再現、ソースを明記してくださいhttps://www.cnblogs.com/demonxian3/p/11327522.htmlを