新しく作った開発ツールに、ソケット使用の簡易デバッガを組み込もうとしたのですが、チョットその前に欲を出してしまいました。
こんなマルチドキュメントのテキストエディタにしたのですが、左のツリーピューをWindowsのエクスプローラーと同じ感じのファイル階層表示にしました。

イメージ 1


そんならついでだからプログラミング関係のファイルを全部ここに表示して、全文検索していつでも必要な情報を取り出せるようにしよう!!と考えました。

現在、開発関係は64GBのUSBメモリーにまとめて積んでいます。
JDKもRubyやJavaScriptも、ダウンロードしたフリーのユーティリティなんかも、自分で書いたプログラムも、書き貯めたサンプルコードも全てこの中に入っています。
基本的に殆どがテキストファイルなので容量はあまり食わず、全て合わせても4GBもありません。

Windowsが64bitになってから、Javaのプログラムもギガバイト単位のデータを扱えるようになりました。

今までは下の画像のようなビュワーを作って、キーワードやカテゴリでサンプルプログラムを検索して、必要な処理のコードを探しては、コピペで開発中のプログラムに貼り込んで使えるようにしていました。
イメージ 2

これは簡易な全文検索ソフトで、起動時に全ファイルを読み通して形態素解析(単語をバラバラに分ける事)を行い、どの単語がどのファイルに含まれているかインデックスを作るものです。
全ての単語に対して、予めその単語を含むファイルのリストを作っておくのです。
事前に全ての検索を済ましておく、と言っても良いでしょう。
実際に「ウィンドウ 作り方」などと入れて検索する時には、既に「ウィンドウ」と言う単語は何処のファイルに含まれている、「作り方」はどのファイルにある、と言う事が分かっていますから、一瞬で検索して(したふりをして)ファイルのリストを表示します。
ツリー表示されたリストの中から、良さそうなものをクリックすると、そのファイルが開かれて下のエディタ部分に表示されます。
そのまま、その場で実行してみたり、書き加えたりも出来ます。

私は覚える事が苦手で、言語の文法やライブラリの使い方を暗記できないので、チョコチョコ調べながらでないとプログラムが書けません。
ですから、これにはとても重宝しています。

欠点は、形態素解析を行ったり、インデックスやハッシュテーブルを作ったりするので、プログラムが複雑になってしまう事です。
一旦作って、そのまま使い続けるぶんには良いのですが、改造したり機能追加したり他所で流用したりしようとすると、とても面倒です。

そこで今回はJavaがGB単位の広いメモリ空間を扱えるようになったので、サンプルのファイルを全部メモリに読み込んで、オンメモリで検索してみることにしました。
サンプルプログラムは全部で45MB程度なので、自作プログラムやオープンソースアプリのコードなどを合わせても
2GBあればお釣りが来ると読んでいました。

デスクトップPCは32ビットのWindows7なので、Javaは1.5GBくらいのメモリ空間しか使えません。
後から買ったノートPC の方が64bitで、8GBの実装メモリを持っています。
64bitならJava自体には制限はないので、実装メモリからOSや常駐タスクが使っている分を引いた残りに近いものが使えそうです。

イメージ 3

タスクマネージャで見てみると、利用可能メモリは4676MB(約4.5GB)となっていました。
8GB積んでいて、何もしてなくても、OSやセキュリティソフト等の常駐プログラムが食っているので丸々は使えませんね。
当面はこれでも足りるはずですし、近い将来64MBくらいのメモリを積んだマシンを購入するツモリで、試作してみる事にしました。

サッと1800件のサンプルプログラムをツリー型のリンクリストに読み込むプログラムを書いて、実行してみると・・・

Exception in thread "Thread-8" java.lang.OutOfMemoryError: Java heap space
Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space

早速出ました。「JavaVMのヒープメモリが足らんでぇ~」と言っています。
いくらなんでも空きメモリが4.5GBもあって、60MB(0.06GB)程度のファイルを読み込んでメモリ不足はオカシイです。
しかもファイルは半分くらい読んだところでフリーズしているので、せいぜい0.03GBくらいしか使っていないはずです。
JavaVMの状態を監視するユーティリティのJConsoleを立ち上げてJavaVMの状態をチェックしてみると、思った通り0.03GBくらいしか使っていません。
イメージ 4

