Hatena::ブログ(Diary)

hnwの日記 このページをアンテナに追加 RSSフィード

[プロフィール]
 

2014年11月22日(土) PHP 5.5.0でイースターエッグが廃止されていた このエントリーを含むブックマーク このエントリーのブックマークコメント

PHPユーザーの皆様に悲しい(?)お知らせです。PHPのオシャレ機能として有名なイースターエッグPHP 5.5.0で廃止されていました。


そもそもPHPイースターエッグって何よ?という方のために説明しておくと、PHP 5.4までは任意のPHPページのURL末尾に特定文字列をつけると下記の象の画像や作者クレジットが表示されるような謎機能がありました*1


f:id:hnw:20141122184442g:image


詳しくは「PHP Easter Egg」をご覧ください。


ところが、PHP 5.5.0からこれが廃止されています。ChangeLogにはこれをほのめかすような内容が見つかりますが、下記の一文だけでピンとくる人も少ないでしょうから、ひっそり廃止されたという印象です。


Removed legacy features:

Remove php_logo_guid(), php_egg_logo_guid(), php_real_logo_guid(), zend_logo_guid()


PHP: PHP 5 ChangeLog


このイースターエッグが廃止された真相は僕にはわかりませんが、中の人にマジメな人がいたのかもしれませんね。

*1:この機能は設定で「expose_php = off」すれば無効になります。念のため

トラックバック - http://d.hatena.ne.jp/hnw/20141122

2014年11月15日(土) HHVM 3.3.1とPHP 5.6.2の==の違いを調べてみた このエントリーを含むブックマーク このエントリーのブックマークコメント

(11/15 16:15追記)本稿で指摘している違いの1件目についてバグレポを書いたところ、すぐ直すよーとのことでした。

(11/18 17:30追記)上記修正がmasterブランチに取り込まれていることを確認しました。


PHPJITコンパイラ実装であるHHVMが最近話題ですね。本家より高速というふれこみですし、Facebookが開発・実運用している実績もあるわけですから、導入を検討されている方も多いのではないでしょうか。


とはいえ、特に商用環境に導入するとなると互換性がどこまで確保できているかも重要です。現時点でも実運用に耐える程度の互換性はあるはずですが、僕は非常に保守的な人間なので、HHVMが互換性にどこまでこだわっているのかに興味があります。


今回、==演算子に絞ってHHVMとPHPの挙動を調べてみたところ、2点の違いを見つけたので紹介します。比較にはUbuntu14.04上のprebuilt版HHVM 3.3.1と自前ビルドしたPHP 5.6.2を利用しました。


浮動小数点数と16進数値文字列の比較が浮動小数点比較されない

PHPで数値と数値文字列を==で比較した場合は数値として比較されます。HHVMでも大半の場合は同じ動作になるのですが、浮動小数点数と16進数値文字列の組み合わせに限って16進文字列が0.0として比較されるようです。


<?php
var_dump(1.0 == "0x1"); // HHVM: false, PHP: true
var_dump(0.0 == "0x1"); // HHVM: true, PHP: false

これはHHVMのバグだと思われます。==処理の分岐が複雑すぎて間違えたんでしょうか。


整数の範囲を超えた10進数値文字列浮動小数点数として数値比較される

PHPで数値文字列同士を==で比較するときは原則として数値比較されるのですが、約2年前の修正から数値比較で精度が落ちる場合には文字列比較するようになりました(参考:「PHP 5.4.4から==の挙動が一段と難しくなりました - hnwの日記」)。しかし、HHVMはこの変更に追従していないようです。


これは次のようなコードで確認できます。


<?php
var_dump("9223372036854775807"=="9223372036854775808"); // HHVM: true, PHP: false

HHVMの挙動は少し前のバージョンのPHPと同じですから、実用上はそれほど大きい問題ではないでしょう。しかし、これはPHPの全変更に追従し続けるのは無理という証拠だとも言えそうです。特にPHPの場合はChangeLogにも残らずドキュメント化もされないような細かい変更が珍しくないので、全変更を把握することさえ非現実的かもしれません。


HHVMはPHPのCソースコードをかなり利用している


僕が見つけられた違いは上記の2点だけでした。関連する仕様の複雑さを考えるとありえないくらい同じだという印象です。


