質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

2回答

1793閲覧

Simple HTML DOM Parserを使うと通信が重くなる

tanamochi

総合スコア83

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2016/09/26 07:30

編集2016/09/26 11:12

###発生している問題
Simple HTML DOM Parserを使った場合と使わなかった場合で処理速度が大きく変わっているところまでは判明したのですが、原因が判明しておりません。
ただ処理自体が重いというわけではなく処理後のレスポンスが遅いという状況です。

###該当のソースコード

PHP

1$ch = curl_init(); 2curl_setopt($ch, CURLOPT_URL, $url); 3curl_setopt($ch, CURLOPT_POSTFIELDS, $params); 4curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 5curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 6curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie); 7curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie); 8curl_setopt($ch, CURLOPT_POST, TRUE); 9curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 10curl_setopt($ch, CURLOPT_HEADER, TRUE); 11curl_setopt($ch, CURLOPT_TIMEOUT, 30); 12$html = curl_exec($ch) or die('error ' . curl_error($ch)); 13curl_close($ch); 14 15error_log("a"); 16 17$dom = new simple_html_dom(); 18$dom->load($html); // これを使うと重くなる 19 20error_log("b"); 21 22$ret = $dom->find('*****', 0); 23 24error_log("c"); 25 26return !empty($ret);

