2011年09月13日

Google App Engineの新料金体系対策

Google App Engineの料金体系が変わるというのは5月に発表されていたのでいまさらですが、最近になって実際に新料金体系でいくらになるのか確認できるようになりました。

私はGAEはTwitter botや簡単なスクリプトにしか使っていなかったので楽観視していたのですが、新料金体系では無料枠を超えることが分かり、慌てて対策をしました。

旧料金体系と新料金体系の違い

旧料金体系から大きく変わるのが、CPU時間ベースの課金から、インスタンス時間ベースの課金になります。

Google App Engineは、リクエストが増えると自動的にインスタンス数を増やして並列化してくれるのが最大の特長です。リクエストに対する反応が遅くなると自動的にスケールアウトし、暇になればインスタンス数を減らします。

新料金体系では、このインスタンスが動いている数×時間で金額が決まり、無料枠では24.0 28.0となっています。これは、インスタンス数が1つだけなら24 28時間、2つ動いていれば12 14時間までということです。

基本的にインスタンス数は自動制御なので、無料の範囲内だけで使いたいと思っていても、気を付けないと勝手にインスタンスを増やされて、24時間動かすことができなくなります。

また、Datastoreの制限も厳しくなり、旧料金では課金対象が容量だけだったのが、新料金ではDatastore操作回数でも制限を受けるようになり、私はこれもひっかかっていました。

今回は、この2点について対策をします。

続きを読む
2011年09月13日 【プログラミング】 | コメント(1) |
2011年03月25日

MONITORINFOEXはMONITORINFOを継承していた

Win32APIには、それ自身の大きさをメンバにもつ構造体というのが多くあります。例えばウインドウ作成時に使用するWNDCLASSEXは次のようになっています。

WNDCLASSEX
  1. typedef struct {
  2.     UINT cbSize;
  3.     UINT style;
  4.     WNDPROC lpfnWndProc;
  5.     int cbClsExtra;
  6.     int cbWndExtra;
  7.     HINSTANCE hInstance;
  8.     HICON hIcon;
  9.     HCURSOR hCursor;
  10.     HBRUSH hbrBackground;
  11.     LPCTSTR lpszMenuName;
  12.     LPCTSTR lpszClassName;
  13.     HICON hIconSm;
  14. } WNDCLASSEX, *PWNDCLASSEX;

cbSizeが構造体の大きさを表すメンバで、このメンバは必ず最初に宣言されるという決まりがあります。

このメンバは本質的にはバージョンを表していて、将来的に構造体が拡張されてもこのメンバを見ればどのバージョンの構造体を渡されたのか判別できるようになっています。

実際に拡張された例としては、BITMAPINFOHEADERがあります。Windows95で拡張されてBITMAPV4HEADERとなり、Windows98でBITMAPV5HEADERとなりました。

cbSizeを持つ構造体の初期化には、次のような定番の構文があります。

  1. WNDCLASSEX wc = { sizeof(WNDCLASSEX) };

これは配列や構造体を初期化リストを使って初期化する構文で、足りないメンバは0と見なすという性質を利用して、cbSizeに構造体の大きさを入れつつ残りは0で初期化する便利な書き方です。この一行だけで次のコードと等価になります。

  1. WNDCLASSEX wc;
  2. ZeroMemory(&wc, sizeof(WNDCLASSEX));
  3. wc.cbSize = sizeof(WNDCLASSEX);
続きを読む
タグ:Win32API
2011年03月25日 【プログラミング】 | コメント(2) |
2010年08月27日

掲示板CGIの削除キーは他人に簡単に見られるので注意

日本の個人サイトに多いログイン機構を持たない簡単な掲示板システムでは、後で記事を削除するためのパスワードを入力するものが多いですが、このパスワードをCookieに記憶しておいてCGI側でフォームに埋め込んで返すという仕組みはセキュリティ上の問題があります。

HTMLのフォームのパスワード入力欄は入力された文字が見えないようにマスクされていますが、この入力欄に初期値を与えようとすると、HTMLのソースにパスワードをそのまま書く必要があります。そのため、ブラウザで掲示板を開いた状態でそのページのソースコードを他人に見られてしまうと、パスワードがバレてしまいます。

次の例は、某サイトで配布されている掲示板CGIに、削除キーとして”pass”と入力して書きこんだ後の、CGIの返したHTMLの一部です。

<tr>
  <td nowrap><b>削除キー</b></td>
  <td>
    <input type="password" name="pwd" size="8" maxlength="8" value="pass">
	<small>(英数字で8文字以内)</small>
  </td>
</tr>

