jQueryとメモリーリーク(prevObject)
jQueryを使って要素を追加したり消したりするときに、特に意識せず書いていたらメモリーリーク起こしちゃってたのでメモ。
たとえば以下のようなコード。
addを押したらspan要素が増えていって、next、prevで選択中の要素(赤色)が変わっていく。"remove unselected"で選択中の要素以外の要素を消す。
これで以下のような操作をするとメモリーリークする(DOMから削除された不要な要素がメモリに残り続ける)。
- add を何回か押して要素を足す
- next を何回か押して選択要素を変える
- remove unselected を押して選択要素以外を削除
原因は、jQueryでnext()やprev()などを使って(あるいは他のメソッドでもだが)要素を次々と移っていったときに、current.prevObject にその前の要素を保持しているせいである。今回はjQueryオブジェクトをプログラムの実行中ずっと保持し続けているので、そこからprevObjectを辿っていくことで消したはずの要素にもアクセスできるようになってしまっている。
以下は実際にprevObjectの中身を出力して、消したはずの要素がメモリに残っているのを確認できるようにしたもの。
"show hisotry"を押すと、それまでの移動履歴が表示され、削除された要素も残っていることが分かる。
(demoは実際に上記のメモリーリークを起こすパターンを再現するようにしたもの)
対策としては、そもそもjQueryオブジェクトを保持しておくのをやめればよい。たとえば代わりに素のDOMオブジェクトで保持したり、もしくは選択中であることを示すclassを付けるなどして代替するのがおそらく望ましい。
一応、以下のような方法で jQuery の prevObject をリセットすることもできる:
delete element.prevObject;
もしくはelement = $(element);
Herokuで実際の稼働環境に特定のファイルを含めない
Herokuで、特定のファイルを実際の稼働環境に含めたくない場合。
一つの方法はそのファイルを.gitignoreに含めることだが、この場合はそもそもそのファイルがバージョン管理下に置かれないので、「Git でバージョン管理したいが、稼働環境には含めたくない」という場合には困る。
この問題に対する一つの解決策としては、.slugignoreというファイルを作り、そこに稼働環境に含めたくないファイルを列挙する。
.slugignoreの書式は基本的には.gitignoreと同じで、ここに書かれたファイルはHerokuのslugに含まれない。すなわち、実際の稼働環境(Dyno)では.slugignoreに書かれたファイルは存在しなくなる。
ただし、push時にHerokuのサーバーへのアップロードはされる。実際、herokuからcloneなりなんなりをしてみると、.slugignoreに書いたファイルも含まれていることが分かる。
よって、たとえばサイズの大きなファイルのアップロードを防ぐ目的では使えないことになる(Slug sizeを減らすのには有効)
Android エミュレータが真っ暗
さっきの記事で Intel x86 Android Emulator をインストールする話を書いたのだが、実はこちらの環境では別の問題でこれが正常に起動しなかった(起動しても真っ暗なまま何も表示されず)。
そもそも実は x86版のエミュレータを入れる前からこの状態で、その原因が分からなかったがとりあえずx86版にすれば直るかも、と思ってx86版にしたのだが直らなかったようだ。
色々試してみて、結局エミュレータのデバイスの設定で「Use Host GPU」にチェックをつけていないことが原因だった。これにチェックを付けて起動するとすんなりと起動した。
ネット上で調べたときにはむしろ逆に、これのチェックを付けると起動しない、という事例をいくつか見ていたのだが、原因はよく分からないがうちの環境では逆だったようだ。
x86版Androidエミュレーターの導入
Android SDK に標準で付属しているエミュレータ(ARMアーキテクチャをエミュレートしている)とは別に、Intel Atom(x86) Android エミュレータというのがあって、そのほうが動作が高速だと書いてあったのでそれを入れてみた。
使用要件は CPU が Intel Virtualization Technology に対応していること。
インストール過程で結構詰まったので詰まった箇所を書いておく。
主にこのサイトを参考にした。基本的な手順は以下の通り。
- SDK Managerから、使用したいバージョンの「Intel x86 Atom System Image」と、一番下の方にある「Intel x86 Emulator Accelerator (HAXM)」をインストール。
- HAXMの方はSDK Manager上ではインストーラがダウンロードされているだけで、本当のインストールは手動で行う必要がある。SDKディレクトリ下のextras\intel\Hardware_Accelerated_Execution_Manager\IntelHaxm.exe を起動してインストール(ただしWindows8.1では、別バージョンをIntelのサイトからダウンロードする必要があるらしい。参照)
- あとは通常通りエミュレータを作成する際、CPU/ABI から Intel Atom を選ぶ。
ページによっては(3)の前にフォルダ構成を変える必要があると書いてあるところもあったのだが、それはこちらの環境ではしなくても大丈夫だった。
基本的には以上でできるはず……なのだが、こちらの環境ではHAXMのインストールのところでエラーが出て結構詰まった。出たエラーは This computer meets the requirements for HAXM, but Intel Virtualization Techonology is not turned on.please enable VT-x and re-install HAXM.please refer to the Intel HAXM documentation for more information.
というもので、この文章自体は「HAXMの要件には合致してますけどVTがONになってませんよ」と言っている。
こちらの環境では調べてみると確かにVTがDisabledになっていたので、BIOSからこれをEnabledにして再起動……したのだが、にも関わらず再び同じエラーが出た。
色々調べて、まず試したのがここに書いてある"bcdedit /set nx AlwaysOn"を実行する、というもの。が、これをやっても変わらず。(いま気付いたがこのページで質問している人のエラーメッセージは僕のエラーメッセージと少し違った)
さらに調べていると、日本語のページでそのものずばり書いてあるのがあった
原因はセキュリティソフトのavastにあるようで、avast 9の場合、 設定→トラブルシューティング→「ハードウェアによる仮想化支援機能を利用する」のチェックを外して再起動すれば、インストールできるようになります。インストール後は、設定を戻しても正常に動いています。
これに従って、avastの設定で「ハードウェアによる仮想化支援機能を利用する」のチェックを外してからPCを再起動すると、無事にHAXMがインストールできた。めでたしめでたし。
Javaパッケージ名登録サービス
Javaのパッケージ名は慣例的にドメイン名を逆順にしたものを用いるらしいのだがドメインを持っていないので、どうするか悩んでいたところ以下のサイトを見つけた。
このページから、Javaのパッケージ名を登録することができる。
登録できるパッケージ名は以下のような形式。
jp.gr.java_conf.****
登録するといってももちろん、他の誰かがわざとぶつけてくることはできるのでそういう意味ではあまり意味はないかもしれないが、それは所持ドメインを逆順に用いる場合も同じなので、そういう悪意ある人がいない限りはこれで実質的に一意的な(偶然被る心配がほとんどない)パッケージ名を取得できる。
登録するには、名前とアドレスが必要。入力したアドレスに認証確認メールが送られる。
メールアドレスと名前は上記ページから誰でも見られる状態になるので注意(HNで登録している人も多いようだ)。
また登録内容変更は一見誰でも可能に見えるが、実際はちゃんと登録したメールアドレス宛てに確認メールが送られるよう。(メールアドレス変更時は旧アドレスと新アドレスそれぞれに届く確認メールが両方必要)