ようこそゲストさん

CPA-LABテクニカル

メッセージ欄

分類 【PHP変数管理を理解する】 で検索

一覧で表示する

2008/03/16(日) PHPの配列上限数-PHP変数管理

PHP*1では、配列の管理にハッシュテーブル(シンボルテーブル)を使用している
そのサイズは、実質31bitであり*2、上限は16進数で80,000,000、10進数では、
21億4千7百83万3千6百48個となる。

地球の人口は66億人を超えているそうなので、全人類のデータを一度に配列に納める時には、注意しなければならない。

この制限は、ひとつのハッシュテーブルの個数なので、複数に分割、この場合は4つの変数に分割すれば、全人類データを一度に入れるに納めることが、できる*3*4


参考:世界の人口は現在

*1 : バージョン5.2.5

*2 : 32bitのuint(符号なし単精度)を使用しているけど、半分しか使わない構造になっている

*3 : 誰も突っ込まないと思うけど、その前にメモリが足りなくなる

*4 : ただし、環境によっては、個数管理に使われている変数の型unsigned int は一般的には32bitだけど、64bitのこともあるそうなので、その場合は、余裕で全世界の人々のデータを一度に配列にぶち込める。

一番最初に作られる配列の個数は8個である。
1つの配列要素を作っただけでも*5、8個分のハッシュテーブルが用意される。


ZEND_API int _zend_hash_init()メソッドの中で、こんな感じ。
ht->nTableSizeがテーブルサイズである。
uint i = 3;
while ((1U << i) < nSize) { ## 1U 符号なしの1
    i++;
}
ht->nTableSize = 1 << i; 
(一部省略している部分あり)
nSizeは、array_init より、ゼロでコールされているので、デフォルトのiの回数3回だけ、2進数0001が左へビットシフト*6され、1000(2進数)、10進数では8となる。


PHPでは、当初、この8個の枠の中で配列をやりくりするが、足りなくなると、ひとつづつ左へビットシフトする。
つまり、配列の要素を使うにしたがって、その配列の個数の上限は、

8個→16個→32個→64個→128個→256個→・・・・→1024個→・・・→21億4千7百83万3千6百48個

と段階的に増えていく。

*5 : いや、0個 $a=array(); でも

*6 : C言語での<<は、左ビットシフトの意味。<< 1は、2の1乗、<< 2は、2の二乗を表す。

  • 「配列の個数なんて増やす度に、カウント++でええやん」
という考え方もあるが、ハッシュテーブルの考え方が、
  • 「大目に個数を確保しておいて、文字列キーを上手に数値に変換して、素早く探す」
ということなのと、ビット演算は、内部でのハッシュ関数と密接に関係する*7ので、このような実装になっているのであろう。

なお、
  • PHP関数のハッシュ関数 と ハッシュテーブル は、全く違うもの
名前こそハッシュとついているが、全くの別物である。「任意の文字列から、一意のデータを出力する」というハッシュアルゴリズムの考え方は同じであるけど、ハッシュ関数と呼ばれるmd5,hsaなどは、あくまでも、任意の文字列から、文字列のハッシュ値を計算するもの。
ハッシュテーブルは、ハッシュアルゴリズムは使用するけど、md5やhsaではなくて、独自のハッシュ関数を実装し、それをさらにC言語の配列のキーとして利用する*8


また、
  • PHP関数のハッシュ関数md5,hsaなどは、最後のアウトプットは文字列
  • ハッシュテーブルで実装されるハッシュ関数*9の最後のアウトプットは、数値
という点も大きく違う。


ハッシュテーブルの構造については、またいつか別項にて記載したい。

PHP変数管理の目次はこちら

*7 : いつか別項で書きたい

*8 : C言語の配列キーは数値のみ

*9 : PHPの内部的に使われる

2008/03/15(土) PHPの配列管理方法を正しく理解する-ハッシュテーブルとZval

配列は、となりの家に行くときも、毎回毎回、近所の交番で道を尋ねる


PHPの配列の管理方法については、意外に日本語情報が少ない。
これがわかっていないと、PHPに備わる膨大な配列関数をうまく使いこなせない場面もあるのではないか。
というわけで、できる限りわかりやく説明を試みる*1
きっと目から鱗。

続きを読む

PHPの配列管理方法

続きを読む

1: kotonoha 『解説と図に出てくる zValがサンプルコードの中に出てきません。何か例をご提示頂けないでしょうか。』 (2012/03/07 11:32)

  • PHPの配列上限数-PHP変数管理 CPA-LABテクニカル spok
    ■配列の個数制限PHP*1では、配列の管理にハッシュテーブル(シンボルテーブル)を使用している。そのサイズは、実質31bitであり*2、上限は16進数で80,000,000、10進数では、21億4千7百83万3千6百48個となる。地球の人口は66億人を超え...

2008/02/23(土) issetを正しく理解する。null値とunsetの違い-PHP変数管理

nullほど人を惑わすものはないだろう。設定されてない値ってなんだ?
unsetされた変数とは違うの?
様々な疑問があろう。
ここで、明確な理解をしておきたい。(PHPの場合)

なお、ここで以下の質問に理由とともに答えられる人は読む必要のない記事です。
   ! isset ( $a )  と is_null ( $a ) 等価である。 × or ○

続きを読む

1: 通りすがり 『まず、*9にも書いてありますが、Noticeってエラーではないと思います。変な書き方だから、直しといた方がいいよってことと思って...』 (2010/02/04 16:38)

2: 通りすがり 『PHPの実装者(PHPを作る人)から見れば、nullが代入されたら、テーブルから消す実装にしても、言語的にはおかしくないのではな...』 (2010/02/04 16:40)

3: 通りすがり 『staticな場合、unsetだとstaticまで解除されます。nullだとstaticのまま?』 (2010/03/23 12:45)

4: ごんべ 『むむ、考えるのは勝手だがNoticeはエラーです。ということで、これも、しらんかっとってんちんとんしゃん!』 (2013/02/01 16:55)

5: CertaiN 『E_NOTICEの「E」は「Error」の略ですからねもちろん。』 (2013/07/05 21:11)

6: ほんじ 『NULLは不定値です。 なので、変数の示すポインタの値が0であることではありません。 C言語とかPHPというより、コンピュータ...』 (2016/09/26 19:56)

7: ほんじ 『スレ違いだけど、思い出したので。 サーバ機などに使われるECCとかRegisteredメモリは電源ON時に初期化します。 通...』 (2016/10/17 16:55)

  • [php]phpでNotice Errorの Undefined index等が多発してうざい場合はこれで解決 Kemworld::Diary
    phpでNotice Errorの Undefined index等が多発してうざい場合は(エラーレベル落とせいいというのは置いておいて)、 $a = null; という感じで変数を初期化しておくといいかもしれない。issetで条件分岐してる場合はやっか...
  • Notice:Undefined Index を回避するには エリベリンデラボ
    Notice:Undefined Index やら Notice:Undefined Vriable が多発しているのを見るととても切ない。これを回避するには変数を使う前にきちんと初期化する,もしくはis_nullで分岐してから処理をする。こちらを参考にさ...