###試したこと

  • 処理前後にerror_logを仕込んで処理速度の確認(a,b,c,が表示された後もしばらくレスが返ってこない
  • php.iniのメモリ上限変更、文字コードをutf-8に変更
  • 文字列長は2万前後

###補足情報(言語/FW/ツール等のバージョンなど)
OS CentOS Linux release 7.2.1511
Apache/2.4.6
Phalcon (2.0.14)
PHP 5.6.26
MYSQL 5.5.50-MariaDB

どうぞよろしくお願いします。

#追記
返信ありがとうございます!

結果は以下になりました。

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 1 0 0 6520952 868 409280 0 0 4 1 25 51 0 0 100 0 0 0 0 0 6520828 868 409280 0 0 0 0 58 115 1 0 100 0 0 0 0 0 6520828 868 409280 0 0 0 0 39 87 0 0 100 0 0 0 0 0 6520828 868 409280 0 0 0 0 35 83 0 0 100 0 0 0 0 0 6520828 868 409280 0 0 0 0 51 102 0 0 100 0 0 0 0 0 6520828 868 409672 0 0 0 0 154 247 1 0 99 0 0 // 通信開始 0 0 0 6520828 868 409680 0 0 0 4 141 217 1 1 99 0 0 0 0 0 6520828 868 409680 0 0 0 0 77 155 0 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 72 82 157 0 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 76 140 0 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 66 126 0 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 78 156 0 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 74 136 0 1 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 63 128 0 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 62 128 0 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 66 126 1 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 70 135 0 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 76 145 0 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 65 132 0 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 69 134 0 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 69 130 0 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 72 146 0 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 63 128 0 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 62 123 0 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 68 133 0 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 63 126 0 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 61 117 1 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 51 102 0 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 47 99 0 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 41 85 0 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 36 81 0 0 100 0 0 0 0 0 6520828 868 409680 0 0 0 0 53 111 0 0 100 0 0 // 通信終了

処理の始動は携帯端末からリクエストを飛ばしてローディングの表示を行いレスポンスがあればローディングの表示を消す、という流れになっています。
この回答でずれていないでしょうか?大丈夫でしょうか?

unset($dom)も効果ありませんでした。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

popobot

2016/09/26 09:57 編集

実行中に別の端末で、vmstat 1を実行してどのOSリソースを使っているか見てみたらどうでしょうか。(追記)メモリ解放が足りない気がしてきたので、回答に記載しています。先にそっちを試してみてください...。
popobot

2016/09/26 10:01

すみません... 質問欄に貼っていただけますでしょうか
tanamochi

2016/09/26 10:03

コード表記できないんですね…
popobot

2016/09/26 10:06 編集

まったくCPUもメモリも使ってないですね...逆に謎です... これPHPが動いているサーバのですよね??
guest

回答2

0

自己解決

環境を再度構築しなおしたら解決しました。
根本の原因は判明しませんでした。

投稿2016/09/28 06:09

tanamochi

総合スコア83

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Simple HTML DOM Parserはメモリをたくさん使う上に、
循環参照している部分があるようで、使わなくなったあとでもメモリが正しく開放されない場合があります。
なので、使わなくなった後に以下を実行すると解決するかもしれません。

php

1$dom->clear(); 2unset($dom) // これはいらないかもです...

※詳しくはメモリのクリーンナップを見てください。

解決しない場合は、vmstat等でなんのリソースが足りないのか見てみないとなんとも言えません。

投稿2016/09/26 09:56

popobot

総合スコア6586

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tanamochi

2016/09/26 10:15

回答ありがとうございます。 こちらの方法では解決できずでしたm(_ _)m
popobot

2016/09/26 10:49

続きはこちらに書いていきますね... phpコードを見ると、returnはtrueかfalseのようですが、simple_html_domの処理だけをコメントアウトして、結果をtrue/false両方返すパターンを試してみた場合、どちらもレスポンスは速いのでしょうか? 自分はsimple_html_domはあまり関係ないのではないかとちょっと思っています。
popobot

2016/09/26 10:54

あと、vmstatの結果を見ると20秒近くかかっていますが、誰かがそれだけCPUも使わずに待っていたと思います。それが誰なのか切り分けたいです。 PHP側の最後の処理でログ出力してみたり、Apacheログをみてり、ブラウザのデベロッパツールでリクエストが帰ってきた時間を見て見てください。
tanamochi

2016/09/26 11:25

PHP側の最後の処理でログ出力していますが Apacheログでは表示は1、2秒で出ており 20秒ほどローディング表示のままという状況です。 simple_html_domの処理をコメントアウトした場合は2秒ほどでローディング表示は消えます。 ブラウザからは始動がネイティブコードで書かれているもののため確認までに時間がかかりそうです。
popobot

2016/09/26 11:34

もしかしたら、大量にPHPのWARNINGとかがでちゃっているのかもしれないですね。 @$dom->load($html); という感じで@を追加してみてください。そうするとPHPのWARNINGがもみ消せます。
tanamochi

2016/09/26 11:44

うーん、変わらずでした。。
popobot

2016/09/26 12:43 編集

ちなみに、ブラウザからは始動がネイティブコードで書かれているというのはどういうことですか?ネイティブコードとはなんでしょうか? PHPからのレスポンスデータそのものって見えるのでしょうか? もし見えるなら、dom->loadをコメントアウトした時とそうでない時で違うのでしょうか? 後、dom->loadをコメントアウトした時としていないときで、Apacheのログに記載されている転送サイズって同じですか?? http://web.just4fun.biz/Apache/access_log%E3%81%AE%E8%A6%8B%E6%96%B9.html
tanamochi

2016/09/27 05:25

失礼、言葉足らずでした AndroidStudioで作ったアプリからphpにアクセスしてその通信を行っているのでブラウザからの確認をする場合は新規でテスト用のコードを書く必要があるので時間がかかるという意味でした。 Apacheのログですが%bの項目はあるのですが何故か表示されていませんでした。 こちらの調査にも時間がかかりそうです。 環境を作った時に手間取っていろいろミドルウェアやFWをいれたりしたのでそのあたりに原因があるかもしれません。。
popobot

2016/09/27 05:31

なるほど...複雑ですね。 今までの状況からすると... サーバサイドはCPU等もそんなに使っておらず、Apacheも2秒でレスポンスを返しているので、特に問題はないと思っています。ただ、simple_html_domを使うとレスポンスが変わってしまい、その結果、アプリ側でレスポンスを処理するのに時間がかかっているのではないかと推測しています。 なので、レスポンスの内容がどう違うのか調べたり、アプリ側でレスポンスを処理する部分に問題がないかを調べていくしかないかと思います。
tanamochi

2016/09/27 08:31

最終的な戻り値が同じでもsimple_html_domをコメントアウトした場合とそうじゃない場合でも差が出ているのでアプリ側に問題があるというわけでもなさそうなんです。
popobot

2016/09/27 08:47

戻り値が同じでも途中でWARNINGがでたり、と何らかの想定外の出力があってレスポンスが違うんだと思うので、レスポンスを確認するのが次のステップだと思います。
popobot

2016/09/27 10:54 編集

やや思いつきなのですが、simple_html_domが何らかの影響を与えているのであれば、DomDocument + XPathを使ってHTMLを解析する方法に実装を変えてみたらどうでしょうか。変更の工数がどのぐらいかわかりませんが...。なお、実際に実装する前に、試しに、DomDocumentでHTMLをloadする処理だけ実行させてみて、同じ現象が起きないか確認するといいと思います。 $dom = new DOMDocument(); @$dom->loadHTML($html); ※もはやsimple_html_domはメンテされてないですしね...
tanamochi

2016/09/28 06:10

環境を再構築したところ問題は解決しました。 長い間お付き合いいただきありがとうございましたm(_ _)m
popobot

2016/09/28 06:20

うまくいってよかったです!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問