2009年6月30日火曜日

にっきちゃ

Vol.24 4ビットマイコン 大人の科学マガジン 大人の科学.net
http://otonanokagaku.net/magazine/vol24/index.html

 ひゃっはー! はつばいびだー!
かいにいく。


/***/

 書店にいったら発売日が7/1、近日入荷となってた。The ぬか喜び!
あと、ついでにシャンプーとボディソープを買おうと思ってたのにすっかり忘れてた。

2009年6月26日金曜日

日記ちゃん

 たわむれに1km走ってみたら体温がもりもり下がって凄い寒い。
あと2時間ほどたつのに息切れが収まらないよ! 歳だ!

*追記
 熱中症らしい。
(1)熱中症招く「無知と無理」 : 健康プラス : 医療 : 医療と介護 : YOMIURI ONLINE(読売新聞)http://www.yomiuri.co.jp/iryou/medi/plus/20090804-OYT8T00487.htm?from=yoltop


 関係ないけど「もりもり」って擬音(?)が今自分の中でブームだ。
語感がかわいらしい。「しゃりしゃり」とかも好き。

2009年6月24日水曜日

にっきちゃん



 ペンギン作って遊んでた。
それにしてもおなかすいたなぁ

 お寿司食べに行って、
コーン巻きとシーチキン巻きとお稲荷さんとかっぱ巻き食べてきた。
おなかいっぱいになった。564円

 なんか急に父上の持ち物がなくなってた。
なんだろ? 離婚でもすんのカナ。

2009年6月22日月曜日

日記ちゃんがmemory pool

 メモリプールの挙動が怪しかったので、取得と解放を繰り返すだけのプログラムを書いて動かしたらメモリリークした。たかが128Byteのメモリプールをうまくコントロールできないとか涙が出る。
 ここ数週間ずっとそんなかんじ。

 たぶん解決した。
メモリ最適化のときに、空きメモリを指すポインタがおかしい値になってた。これを修正したらとりあえずリークしなくなった。

 修正したメモリプールをゲームのほうに適用したら、まだエラー出たんで、なんでよーって具合。
メモリプールはおかしくない!俺は常に正しい!俺が間違うことはない!
犯人はお前だ! 撲滅! オーバーフロー!
って、勘でoggをデコードするプログラムを見直したら、範囲外にもりもりファイル読み込んでた。
直したらエラーでなくなった。
たたかいはおわった。

 

 以下、使用中のメモリプール。
newと比較したところ10000000回で1000ms程度の差。つまりほとんど差なし。
resizeできたら面白いかなーと思ってvectorを使用しているけど、std::allocとかのほうが速いと思う。
参考程度に。

●基本イメージ
□□□□□□□□□□□□
↓メモリ頂戴
■■■■□□□□□□□□
↓メモリ頂戴
■■■■■■■■□□□□
↓返すよ
□□□□■■■■□□□□

こんな感じ。


●メモリ最適化イメージ
■■■■□□□□■■■■□□□□
[■4][□4][■4][□4]
↓返すよ
□□□□□□□□■■■■□□□□
[□4][□4][■4][□4]
↓最適化
□□□□□□□□■■■■□□□□
[□8] [■4][□4]



●欠陥
以下のような状況が頻繁に発生する
□□□□□□□□
↓1つ頂戴
□□□□■□□□
↓5つ頂戴
□□□□■□□□空きが無いから無理



#include <limits.h>
#include <windows.h>
#include <cstdio>
#include <tchar.h>
#include <vector>
 
 
 
class Pool
{
private:
  struct PoolObject
  {
    size_t blockNum;
    bool use;
 
    // デバッグ用オーバーフローチェック
    unsigned short check;
    enum { CHECK_PARAM = 0x5353, };
  };
 
 
 
  /** プール */
  std::vector<PoolObject> m_pool;
 
  /** 使用したメモリ量 */
  size_t m_useBlockNum;
 
  /** 次に確保しようとするメモリの先頭位置 */
  PoolObject* m_head;
 
public:
 
 
  /**
   * compaction
   * 隣り合った空きメモリを結合する。
   */
  void compaction()
  {
    m_head = NULL;
    size_t space = 0;
 
    const PoolObject* lastPoint = &m_pool[0] + m_pool.size();
    PoolObject* runner = &m_pool[0];
    for (; runner<lastPoint; runner+=runner->blockNum)
    {
      // err
      if ( runner->blockNum == 0 )
      {
        OutputDebugString(TEXT("Memory Pool Error...(object size == 0)\n"));
        abort();
        break;
      }
 
      if ( runner->use && space )
      {
        (runner - space)->blockNum = space;
        space = 0;
      }
      else if ( runner->use == false )
      {
        if ( !m_head ) m_head = runner;
        space += runner->blockNum;
      }
    }
 
    if ( space )
    {
      (runner - space)->blockNum = space;
    }
 
    if ( !m_head )
    {
      m_head = &m_pool[0];
    }
  }
 
 
 
private:
  /**
   * searchSpace
   * 空きメモリを探す。
   * @param blockNum 確保したいメモリ量(ブロック単位)
   * @return 見つけた空きメモリのポインタ。確保できないようであれば NULL。
   */
  PoolObject* _searchSpace( size_t blockNum )
  {
    // search
    const PoolObject* lastPoint = &m_pool[0] + m_pool.size();
    for (PoolObject* runner=m_head; runner<lastPoint; runner += runner->blockNum)
    {
      if ( runner->use == false &&
        runner->blockNum >= blockNum )
      {
        return (m_head = runner);
      }
    }
 
    // compaction
    compaction();
 
    // search retry
    for (PoolObject* runner=m_head; runner<lastPoint; runner += runner->blockNum)
    {
      if ( runner->use == false &&
        runner->blockNum >= blockNum )
      {
        return (m_head = runner);
      }
    }
 
    // space none
    return NULL;
  }
 
 
 