見ての通り、value=”pass”としっかり書かれています。

このように簡単に見ることができてしまうので、重要なアカウントに使用しているのと同じパスワードを簡易掲示板に入力するのは絶対にやめた方がいいです。

続きを読む
タグ:Webサービス
2010年08月27日 【プログラミング】 | コメント(2) |
2010年07月28日

C#からDirect3Dを使う第3の方法

C#からDirect3Dを使う手段として、以前はManaged DirectXがありましたが2007年頃からDirectX SDKから削除されてしまいました。

Managed DirectXが消された代わりに、現在はXNA FrameworkというPCとXbox360両方で動くゲームが作れるフレームワークを使うことでDirect3Dを使った描画を行うことができます。しかし、XNA Frameworkはゲーム製作のために高度に抽象化されたライブラリなのでDirect3Dとは全くの別モノになっています。

もう1つ、C#でDirect3Dを使う手段がMicrosoftから提供されています。それが今回紹介する「Windows® API Code Pack for Microsoft® .NET Framework」です。

API Code Packは、Windows Vistaや7の機能でC++からは利用できるがマネージコードからは利用できないAPIを、C#等のマネージコードから利用できるようにするライブラリです。その中にDirect3Dも含まれています。

例としてDirect3D10は次のようになっています。

API Code Pack

C++用のインターフェースから、ID3D10の接頭語を抜いた名前でクラスが定義されています(一部のクラスはD3Dの接頭語付き)。引数や戻り値が変わっているものもありますが、ほとんどが元のインターフェースと同じように定義されています。XNAのような抽象化されたものではなく、もっとDirect3Dをダイレクトに使いたいというDirect3D大好きっ子でも安心です。

ちなみに、API Code Packはソースコードでの提供となっているので、利用するには自分でビルドする必要があります。ライブラリ部分はC++/CLIで書かれているので、ビルドするにはVisualC++が必要になります。たぶんライブラリのビルドはExpress Editionでも出来ると思いますが、サンプルプログラムはC++とC#の混合プロジェクトなので、Express Editionではビルドできないと思います。

D3DXに相当するコードも用意されていますが、D3DXの全てを網羅しているわけではないようです。さっと見た感じでは、実行時にシェーダをコンパイルする機能は無さそうです。

また、みんなが大好きなDirect3D9もありません。対応しているのはDirect3D10.0、10.1、11.0、DXGI1.0、1.1となっています。Direct2DやDirectWriteにも対応しています。

ぶっちゃけ誰にでも作れそうなラッパーライブラリですが、Microsoftが公開したことで標準と呼べる物ができたのは大きいですね。

ところで、サンプルプログラムは無操作でもアニメーションし続けているにも関わらず、コールバックタイマーのような物が見当たらないので、どうやって画面を更新し続けているのか調べてみたら、次のようになっていました。

IntPtr DirectHost::WndProc( IntPtr hwnd,  int message,  IntPtr wParam,  IntPtr lParam, bool% handled)
{
    switch (message)
    {
    case WM_PAINT:
    case WM_DISPLAYCHANGE:
        {
            if (Render != nullptr)
                Render();            
        }
        handled = true;
        return IntPtr::Zero;

    case WM_DESTROY:
        {
            Render = nullptr;
            break;
        }
    }

    handled = false;
    return IntPtr::Zero;
}

通常、WM_PAINTのハンドラではBeginPaint/EndPaintやValidateRect等を呼んで、無効領域のクリアをしないといけません。しかし、このサンプルではWM_PAINTで何もしていないので、無効領域がクリアされず永遠にWM_PAINTが発生し続けます。

普通はWindowsプログラマがやってはいけないことのタブーを、このサンプルプログラムでは画面更新のトリガーに使っています。私の感覚では、気持ち悪いですね。

VistaからGDIのティアリングを抑える設計になったので、この方法で上手い具合にWM_PAINTが発生するんですかね?DWMを切った状態でどうなるのか、ちょっと心配です。

2010年07月28日 【プログラミング】 | コメント(0) |
2010年05月22日

やっと分かったフーリエ変換・続き

前回は、フーリエ変換とは入力値をグルグル回転させながら足し合わせる計算であるということを説明しました。今回は、なぜ回転させながら足し合わせると周波数分解できるのかという話です。

あらためて離散フーリエ変換の式を書いておきます。

dft

さて、ここでは入力値fjはガウス平面内で等速円運動をする波形とします。回転方向は cosθ+isinθ のθが増加する方向です。

離散フーリエ変換の式をよく見ると、eのべき乗部分にマイナスの符号が付いています。これは、入力信号を逆回転させることを意味しています。この「逆回転」というのがミソです。