なのに「メモリが足らんでぇ~」と言っています。
まるでザルみたいに金を使うドラ息子が競馬とキャバクラで豪遊している状態みたいです。
与えても与えても「足らんでぇ~」です。

私はもともと仕事ではJavaではなくC言語やC++をばかり使っていたので、チョット勘違いしていました。
C言語では、メモリは欲しい分だけその都度プログラム中に「ここでこんだけチョウダイ!!」と書いて確保します。
要らなくなったら「もうええでぇ」と書いて破棄します。
ファイルを読み込んだら読み込んだ分ずつ取っていきます。
実装メモリが足りなくなったらOSがディスクにスワップしてくれるので、性能は落ちますが、少々オーバーしても取れます。

Windows95の頃のPCで実装メモリがせいぜい128MBくらいのマシンでも、メインフレームから5万~10万件くらいのデータベースのレコードを3セットくらいダウンロードして、全件オンメモリのハッシュテーブルに読み込んだら、カリカリとディスクスワップの音を立てながらもちゃんと動いていました。

しかし、JavaはC++の様に直接ベタにメモリーを確保するのではない事をあらためて思い知らされました。
これがチョ~メンドクサイんです。

JavaVMはJavaの実行部隊です、Java言語で書いたプログラムはコイツが読み取って実行します。
極端に大雑把な言い方をすれば、Excelでマクロを実行させるようなモンです。
と言う事は、段取りとしては先ずJavaVMが仕事をする場所を用意しておかなければなりません。
それがヒープメモリで、JavaVMを起動する時にサイズを指定できます。


利用可能メモリは4676MBとなっていましたので、取り敢えず起動時に1600MBを指定しました。すると・・

Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

「メモリが取れん!!起動できん!!」と言ってきます。
値切られたので、1500MBに値下げして指定すると起動出来ました。
どうもJavaVMが32bitバージョンでこの辺りがいっぱいいっぱいみたいです。

そんならC++のように1500MB全部使えるかというと、これがまたそうは行かないのです。
まるで15万円の給料から、所得税やら市民税やらナンやらカンやら引かれて、手取りは12万チョツトみたいな話です。

JavaVMには私の代わりにメモリ管理を全部やってくれるガベージコレクションと言う仕掛けがあります。
コイツのお陰でプログラマはチャッチャ、チャッチャと、メモリを湯水のように使って、使ったものはトッ散らかして放り投げても大丈夫なのです。(何やっても大丈夫なワケではありませんが)
C++だとキチンと使い終わったメモリエリアは開放しないと、最悪パソコン全体がハングアップを起こす可能性があって、長時間動き続けるシステムを組むと、プログラマはメモリーリークが心配で眠れなくなったり、悪い夢を見てうなされたりします。
JavaVMはそんな事にならない様に、プログラマの福利厚生の為に?メモリー管理をしてくれますが、キッチリ手数料を取られるわけです。

中の仕掛けを細かく説明するとアタマが痛くなりますが、JavaVMは割り当てられたヒープメモリを、いくつかの領域に分けて、データをアッチにやったりコッチにやったりしながら、使い終わってゴミになったメモリエリアを掃除します。
丁度、卵を割って半分の殻からもう一方に黄身をイリクリしながら白身を落として黄身だけにする調理テクニック?に似ています。
イリクリしなからゴミを除いて行って、残った黄身を最終的な「容器」に保持します。
そのせいで100のメモリを割り当てられても、いくつかの「容器」に分けて使うのでいっぺんに使えるのは20づつとか、30づつとかになってしまうようです。

はじめは一気に1800件のファイルを読み込んだので、メモリのイリクリが間に合わなくなってアップアップになったのだと思いました。
しかし、それにしても1.5GBで0.03GB使ってアップアップはヘンです。

100件づつ読み込むボタンを付けて、JConsoleで監視しながら徐々に読み込み、100Mくらい使ったところで強制的にガベージコレクションを実行して見るとヒープの使用量は20M程度に下がります、
イメージ 5

にもかかわらず700件くらいのところで、酸欠の金魚みたいにアップアップして「もうアカン・・」になって、プッカァ~ッとお腹を上にして浮き上がってしまいます。

何が起こっているのやら、見当もつきません。

