ダメ元で探したら、Win32_Processから取れるよ、というヒントを見つけた。
Win32_Processってどう使うんだ? と悩んでいたらここにたどり着きました。
さすがにこれだけでは寂しいので、サンプルコード書いたものを続きを読むの中に置いておきます。上記サイトを参考に組ませて頂きました。
ダメ元で探したら、Win32_Processから取れるよ、というヒントを見つけた。
Win32_Processってどう使うんだ? と悩んでいたらここにたどり着きました。
さすがにこれだけでは寂しいので、サンプルコード書いたものを続きを読むの中に置いておきます。上記サイトを参考に組ませて頂きました。
ImageIO.writeというと、BufferedImageなどをpngなどに変換する場合によく用いますが、そこでIndexOutOfBoundsExceptionとかいうのがスローされていて原因がさっぱりだったので調べた結果。
まずはググってみた。「ImageIO.write IndexOutOfBoundsException」とか。
海外のフォーラムで「バグっぽいね!ImageIOに渡す第三引数をMemoryCacheImageOutputStreamで包んでやればいいよ!」とかいう記述を見た。
サンプルコード:
1 2 |
//ImageIO.write(data,"png",baos); ImageIO.write(data,"png",new MemoryCacheImageOutputStream(baos)); |
で変更して再実験、確かにExceptionは出ない。だけど望む処理ができてない。MemoryCacheImageOutputStreamに関しては探しても日本語の情報出てきそうになかったのでとりあえず気にしないことにして元に戻したりしていた。(javax.imageio.stream以下のそんなもの聞いたこともなかったので)
~(30分経過)~
アレ?Exceptionは見つからない…?
1 2 3 4 5 6 |
try{ ImageIO.write(data,"png",new MemoryCacheImageOutputStream(baos)); //}catch(Exception e){ }catch(Throwable e){ e.printStacktrace(); } |
というわけでお見事OutOfMemoryErrorさんが釣れました。
普段メモリーの事気にしないとExceptionで全部取れる気がしてしまうけど、デバッグ時には何でもひっ捕らえるようにしよう…
デッドロックが起きているかもしれない、何気なく書かれている処理がスレッドのどこかでリソースもぐもぐしてるかもしれない、と不安に思ってスレッドダンプを取得する方法探したら、別途ツール使用する方法ばかりだったのでメモ。
1 2 3 4 5 6 7 8 9 10 11 12 |
StringBuilder builder = new StringBuilder(); Map<Thread,StackTraceElement[]> traces = Thread.getAllStackTraces(); for(Thread th : traces.keySet()){ StackTraceElement[] elem = traces.get(th); builder.append("------------"); builder.append("THREAD:" + th.getClass().getName()); for(StackTraceElement e : elem){ builder.append(e.toString()); builder.append("\n"); } } System.out.println(builder.toString()); |
builderに纏めてからprintlnしてますが、デバッグフラグが立っている時にloggerに投げるなりしてあげてください。
1 2 3 4 5 6 7 8 9 10 11 |
------------THREAD:java.lang.Threadjava.lang.Thread.dumpThreads(Native Method) java.lang.Thread.getAllStackTraces(Thread.java:1619) com.gumulab.test.Startup.main(Startup.java:18) ------------THREAD:java.lang.Thread------------THREAD:java.lang.ref.Reference$ReferenceHandlerjava.lang.Object.wait(Native Method) java.lang.Object.wait(Object.java:503) java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133) ------------THREAD:java.lang.ref.Finalizer$FinalizerThreadjava.lang.Object.wait(Native Method) java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135) java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151) java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:189) ------------THREAD:java.lang.Thread |
所々スタックトレースがなぜか空になってる部分がありますが、実運用で使う訳ではないでしょうしデバッグ時だけなので見逃してあげてます。嫌な人は弾いちゃってください。
今回の変更点は以下になります。
・ユーザー詳細ページの表示を高速化(推定従来比8~10倍の速度)
コツコツアップデートを繰り返していた物がようやく実った形になります。ユーザーページへのアクセスを行う際のストレスがかなり軽減されると思います。
今後実装予定(かなり先になる可能性有)
ググっても無かったり、怪しすぎて使いにくかったりしたので面倒になって自作。
http://blog.gumu-lab.com/tool/bin.php
どこがWebページなのか聞きたくなるほど適当なUI。
もしかして:POSTパラメータで外から投げさせれば怪しげな実行ファイル仕込める?
リファラを確認しています。対策が足りないようならメールフォーム等からご一報ください。
もしかして:ファイル一回毎に作ってる?
作ってません。安心して(?)ご利用ください。ファイル名を設定する為にactionの飛ばす先を動的に書き換え、飛ばしています。ただソースから察せますが、../とかファイル名に含むと上手く動きません(ブログに飛んだりする程度、脆弱性はないはず)
2014/09/08 追記
ファイル名の末尾をhtmlにすることで自由なスクリプトを実行できてしまう問題(IEで確認)、blog.gumu-lab.comドメイン下ではあるものの、Ajaxのクロスドメインが回避できてしまう問題や、が存在したので公開停止しました。
Google ChartのTableを使っていて、このイベント取りたいのに、mouseoverとかfocusとか、ないんですか!という状況になった。jQuery環境。
マウスオーバーのイベントをなんとか捕捉する為、テーブル行へのスタイルの追加の段階でDOMの変更を監視してなんとかしました。当然ですが、かなりゴリ押しな方法なのでアップデートなどで正常に動作しなくなる可能性があります。(allowHTML:trueとするとHTMLのTableで出力されるので少し楽だった)
MutationObserverを扱う日本語の情報が少なすぎてつらかった。誰かの記事に書いてありましたが、確かにここのリンクで事足りるのかもしれませんがサンプルコードはちょっと欲しかった。
ブラウザの機能の変化は早くて嫌になりますね。
window.addEventListener(‘DOMAttrModified’,function(){})系の非推奨のサンプルコードは既に動きませんでした。(書き方が悪かっただけかもしれませんが、推奨する書き方で動いたのでそちらを使用)
GoogleChartで円グラフとテーブルを横に並べて同じデータを表示している状態。行番号を表示しておいて、それを配列のインデックスに流用しているので、それが嫌な方は何らかの(children取得して上から順に数えるとか)処理に変えてください。Tableをソートする場合のコードは後ろに分けてあります。
1 2 3 4 5 6 7 8 9 10 11 |
new MutationObserver(function(mutationRecords){ $.each(mutationRecords,function(){ if(-1 != this.target.className.indexOf("over")){ piechart1.setSelection([{row:$(this.target).children(":first").text()-1,column:null}]); //適当に処理 }else{ piechart1.setSelection([{}]); } }); }); $.each($("#table1").find('tr'),function(){ mo.observe(this,{attributes: true})}); |
1 2 3 4 |
mo_div = new MutationObserver(function(mutationRecords){ $.each($("#table1").find('tr'),function(){ mo.observe(this,{attributes: true})}); }); mo_div.observe(document.getElementById('table1'),{childList:true ,attributes: true}); |
とりあえず書いたコードはこんな感じ。ソート時にはtable作り直すのかな?テーブルをここに入れろ、とIDと指定するdivの場所で変更を拾ってると再適用できました。
jQuery書いた経験少ないので、何か変なコード見たら突込みください。
まともに誇れるような技術を何一つここに書いてないような気がするのは気のせいだろうか…。トリッキーというかその場しのぎな事ばかり投稿しているような…。
前(状況はこちらにかいてあるので省略)
で、まぁどうしてくれようかと思っていたんですが、方法を変えたらあっという間に決着がついたので追記。バックアップデータをsrctbl,入れる先をtargettblとしています。
1. srctblをCSVエンジンからMyISAMへ
ALTER TABLE srctbl ADD PRIMARY KEY(firstprimkey, … ) ENGINE MyISAM;
2.JDBCでPRIMARYKEY(複数カラム)の最初の物を列挙してArrayListに取得
SELECT * FROM srctbl GROUP BY firstprimkey
3.そのキーでWHERE句指定してINSERTを一個ずつ送り込んであげたらすぐに終わりました。
INSERT INTO targettbl (SELECT * FROM srctbl WHERE firstprimkey = ?)
恐らくmysqlクライアントにコマンド流し込む場合をそのまま続けているとかなり時間がかかっていた(一週間)ので、方法を変えたのはよかった。ALTER TABLEですが、予想外に高速でした。おおよそ3千万レコード入っていましたがすぐ(10分以内程度)に終わりました。インデックスなどをつけていない生のDBだとかなり速いのかもしれませんね、遅いイメージが先行していて試していませんでした。
かかった時間としてはこんな感じ
CSVテーブルのまま前回のスクリプトでゆっくりインサート→一週間程度(推定。下手するともっと)
MyISAMにALTER TABLEしてPRIMARY KEY付加してからJDBCでWHERE句で区切ってインサート(恐らく絞った後は2000~15000程度のカラムが存在)→約2時間
速くできる方法を探すのって大事。毎回言ってる気がしますが。
汚いコード書くからだろ、と言われると弱いですがデコンパイルすると挙動が変わるというのは結構致命的だと思ったので英文でバグ報告をせっせと書いてました。英文は載せないけどバグに遭遇したコードだけ書いておこうかと。
今回は主に深夜巡回プログラムのツイートの密集具合が軽減されます。
ユーザー視点での機能追加が少なくて申し訳ないのですが、サーバーへの負荷等を徐々に軽減していき、Webページの表示の高速化を目指しています。その為の布石としてのアップデートを行っていると認識頂ければ幸いです。