PHPExcelが遅い場合


ネタバレ:犯人は ヤス xdebug。

PHPExcelというPHPライブラリがありまして、PHPでシンプルなExcelを生成するのに便利なので、何かと利用しているわけです。

#「シンプルな」というのはどういうことかと言うと、 #既存のExcelファイルを開いて操作することも可能ではあるのですが#いわゆる「Excel方眼紙」や、図表が入っている場合には、ほぼ再現できないためです。

さて、このPHPExcel、「遅い」ともっぱらの評判です。

しかし。

手元の環境で、 ・6×50行 ・150シート というデータで生成しているのですが、これが10分以上かかる(!)というのは、さすがに何かおかしいと思うわけです。

検索した結果、高速化させる方法としていくつか上げられている答えが: ・シートをコピーしないようにする ・罫線を1セルづつ引かない(まとめて引く) ・ループが終わったらメモリを開放する はい。やってみました。 細かいことは省きますが、最終的に30秒くらい早くなりました。 ……30秒に、ならよかったんですが。

さてではもう少しスコープを広げて検索してみます。 どうやらPHPExcelで最も多い質問は、メモリフルエラーのようですね。

というわけで memory_get_usage() と microtime() を入れてトレースしてみたのですが、 microtime() どころか time() で間に合うくらいまんべんなく時間がかかっています。 メモリの使用量は、さほど猛烈な量というわけでもありません。 しかし、topコマンドを走らせながら結果を見て見ると、CPU使用率が振り切っています。 普通に考えるとこれは、 ・計算量がめちゃめちゃすごい ・何かファイルI/Oがすごい ということだろうと推測できます。

計算量がすごいことになってるというのであればまたこれはしょうがないんですが、 まんべんなく時間がかかってるのはちょっと納得がいかないわけです。 納得はいかないものの、時間がなかったのでここでいったん放置しました。

・・・・・・

さて、2週間ほど後、全く関係ない謎事態が発生しました。 いつのまにか、HDの残り容量が全然無いのです。 とりあえずduコマンドで原因を探すと、/var/tmp/にcachegrind.out.*というファイルが150GB分存在しています。 cachegrind.out.*とはなんぞ、と検索してみると、これはxdebugが生成しているということです。 じゃー消していいや。わーい150GB空いたよー。

……xdebugが……生成する?……ファイルI/O……?

ということでしょうもない茶番をはさみましたが、xdebugがcachegrind.out.*を書いてるのが原因じゃないか?ということで、xdebugをOffにしてみることにしました。

で、そもそもなんでxdebugが入っているかというと、phpunitを入れているから(phpunitのコードカバレッジ機能に必須)で、PHPExcel走らせる時だけOffにできないのかなと思ったのですが、これもあれこれ試してみた結果、今回関連している個所はiniに書かないと効果が無いようなので、とりあえず、 xdebug.profiler_enable=0 にしておきます。

結果、あの10分かかっていたPHPExcelでのファイル生成が、なんと、 80秒 で終わるようになりました。 10分間、動いてたのはほとんどxdebugだったということになるわけですなー……

#その後、「遅いなー」と思っていた処理がことごとく速くなりました

最新記事

すべて表示

小ネタです。 SQLiteを使っていて "no such table" とエラーが出た場合、 DBファイル名の指定が空になっている、という凡ミスを起こしていないかを確認してみましょう。 ・・・ そういう凡ミスをしてしばし悩んだので… ファイル名の指定が空になっている場合、一時的なインメモリDBとして保存されます(※1)。 つまりDB接続を切断すると中身は消えます。 なので接続

最近、 Goで書かれたアプリケーションサーバが起動しない! ->原因: .env ファイルが欠けていた というドタバタがありました。 結局Goと関係ないですが、この時、 「あまりGoに慣れてないのでGoの問題かと…」「DockerまだよくわかってなくてDockerの問題かと…」 というような声があったのて、あえてGoで検証してみようと思ったわけです。 さて、Goでサーバサイドのシステムを作

弊社ではかなり前からGitLab(CE)を自社環境で運用しているのですが、ふと気付くと、バージョンがだいぶ先に行ってしまっていました。 とくに最近のバージョンでは Auto DevOps なども使えるようになっていたりするので、さすがにそろそろキャッチアップしたいと考えたわけです。 現行の環境は次の通りです: GitLab 9.1.2 sameersbn/gitlab 使用 MySQL 5.6