この再現性の高さはHHVMの中の人が頑張った成果かもしれませんが、PHPソースコードをうまく取り込んでいるおかげもありそうです。たとえば、HHVMのhphp/runtime/base/zend-strtod.cppを見ると、PHPのZend/zend_strtod.cをベースにしているのが明らかです。ソースコードを流用してしまえば、ドキュメント化されていないような仕様であっても再現できますし、何より楽ができそうで良い手ですね。


まとめ

  • HHVMとPHPの==に違いがあるかどうか調べた
    • 2点の違いを見つけたものの、十分互換性があると言えそう
    • とはいえ、PHPの細かい修正すべてに追従できているわけでもなさそう
  • HHVMはPHPのCソースコードをかなり流用している
    • PHPとの互換性が高い理由かもしれない

y-utiy-uti 2014/11/16 17:25 二件目は、つい最近 (下記コミットで) 修正されたようです。掲示のコードは master ブランチの HHVM では PHP と同様に false になりました。
https://github.com/facebook/hhvm/commit/1fd8ceb

hnwhnw 2014/11/16 17:41 なるほど、ありがとうございます。こんなことを気にするのは僕くらいかと思ってたんですが、想像よりも最新のPHPの挙動に合わせてるんですね。

2014年11月9日(日) APCuは速いけど初期設定がイマイチだというお話 このエントリーを含むブックマーク このエントリーのブックマークコメント

ISUCON本戦で惨敗してきた皆さんこんにちは。昨日のやけ酒は最高でしたね!今日はISUCON予選のときに気づいたAPCuのイマイチな点を紹介します。


APCuというのはPHP extensionで実装されているKVS(Key Value Store)で、localhost内でのデータキャッシュに利用されます。かなり高速な上、APCの時代から考えると利用実績も十分あるため、PHPでは定番extensionの一つといえるでしょう。


ところで、APCuに大量のデータ(10万エントリ以上)を格納するとデータの取得や更新が遅くなることがあります。APCuでは格納するエントリ数の「ヒント」をあらかじめ設定値で指定するようなつくりになっているのですが、この設定があまり知られておらず、デフォルト値もかなり小さいため、遅いまま使っている環境が多いように推測しています。


APCuの設定

APCuの設定値に、「apc.entries_hint」というものがあります。これはAPCの「apc.user_entries_hint」と同じもので、APCuに格納するデータ総数の推測値を指定するものです。


apc.entries_hint


A "hint" about the number variables expected in the cache. Set to zero or omit if you're not sure. (Default: 4096)


APCu INSTALL


この「apc.entries_hint」の指定を元に、APCuがデータを格納するときに使うハッシュのスロット数が決定されます。また、このスロット数はエントリ数が増えても拡張されることはありません。同じハッシュスロットに格納されているデータはlinked listで格納されるため、データが増えれば増えるほどlinked listが長くなります。


apc.entries_hintの初期値は4096であるため、たとえばAPCuに40万エントリを格納した場合、linked list部分の長さが平均で100になってしまいます。データの参照や更新のたびにハッシュ値の計算に加えてキーの重複チェックのため100エントリ分の文字列比較が必要になるため、速度面で効率が悪くなってしまいます*1


apc.entries_hintにデータの総数を指定しておけばlinked list部分の長さが平均1になり、速度とメモリ効率の観点から理想に近づくと言えます。多少ブレても影響は軽微なので、若干小さめの値を指定するくらいのノリで良いと思います。


APCu 4.0.6までの制約

ところで、APCu 4.0.6まではapc.entries_hintにどれだけ大きい値を指定しようと、ハッシュスロット数は19457までに制限されていました*2


この制約はデータを20000個前後しか格納しない前提であれば問題ないのですが、現実にはもっと大量のデータを格納することがあるはずです。そこで、下記のようなPull Requestを投げ、より大きい設定値に対応できるようにしました。



これは無事採用され、APCu 4.0.7からはハッシュスロット数の最大値が983063になっています。


apc.entries_hintを大きくしたときのメモリ消費量

このスロット数が1増えるたびに、64bit環境では64バイトのメモリを消費します。つまり、2万スロットであれば約1.2MBのメモリを消費します。100万スロットでも約64MBです。大抵の環境では、hintを大きくするリスクは小さいと言えそうです。


もっとも、これ以外に格納するデータに対応する分のメモリも必要です。APC/APCuでは1エントリごとに管理用の構造体で960Byteを消費します。更にキーと値に対応するデータの分もメモリを消費しますので、数百万エントリを格納する前提の場合は十分なメモリを用意しておきましょう。


