今回はクリーナーです。クリーナーをご存知ですか?掃除機ではありませんよ?まぁそれに近いですが…。
今回のスクリーンショットです。

物理メモリの空きが不足してくると様々な不都合が生じてきます。
クリーナーはこの物理メモリ上のフラグメントを解消(コンパクション)し、
メモリ不足によりシステムが不安定になるのを防ぐ為のソフトです。
重要でないメモリだけ退避させることはできませんので実効的な効果は得られにくいですが、
HSPでやるには1番簡単なスワッピング方式で作成します。
早速取り掛かっていきたいと思いますが、メモリ量を知るには標準命令ではできないのでDLLを使用します。
さくらさんのsrexhsp.dll、forceさんのexforce.dll、その他いろいろなDLLで知ることができますが、
標準付属のhspext.dllでもいけますのでこの講座ではhspext.dllを使ってクリーナーを作成していきます。
HSP2.6からsysinfo命令が標準命令となりましたので2.6以上をお使いの場合はDLLを使用しなくて結構です。
#include "hspext.as" sysinfo all,34 sysinfo mem,35 mes "全体:"+all+"BYTE" mes "空き:"+mem+"BYTE" stop
これでアナタが使用しているパソコンの物理メモリ量を知ることができます。
バイト単位では見にくいと言う場合は、出てきた数値を1024で割ればKB単位になりますね。
元の数値から1048576(1024×1024)で割ればMB単位になります、念のため。
上記のスクリプトをループさせればメモリ監視ソフトの完成ですね(^-^)。
今回はクリーナーと言うことで空きメモリを確保しなければなりません。
入門講座でやりましたね、dim、sdim、(alloc)でHSP用にメモリを確保することができます。
#include "hspext.as" gosub *memory sdim buf,1048576 ; 1MBメモリを確保する gosub *memory sdim buf,1 ; 1MB→1B gosub *memory stop *memory sysinfo all,34 sysinfo mem,35 mes "全体:"+all+"BYTE / 空き:"+mem+"BYTE" return
上記サンプルを試すと確保して解放するまでの様子を知ることができますね。
1MBを確保した後、1バイトにサイズを縮小すれば(約)1MBメモリに空きができます。
元々メモリに1MB以上空きがあった場合は、余っているところから使ってまた返す、と言うことになり、
実質空きメモリは増えていません。
しかし例えば空きが100KBしかなかったとして、1MB確保するとどうなるのでしょう???
Windowsは仕方なしに元々メモリ上にあったデータをHDDに退避(スワップ)させHSP用に1MB確保するのです。
そしてこの確保した分を縮小すると、その部分に空きができると言うわけですね。
最近のパソコンは大容量メモリを積んでますので空きが何10MBとあることでしょう。
スワッピングでメモリを確保するにはそれ以上の量を確保しないと無意味です。
#include "hspext.as" gosub *memory size=mem+1*1048576 ; 現在の空きメモリ+1MB sdim buf,size gosub *memory sdim buf,1 gosub *memory stop *memory sysinfo all,34 sysinfo mem,35 all=all/1048576 mem=mem/1048576 mes "全体:"+all+"MB / 空き:"+mem+"MB" return
十分なサイズが残っていると、うまく確保できない場合もあります。
スクリプトを実行すると2行目に「空き:0MB」となりますよね?
ここでメモリ上に合ったデータをHDDにスワッピングさせて不足分を補います。
そして解放すると、スワップ前の空きメモリ+1MBになります。
この解放するサイズをユーザーに決定させたり、一定間隔でスワップさせたりすればクリーナーの完成です。
#include"hspext.as" screen 0,200,85 title "脱講座2章サンプル" objsize 145,25 pos 5,55 : input size,40,25,3 pos 50,55 : button "クリーン",clean gosub *allmemory *main gosub *memory wait 1 goto *main *allmemory ; 全体メモリ sysinfo all,34 all.1=all/104857/10 all.2=all/104857\10 return *memory ; 空きメモリ取得&表示 sysinfo mem,35 if mem=mem.3 : return redraw 0 color 50,,50 : boxf : color 255,255 mem.3=mem mem.1=mem/104857/10 mem.2=mem/104857\10 pos 15, 5 : mes "全体メモリ:"+all.1+"."+all.2+"MB" pos 15,30 : mes "空きメモリ:"+mem.1+"."+mem.2+"MB" redraw return *clean ; クリーン部分 all.3=all/2097152 ; 全体メモリの50%値が入ります if size>all.3 : dialog "設定した値が大きすぎます\n"+all.3+"MB以下にしてください" : goto *main sdim clr,size*1048576 wait 10 sdim clr,1 goto *main
全体のメモリサイズはコロコロ変わるものではありませんね?初めに一度だけ取得しておきます。
「all.1=all/104857/10」というのは、MB単位に直しただけではちょっと寂しい表示になりますので、
少数第1位までを求めるやり方です。
例えば128MBの場合、all/104857で「1280」と出てきます。それの10分の1ですので「128」です。
「all.2=all/104857\10」の部分で先ほどの「1280」の「0」が出てきます。
コレを表示の部分で「mes ""+all.1+"."+all.2+"MB"」とすることで「128.0MB」と表示されるわけです。
前章同様空きメモリ表示の部分でトラップを設けています。
前回に取得した時と同じメモリサイズなら表示を書き換える必要はありませんので。
mem.3に前回取得したサイズが入り、前回と変わっていればmem.3に今回取得したサイズを代入します。
クリーン部分では「all.3=all/2097152」てなことをしていますね。
これは次の行のリミッターに使用されています。
inputで全体メモリの50%以上の値を入れたときはクリーンできないようにしています。
メモリを積んでいる量は様々ですので、32MBに120MB確保、なんてすると良くありませんよね?
実際スワップさせると、その分次回の処理が遅くなるだけですから
特に必要なメモリを開放してしまうと動作が軽くなるどころか重たくなってしまいます。
必要量以上のクリーンは返って効率の悪いもの(本末転倒)となってしまいますので
空きメモリは多ければよいと言う勘違いをしないでください。
以上で解説を終えます。
ココでも一応スクリプトを。コチラです。