偉大な先輩の送別会

abdev 偉大な先輩の送別会 はコメントを受け付けていません
元バイト先でお世話になったジョニー先輩がついに転勤になりました(昇格ってことで、めでたい出来事です)。

2006-09-14.jpg

服屋はもう10ヶ月前にやめていたのですが、これは私も知らんぷりはできないっ。ということでジョニー先輩の好物である芋焼酎を片手に送別会に参加してきました。

 

それにしてもこの飲み会、今までやった中で一番の盛り上がりを見せました。会の中盤で県外へ転勤になってしまった元店長(ジョニー先輩とかなり仲良い)がスペシャルゲストで登場し、会場は大盛り上がり。毎回のことながら、演出すごすぎ。。。

 

写真は二次会の様子なのですが、ライブ会場と化しています。

 

こんな場に参加できる自分は本当に幸せだと感じた日でした。この連中とは長い付き合いになりそうです。

 

この会は明け方の四時まで続いたので、今日はちょっとテンションが低めですf(–;;;

Virtual PCでWebサーバー

abdev 2 Comments »

ソフトウェアの動作検証にしか利用していないVirtual PC。何か面白いことできないかな〜ということで、ちょっといつもとは違った方向でアプローチをかけてみます。

先日ダウンロードしたFedora Core 5をVirtual PC上の仮想マシンにインストールし、そこでWWW/FTPサーバーでも立ててみることにしました。ウチのネット環境は最新設備ではないので本格的に何かをすることはできませんが、将来的に様々なサーバーサービスを自宅に待機させ、いつでも利用できる環境を構築しておきたいな〜なんて考えています。ま、最終的にメンテが面倒になって「レンタルが一番だ!」とか言わなきゃいいのですが・・・

それにしても、Virtual PCを用いたネットワーク構築はかなりお手軽で驚きました。パケットの流れがホストOS→ゲストOSという風にながれ、IPアドレスの振り分けも複雑になるものだとばかり思っていたんです。しかしその考えは間違っていて、仮想マシン一つ一つにローカルIPが振り分けられると同時に、ハード的に全く別物としてネットワーク上に存在させられることが判明。特別必要になる設定などはありませんでした。

もともと、Virtual PCは窓の杜の64ビットソフトウェアコンテストの賞品でいただいたのですが、かなりの頻度で活用させてもらっています。ありがたいものです。

っつか、Virtual PCって無償化の方向でコトが進んでいるのですねf(–;;;

こいつの正体って一体!?

abdev 4 Comments »

ネットサーフィンしていると、時々右のようなペラッとめくれるようなイメージがでてきます。中には “Special Offer” とか書いてあります。

クリックすると海外の出会い系のようなサイトに繋がるようなのですが、これが全く関係のないサイト(明らかにHTMLコード中に含まれていない)で表示されるので困りものです。

IE側、はたまたサーバー側の問題なのか・・・

情報求む・・・

2006-09-11

abdev 2006-09-11 はコメントを受け付けていません

Fedora Core 5のディストリビューションをダウンロードしているのですが、2GB以上のファイルのダウンロード時、IEのダウンローダ ダイアログの表示がバグりますね。32ビット符号あり整数でファイルサイズを管理していることから生じる問題でしょうか・・・

海外ケータイ

abdev 23 Comments »

友達がNOKIAのケータイ買ったとのことで、見せてもらいました。

USB、Bluetoothが魅力です。Real PlayerがプリインストールされているところなんかもPCを彷彿とさせます。

今後のケータイ機種変は海外メーカーのチョイスも悪くないかも!?

NOKIA – FOMA NM850iG:

http://www.nokia.co.jp/phones/nm850ig/index.shtml

CP2のバグ修正

abdev CP2のバグ修正 はコメントを受け付けていません

Stringクラスへの移行、GCの実態調査など、やりたいことに一通り目を通せたので、今日は一旦、CP2リリースで出たフィードバックを元にバグ修正を行いました。

本日のBGMはカントリーミュージック。デバッグ作業もストレスなく進みました。

LuckySevenRadio – Country Hits

http://www.luckysevenradio.com/listen/country_hi.asx

ガベコレ調査報告

abdev ガベコレ調査報告 はコメントを受け付けていません

さてさて、今回もABでどのようなGCを採用するのがよいかという話題で突き進みます。まずは私なりに考えるGCへの要望をまとめたいと思います。

  1. 解放のタイミングの一切をシステムに任せる。
  2. GCシステムにより確保されたメモリへのアクセス違反は原則として起こらない。
  3. 従来のmalloc/free、new/deleteと仲良く使い分けることが出来る。
  4. 安定した処理速度を有するアプリケーションを除き、ストレスのないGC処理を行う。
  5. 他言語間のやり取りで問題が起きないようにする。

これらの要素を順に解説していきましょう。

まず、解放のタイミングを気にしなくて良いという点ですが、これこそがGCであることのメリットであり、大きな特徴です。生産性の向上、デバッグに費やす時間の軽減が期待できることでしょう。

2つ目、GCで管理されるメモリ領域の信頼性の問題ですが、これもGCそのものの特徴といっても過言ではありません。しかし、実は3番目の要素と関連性がありそうな予感…。

お感じになった方もいらっしゃるとは思いますが、GCを採用する言語って、基本的にはfreeやdeleteとは無縁です(JavaやC#にはdeleteがありません)。中には、「無理やり行わないように」と注意書きがあるものも・・・。

実は、GCの構造上、GCが管理しないメモリ空間ほど怖いものはないのです。例えば、GCで確保したポインタ値をファイルに書き込み、後々アクセスするなどの処理はアウトです。つまりはファイル内のデータはGCシステムとは無縁であり、GC発動時に不要なメモリとして扱われる可能性が高いからです。このように、GCは自身が管理するもの以外の場所へ管理すべきポインタが格納されるとお手上げ状態になります(セーフティ機能が言語に求められる場面といってもよいでしょう)。

そうなると、3番目に挙げる要素を完全に達成するのは、ネイティブコンパイラであるABにとっとは、ちょっと厳しいのかもしれません。この問題に大しては、間違いにくいコーディング作法を推進していくなどの策をとり、対処を行っていく必要がありそうです。

4番目は処理速度とGC発動のタイミングの問題です。mark&sweepをベースにGCを構築すると、GC発動に対して一定期間のアプリケーションの停止が余儀なく行われることになります。この問題は、コピーGCや世代別GCなどでの対処が伺えますが、スループットの低下や、なによりも私がGCの本質を十分に理解していく必要があるため、完成物を作り出すには相応の時間がかかります。まぁ、コマ落ちが致命的になるようなゲームシステムなどは、GCをオフにした状態でメモリ管理を行ってもらう(少なくともメインループだけでも)という方向性で、当面の間は大丈夫だと捉えるより他ありませんね。

5番目の問題も後々に厄介になりそうです。「GCはここまで管理していますよ」ということを明確にしていかなければ、誰がどのタイミングで各メモリを解放するのかが明確になりません。完璧なOS、言語環境があるとすれば、メモリ管理のすべてがGCによって行われ、例外のケースが発生しないということ。これにつきます。

まぁ、そうはいっても無理難題もあるわけでして、GCとは今後うまい付き合い方をしていきたいと思っています。GCを作る側は山済みになった問題を地道に回避していくだけの根気強さ、発想の転換ができなければならないですね。

早速、GCの実装サンプルをコーディング

abdev 早速、GCの実装サンプルをコーディング はコメントを受け付けていません

調べ物をするだけではわからないので、早速、動くものを作ってみました(下記コードを参照のこと)。

/*
※これらの変数はコンパイラが自動的に定義します。
Dim _System_gc_GlobalRoot_StartPtr As VoidPtr
Dim _System_gc_GlobalRoot_Size As Long
Dim _System_gc_StackRoot_StartPtr As VoidPtr
 */

Function _System_GetSp() As LONG_PTR                    'dummy
End Function


Class _System_CGarbageCollection
    ppPtr As **VoidPtr
    pSize As *Long
    pbAtomic As *Byte
    n As Long
Public
    Sub _System_CGarbageCollection()
        ppPtr=malloc(1)
        pSize=malloc(1)
        pbAtomic=malloc(1)
        n=0
    End Sub
    Sub ~_System_CGarbageCollection()
        Dim i As Long
        For i=0 To ELM(n)
            If ppPtr[i] Then free(ppPtr[i])
        Next
        free(ppPtr)

        free(pSize)
        free(pbAtomic)
    End Sub

    Sub add(new_ptr As VoidPtr, size As Long,fAtomic As Byte)
        Dim i As Long
        For i=0 To ELM(n)
            If ppPtr[i]=0 Then
                ppPtr[i]=new_ptr
                pSize[i]=size
                pbAtomic[i]=fAtomic
                Exit Sub
            End If
        Next

        ppPtr=realloc(ppPtr,(n+1)*SizeOf(VoidPtr))
        ppPtr[n]=new_ptr

        pSize=realloc(pSize,(n+1)*SizeOf(Long))
        pSize[n]=size

        pbAtomic=realloc(pbAtomic,(n+1)*SizeOf(Byte))
        pbAtomic[n]=fAtomic

        n++
    End Sub

    Function __malloc(size As Long,fAtomic As Byte) As VoidPtr
        Dim pTemp As VoidPtr
        pTemp=malloc(size)
        add(pTemp,size,fAtomic)
        Return pTemp
    End Function

    Sub sweep()
        pbMark=calloc(n*SizeOf(Byte))

        'グローバル領域をルートに指定してスキャン
        scan(_System_gc_GlobalRoot_StartPtr,_System_gc_GlobalRoot_Size)

        'ローカル領域をルートに指定してスキャン
        Dim NowSp As LONG_PTR
        NowSp=_System_GetSp()
        scan(_System_gc_StackRoot_StartPtr,(_System_gc_StackRoot_StartPtr As LONG_PTR)-NowSp)

        '使われていないメモリを解放する
        Dim i As Long
        For i=0 To ELM(n)
            If pbMark[i]=0 and ppPtr[i]<>0 Then
                free(ppPtr[i])
                ppPtr[i]=0
                pSize[i]=0
            End If
        Next

        free(pbMark)
    End Sub


Private

    pbMark As *Byte

    Function HitTest(pSample As VoidPtr) As Long
        Dim i As Long
        For i=0 To ELM(n)
            If (ppPtr[i] As LONG_PTR)<=(pSample As LONG_PTR) and (pSample As LONG_PTR)<((ppPtr[i] As LONG_PTR)+pSize[i]) Then
                Return i
            End If
        Next
        Return -1
    End Function

    Sub scan(pStartPtr As *LONG_PTR, size As Long)
        Dim i As Long, count As Long, index As Long
        count=size/SizeOf(LONG_PTR)
        For i=0 To ELM(count)
            index=HitTest(pStartPtr[i])
            If index<>-1 Then
                If pbMark[index]=0 Then
                    pbMark[index]=1

                    If pbAtomic[index]=0 Then
                        'ヒープ領域がポインタ値を含む可能性があるとき
                        scan(ppPtr[index],pSize[index])
                    End If
                End If
            End If
        Next
    End Sub
End Class
Dim _System_GC As _System_CGarbageCollection



Function GC_malloc(size As Long) As VoidPtr
    ' sweep
    _System_GC.sweep()

    'allocate
    Return _System_GC.__malloc(size,0)
End Function

Function GC_malloc_atomic(size As Long) As VoidPtr
    ' sweep
    _System_GC.sweep()

    'allocate
    Return _System_GC.__malloc(size,1)
End Function

ちなみに、このコードはAB4やAB5CP2では動作しませんので、あしからず。飽くまでもコンパイラを拡張した形での提供になります。

このコードがプログラマに提供する関数は下記の2つです。

  • GC_malloc
  • GC_malloc_atomic

まず、GC_mallocはその名のとおり、メモリ確保の関数です。後片付けはシステムが勝手にやってくれるので、freeする必要はありません(う〜ん、ラクチン)。

GC_malloc_atomicは内部にポインタを含まないデータ(文字列など)の確保を行うための関数です。GC_mallocで代用しても差し支えはありませんが、適切な場面でGC_malloc_atomicを利用することでGC発動時のパフォーマンスが向上します。

今回のサンプルコードでは、GC_mallocまたはGC_malloc_atomicによりメモリ確保が行われるときに無条件で_System_GC.sweepを呼び出しています(sweep = 掃除。マインスイーパーを連想してしまうf(^^;;;)。これが何を意味するかというと、メモリ確保毎に常にメモリの掃除が行われるのです。一般的には、未解放のメモリが1MBないし10MBたまったときなど、指定条件が出揃った段階で呼び出されるべきものですので、今回のサンプルはちょいと処理速度が遅いです。

... ヘ(;・_・)へ

では、ソースコードの見どころを解説していきましょう。

'グローバル領域をルートに指定してスキャン
scan(_System_gc_GlobalRoot_StartPtr,_System_gc_GlobalRoot_Size)

'ローカル領域をルートに指定してスキャン
Dim NowSp As LONG_PTR
NowSp=_System_GetSp()
scan(_System_gc_StackRoot_StartPtr,(_System_gc_StackRoot_StartPtr As LONG_PTR)-NowSp)

これは_System_CGarbageCollection.sweepメソッドにある、メモリ回収時のルート集合を指定している部分です。グローバル変数、ローカル変数をルートにもってきていることがわかります。下記の3つの変数と1つの関数は普通のコードを書いただけでは取得できないので、コンパイラに自動的に定義&代入してもらうことにします。

  • _System_gc_GlobalRoot_StartPtr … グローバル変数がおかれるメモリの開始位置
  • _System_gc_GlobalRoot_Size … グローバル変数領域の大きさ(バイト単位)
  • _System_gc_StackRoot_StartPtr … スタックフレームの開始位置
  • _System_GetSp関数 … 現在のスタックポインタを取得する

次に、_System_CGarbageCollection.scanメソッドを見てみましょう。指定されたメモリ領域をスキャンし、GC_mallocで確保されたメモリを示すポインタが存在するかどうかをチェックしていきます。

scanメソッドは再帰的に呼び出され、ポインタが含まれる可能性のあるヒープ領域内もスキャンの対象になっている部分に注目しておくとよいでしょう。ポインタが含まれるかどうかはpbAtomic[index]を見分けることで判断できます。pbAtomicはGC_malloc/GC_malloc_atomicの違いをフラグで示しているといったほうが分かりやすいでしょうか。

    Sub scan(pStartPtr As *LONG_PTR, size As Long)
        Dim i As Long, count As Long, index As Long
        count=size/SizeOf(LONG_PTR)
        For i=0 To ELM(count)
            index=HitTest(pStartPtr[i])
            If index<>-1 Then
                If pbMark[index]=0 Then
                    pbMark[index]=1

                    If pbAtomic[index]=0 Then
                        'ヒープ領域がポインタ値を含む可能性があるとき
                        scan(ppPtr[index],pSize[index])
                    End If
                End If
            End If
        Next
    End Sub

あまり長ったらしくないソースコードで実現できたGCサンプル。今後は高速処理の徹底、マルチスレッド状況における動作検証などを行う必要がありそうです。

せっかくなので、ちょっとしたサンプルを作って遊んでみました。

Const MEGABYTE = 1024*1024
Const MAX_LOOP = 1000

Dim lpszBuffer As *Byte
Dim array_pTemp[1024] As LONG_PTR
Dim i As Long

For i=0 To MAX_LOOP
	lpszBuffer=malloc(MEGABYTE)
Next

Dim msg As String
msg=Ex"正常に終了しました。\r\n無駄に確保したメモリの総合サイズは "+Str$(MAX_LOOP/1000)+"GB です。"
MessageBox(0,msg,"GC Test",0)

1MBの無駄メモリを1000回確保するサンプルです。普通にmallocを使うとプロセスメモリはいっきに上がり、私の環境では10000回ループするとヒープ領域の許容範囲を超えてしまいました。

次に、GCを使ってメモリ確保を行ったサンプルを試してみます。

Const MEGABYTE = 1024*1024
Const MAX_LOOP = 1000

Dim lpszBuffer As *Byte
Dim array_pTemp[1024] As LONG_PTR
Dim i As Long

For i=0 To MAX_LOOP
	lpszBuffer=GC_malloc_atomic(MEGABYTE)
Next

Dim msg As String
msg=Ex"正常に終了しました。\r\n無駄に確保したメモリの総合サイズは "+Str$(MAX_LOOP/1000)+"GB です。"
MessageBox(0,msg,"GC Test",0)

無駄メモリの確保ということなので、GC_malloc_atomicを呼び出してみます。正確には計測しませんでしたが、やはりmallocと比べるとちょっと遅いです。まぁ、これは毎回のようにsweepしているのが原因なので、すぐに解消できそうです。

肝心な使用メモリの状況ですが、タスクマネージャで監視を行ったところ、常に平常値を保っておりました(素晴らしい!)。

このサンプルは、開発者向けの次回β版で早速動くようにしたいと思います。

ここまで考えるか・・・

abdev ここまで考えるか・・・ はコメントを受け付けていません

「着信があったふり」を演出できるケータイが今月9日に出るみたいです。

暗い夜道を一人で歩いているときや、長い話を聞かされている時に中座したい場合などに有効に利用できる。

http://japan.internet.com/allnet/20060705/5.html

だそうです。

遊んでいる最中にケータイいじられるのは好きじゃないですし、自分もあまりしません(っつか、基本的に誰からもかかってきやしませんf(–;;;)。

しかし、その場を抜け出すためにこの機能を利用するのも、ちょっと自信がいる行動かも。まぁ、好きな曲登録しといていつでもワンプッシュで聴ける程度に捉えるのがフツーですかね。

今日の音楽

abdev 今日の音楽 はコメントを受け付けていません

朝っぱらからアスワドを聞きながら作業に勤しんでおります。”Shy Guy” が一押し。なんか、休日モードになってしまいそう(いけない いけない)

Aswad – Shy Guy

さて、本日は時間を有効的に使いながら、CP2の不具合待ちとガベコレ調査を引き続き行っていたいと思います。

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS ログイン