  /** sizeToBlockNum */
  static inline size_t sizeToBlockNum( const size_t size )
  {
    // ヘッダ用とデータ用で2は必ずいる
    return size / sizeof(PoolObject) + 2;
  }
 
 
 
  /** blockNumToSize */
  static inline size_t blockNumToSize( const size_t blockNum )
  {
    return blockNum * sizeof(PoolObject);
  }
 
 
 
public:
 
 
  /**
   * constructor
   * @param 作成するプールサイズ
   */
  explicit Pool( size_t size )
    : m_pool( sizeToBlockNum(size) + 8 )
    , m_useBlockNum( 0 )
    , m_head( NULL )
  {
    if ( size > 0 )
    {
      PoolObject* po = &m_pool[0];
      po->blockNum = m_pool.size();
      po->use = false;
      m_head = po;
    }
  }
 
 
 
  /**
   * destructor
   */
  ~Pool()
  {
#ifdef _DEBUG
    if ( m_useBlockNum )
    {
      Debug::outputDebugString( TEXT("[Pool]memory reak!: %dbyte, poolSize: %d\n"), getUseSize(), getPoolSize() );
    }
#endif
  }
 
 
 
  /**
   * alloc
   * プールからメモリを取得する。
   * @param size 取得したいメモリ量
   * @return 使用可能なアドレス。取得に失敗すればNULLが戻る。
   */
  void* alloc( size_t size )
  {
    // はなから空きがないのでお帰りください
    const size_t newBlockNum = sizeToBlockNum( size );
    if ( m_pool.size() - m_useBlockNum < newBlockNum )
    {
      return NULL;
    }
 
    PoolObject* po = _searchSpace( newBlockNum );
    if ( !po )
    {
      Debug::outputDebugString( TEXT("noneSpaceError: %d\n"), size );
      return NULL;
    }
 
 
    // もしも空きサイズが取得したいサイズよりも大きければ、空きサイズを減少させる
    if ( po->blockNum > newBlockNum )
    {
      PoolObject* next = po + newBlockNum;
      next->use = false;
      next->blockNum = po->blockNum - newBlockNum;
 
      // ここにこなかった場合ぴったりサイズなので設定しなおさなくていい
      po->blockNum = newBlockNum;
    }
 
#ifdef _DEBUG
    po->check = PoolObject::CHECK_PARAM;
#endif
    po->use = true;
    
    m_useBlockNum += newBlockNum;
    m_head = po + newBlockNum;
 
    // PoolObject一つ分だけずらしたアドレスを戻す
    return (po + 1);
  }
 
 
 
  /**
   * free
   * @param 返却するメモリのアドレス。
   */
  void free( void* obj )
  {
    if ( obj )
    {
      PoolObject* po = static_cast<PoolObject*>( obj ) - 1;
#ifdef _DEBUG
      if ( po->use == false )
      {
        Debug::outputDebugString( TEXT("2重解放? - [%p]size: %d\n"), obj, blockNumToSize(po->blockNum) );
      }
      else if ( po->blockNum == 0 || po->check != PoolObject::CHECK_PARAM )
      {
        Debug::outputDebugString(TEXT("オーバーフローの疑い: %p\n"), obj);
      }
      else
#endif
      {
        po->use = false;
        m_useBlockNum -= po->blockNum;
      }
    }
  }
 
 
 
  /** プールのサイズ取得 */
  size_t getPoolSize() const { return blockNumToSize( m_pool.size() ); }
  /** プールのメモリ使用量を取得 */
  size_t getUseSize() const { return blockNumToSize(m_useBlockNum); }
};



 空きメモリをリストにして、要求があればリストから渡すようにすれば高速化できそう。
ただメモリ最適化のときに、空きメモリリストもいじらないといけなくなるので処理時間が気になる。メモリ要求回数が圧倒的に多いから、全体的には速くなると思うが。

2009年6月6日土曜日

273号

273号
http://cid-8cd7cf5ea9fbca55.skydrive.live.com/self.aspx/Public/music/no%20name273.ogg

size: 1.7MB
製作時間: 5時間ぐらい
ツール: ピストンコラージュ ver 0.9.1.4
音源: PEPOFONT ver0.70

 Bメロが凄い苦手で、研究がてら。
AからBへは調が一緒なら(もっと的確な言葉がある気がする)割と強引に行っても大丈夫っぽい。
つなぎ方がいまひとつよくわからないから適当に作らざるを得ない。