ヒープの割り当てを変えたり、読み込みのタイミングを変えたり、ガベージコレクションの回数を変えたり、色々試しても上手く行きません。
2日ほどああでもないこうでもないと、いじりまわしていましたが、何かの拍子にプログラムからのコメント文をチェックしてみたら、標準出力(ドス窓)に異常に大量なコメントが出力されているのを発見しました。

Javaのプログラムの中で、  Sytstem.out.println("なんチャラかんチャラ!!" + num); などと書いておくと、num と言う変数の値をコマンドプロンプトに表示してくれます。
numの値が15なら、

なんチャラかんチャラ!!15

とドス窓の真っ黒けの画面に出てきます。

プログラムの中の動きを確かめるために使うのですが、エディタでプログラムを書いて実行させて、ドス窓とエディタのウィンドウを行ったり来たりするのがメンドクサイので、標準出力のデータをドス窓に出る前に横取りして貯め込んでおいて、テスト中のプログラムが終了した時にエディタのメッセージエリアに表示するように仕組んでいました。

それを忘れて、標準出力はWindowsの仕事だからJavaVMのヒープには関係ないと勘違いしていました。
しかもメモリ不足でテスト中のプログラムがハングアップした時に、エディタの方も一緒に強制終了させて立ち上げ直していたので、エディタ画面上に大量に流れていたコメントに気づきませんてした。

どうやらヒープ内の新しいデータを最初に受け取るEden領域というところに短時間にゴッソリとコメントデータが溜まって、それでメモリー不足が起こっていたようです。

コメント文の出力をやめたらウソのように解消して、当面の1800件のサンプルコードは無事読み込めるようになりました。

メモリー上に読み込んでしまえばコッチのもので、ファイルの中身をString(文字列)型データの配列やリストとして保持しておけば、

 String#indexOf("word" );

とするだけで、そのファイルに"word"と言う単語が含まれていれば、その位置を返してきます。
含まれていなければ、「無いょぉ~」と言ってnull(何にも無いというような意味)を返してきますから、それだけで全文検索が出来上がります。


これはファイル読み込み/全文検索機能のところだけを別のウィンドウに組み込んでテストしたものです。
イメージ 6

左側がテスト中のウィンドウです。右側はJConsoleのメモリ管理画面です。
1800件のサンプルコードを読み込んで、"JFrame"、"JTree"、"String"と言う単語を含むファイルを検索しました。
検索結果は右側のツリーに入ります。
正常に機能しました。1800のファイルからそれぞれ300~800くらいのファイルを一瞬で見つけ出してきました。
検索後のメモリ使用量は320MBくらいでしたが、これでEden領域はいっぱいだったようで、直後に自動でガベージコレクションがかかって160MBくらいに下がりました。その後、手動でガベージコレクションをかけたら更に下がって107MBまで減少しました。

最近のパソコンは64GB搭載のマシンも15万円前後で出ていますので、半分の32GBをJavaVMに割り付ければ、32MB = 32768MBで、約300倍のメモリエリアが使えて、1800件で107MBですから、単純計算すれば54万件のファイルを読み込めるようになります。
数年後には512GBのマシンも一般的になるでしょうから、300GBを割りつけて更に100倍の540万件のファイルをメモリーに読み込めるようになるかも知れません。
これだけ読み込めれば、私が仕事と私生活で使う全てのデータが入ってしまいそうです。300GBは約1600億文字です。
新聞の1ページが約12000文字ですから、1300万ページ分くらいあります。

プログラミング技術で検索などの処理を高速化する事は可能ですが、私などのような副業プログラマや現場サイドで実業務に携わりながら自社の業務システムを構築/改善する場合は、ややこしい事や複雑でテクニカルな事をやっていると、コンピュータの世話だけで日が暮れてしまいます。
ハードに投資する事で、システムをシンプルで扱いやすいものに出来るなら、それに越したことはないでしょう。


こうして目出度くサンプルコードの全文検索機能がデッチ上げられ、明るい未来が垣間見れて来ました。
変なトラブル(自分が原因なんですが・・・)が無けれは30分くらいでチョイチョイッと出来る事が、とんでもない大捕り物になってしまいましたが、システムの一番大元の基盤部分の仕掛けが動いたのでチョット良い気分です。