現在使っているエントリ数を確認する方法

APCuに付属しているapc.phpでも表示されますし、下記のようなスクリプトでも確認できます。


<?php
$ret=apc_cache_info('user', true);
var_dump($ret['nentries']); /* 現在使っているエントリ数 */

今回の話に関わらず、この数字が単調増加していないかどうか普段からモニタリングしておいた方が良いでしょう。


まとめ

  • APCuの設定値apc.entries_hintに格納エントリ数の推定値を指定すると性能が上がる
  • APCu 4.0.6以下ではapc.entries_hintに2万以上の値を指定しても無視される
    • 4.0.7から100万付近が上限になった

補足しておくと、このapc.entries_hintの修正が必須になるような環境はかなり珍しいかと思います。上にも書いた通り、多少遅くなったとしてもAPCuは十分高速なので、他のボトルネックに比べれば無視できるはずです。ただ、APCuに数百万オーダーのデータを格納している場合は試しに設定変更してみる価値があると思います。

*1:効率が悪いといっても、この程度ならlocalhostmemcachedを使うよりは高速です。同一プロセス内で処理が完結するのは速度面で有利なのです

*2ハッシュ値modを取ったときの偏りを減らすため、hintより大きい素数をリストから探すような仕組みになっています

トラックバック - http://d.hatena.ne.jp/hnw/20141109

2014年11月6日(木) PHP7で導入予定の新しいメモリマネージャをPHP5.6にバックポートした このエントリーを含むブックマーク このエントリーのブックマークコメント

現在、PHPの開発ブランチでは次期バージョンであるPHP7.0の開発が進められています。この新バージョンでは内部のリファクタリングと性能改善に重点が置かれるとみられており、言語仕様の観点ではメジャーバージョンアップの割に変化の小さいバージョンになりそうです。


ところで、このPHP7でメモリ管理まわりのコードが書き直されるのをご存じでしょうか。これはPHP7開発のキーマンの一人であるDmitry Stogovによるもので、アプリケーションによっては5%から10%の性能アップが期待できるようです。


しかし、PHP7は最速でも1年後のリリースと言われていますので、我々がこの恩恵を受ける日は随分先になってしまいます。そこで、この修正をPHP 5.6.2にバックポートしてみて、現行バージョンでも効果があるのかどうか実験してみました。


修正内容

PHP7で採用予定の新メモリマネージャは、最近の速いmalloc実装(jemallocやtcmallocなど)を参考にした実装をPHPに導入するものです*1


この修正は「New Memory Manager for PHP7 #777」で行われています。この差分PHP 5.6.2に合わせて適宜修正したものが下記パッチです。



内容をあまり理解せずにパッチを作っているので、うまく動かないことがあるかもしれません。ただ、手元で少し試した限りではマトモに動いているようです。


ベンチマークテスト

オリジナルのPHP 5.6.2(old-mm)と、新メモリマネージャを組み込んだPHP 5.6.2(new-mm)とを用意し、ベンチマークテストZend/bench.phpMacOSX 10.9上で実行してみました。結果をまとめたものが次の表になります。

続きを読む

*1:元々mallocの回数を抑制するような実装になっているのですが、何をどう改善したのかは理解していません…

トラックバック - http://d.hatena.ne.jp/hnw/20141106

2014年10月16日(木) GitHub ユーザーの ID 900万件を公開しました このエントリーを含むブックマーク このエントリーのブックマークコメント

https://github.com/hnw/github-login-idsで、GitHubユーザー/オーガナイゼーションのID約900万件を含んだCSVファイルを公開しました。


これはGitHub APIを使えば誰でも入手できる情報ですが、全部取得しようと思うと丸一日かかるので*1、公開しておくことは一定意味があるかなと考えています。


これによれば、2014/10/16現在github.comには約850万ユーザーと約40万オーガナイゼーションが作られていることがわかります。また、サービス初期には「-」から始まるログインIDが許されていたこともわかります。(例:https://github.com/-/


他に面白い使い方を思いついた方は教えてくださいませ。

*1GitHub APIは1ユーザーあたり1時間に5000リクエストまでに制限されているため

トラックバック - http://d.hatena.ne.jp/hnw/20141016
 
ページビュー
1261865