0からnまでの間にちょうど1回転するベクトルを全部足し合わせると、お互いに打ち消し合って0ベクトルになります。

これを逆方向に1回転させながら足し合わせると、元のベクトルの回転が相殺されて全てのベクトルの向きが揃い、結果はn倍の長さのベクトルになります。(ベクトルの向きは最初の値の位相と等しくなる)

2回転させると逆方向に1回転と同じに、3回転させると逆方向に2回転と同じになるので、0ベクトルになってしまいます。

正方向に1回転するベクトルは、逆方向に1回転させたときだけ全ての位相が揃い、それ以外の回転数では全て0ベクトルになってしまいます。これが周波数分解の原理です。

この操作が視覚的に分かるデモをSilverlightで作ってみました。

上側のラジオボタンで入力信号の波形を選び、それを右側で回転させます。グラフのプロットエリアでマウスを左ドラッグをすると、向きを変えることができます。

標本化定理とナイキスト周波数

上のデモで入力信号を直流にして表示をサンプリング値だけにし、1回転と7回転を見比べてみると、まるで7回転は1回転と逆方向に回転しているように見えます。

これは「高速で回る自動車のタイヤが逆回転してるように見える原理」と言います。(嘘です)

アナログ信号をデジタル信号に変換する際に、元の信号の2倍以上の周波数でサンプリングしないと元通り復元できないという法則があります。これを標本化定理といいます。

今回はサンプリング数が8なので、その半分の4が復元できる限界の周波数となります。この周波数をナイキスト周波数と呼びます。(この例では時間の単位がないのでただ4とか8と言っていますが、0〜nで1秒だとすると4Hz、8Hzのことです)

ナイキスト周波数を超えた信号は、本来の信号とは異なる波形として観測されてしまいます。このような現象をエイリアシングと言います。今回はサンプリング数が8なので4回転までが正常に観測でき、5回転以上はエイリアシングにより逆回転しているように見えます。

離散フーリエ変換では、このエイリアシングによる逆回転までも有効に利用していて、逆方向の回転の計算をする代わりにナイキスト周波数以上の速さでブン回して同じ結果を得ています。今回は入力値として逆方向の回転波形は用意していませんが、逆方向に1回転する信号は7回転させたときに位相が揃います。

共役複素数

ある複素数に対して、虚部の符号が逆のものを共役複素数と言います。元の複素数と共役複素数を足し合わせると、虚部がお互いに打ち消し合って0になり、ただの実数になります。

上のデモで入力信号を正弦波にして、1回転と7回転、2回転と6回転を見比べると、虚部だけが反転した共役複素数になっています。(表示を分離ベクトルにすると分かりやすいです)

実数の数列に対して離散フーリエ変換をすると、x番目とn-x番目の結果は必ず共役複素数になります。逆フーリエ変換をすると、1回転と7回転(逆方向に1回転)がお互いに虚部を打ち消し合って、実数に戻るというわけです。そのため、実数のみを対象とした離散フーリエ変換はナイキスト周波数以下の結果だけあれば十分ということになります。

パワースペクトル

フーリエ変換の結果を表示する際には、パワースペクトルで表すのが一般的です。

パワースペクトルは、フーリエ変換の結果の絶対値で表されます。また、ナイキスト周波数を超える成分はエイリアシングによるものなので表示しません。(単純に半分だけ表示だとエネルギーの総和が半分になってしまうので、ナイキスト周波数以下を2倍にして表示する場合もあります)

パワースペクトルでは位相の情報が失われてしまうので、ここから信号を復元することはできません。あくまでも周波数成分を視覚的に確認するためのものです。

逆離散フーリエ変換

離散フーリエ変換の逆変換、逆離散フーリエ変換は次のようになります。

idft

フーリエ変換とほとんど同じ式ですね。

eのべき乗のマイナス符号が無くなっているので、フーリエ変換とは回転方向が逆になります。右回転させながら足し合わせるのがフーリエ変換なら、それを左回転させながら復元させれば元に戻るというわけです。

また、jとkも入れ替わっています。フーリエ変換では回転数一定で全体を足し合わせましたが、逆変換では位相を一定のまま回転数を変化させていきます。

頭の1/nは、フーリエ変換のときにn個の信号を足し合わせて結果がn倍のベクトルになっているので、それを打ち消すためにあります。離散フーリエ変換・逆離散フーリエ変換の式どちらにも1/√nの係数をかけて式を揃えるという宗派もあります。

2010年05月22日 【プログラミング】 | コメント(11) |
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。