« 2010年8月 | トップページ | 2010年10月 »

2010年9月の6件の投稿

2010/09/26

[読書]約定率が低いことは良いことか『システム改革の正攻法』

 

正確には、システムの性能が上がったことを外部の人に示す指標として約定率の低下を用いるのは適切なんだろうか、という疑問です。

 

本書『システム改革の正攻法』の冒頭で、東証新システムarrowhead導入の効果について、以下のように記述されています。

arrowheadの導入効果は、早くもデータに表れている。代表例が東証の株式市場における「約定率」の変化だ(図1-4)。約定率とは、約定件数を全注文件数で割った値であり、これが低いほど、一般的に株式売買システムの応答スピードが速いと考えることができる。全注文に占める取消注文が相対的に多いからであり、約定までに注文と取り消しを繰り返す回数が増えたと考えることができるからだ。

引用文中の図1-4というのは、期間や表記方法は異なりますが、東証のwebサイト『arrowheadのIT Japan Award2010「経済産業大臣賞(グランプリ)」受賞について』(2010/07/05)の2つめのPDF『arrowhead(東証株式売買システム)の「①IT Japan Award2010 経済産業大臣賞(グランプリ)受賞」及び「②arrowhead稼働後6ヶ月の運転状況」について』11ページ目と同じようなものです。

上記のPDFでも『稼働前は40%以上あった約定率が、稼働後に40%を下回る水準に』と書かれているように、現在の東証は約定率低下は好ましいことである、としています。

その他、東証が約定率に関して触れている記事を探したところ、鈴木義伯東証CIOの講演『東証新売買システム(arrowhead)の開発経緯について~上流工程の取り組みとその効果~』(2010/04/27)に関して、日本システム監査人協会が発行する活動報告(SAAJ 会報)PDFにありました。

3.稼動後の状況
arrowhead 稼動後、東証自身で各種の稼動状況のデータを収集し分析を実施している。
主な指標とその傾向は以下の通りである。
(1) 注文件数/約定件数/約定率
注文件数の増加と約定件数の微増という傾向が見られる。ただし、約定率は低下傾向にあるが、これは注文の小口化が進んだ結果が要因であろうと分析している。

ここでは約定率の低下とシステム刷新の因果関係を否定しているように取れますので、途中で方向転換したのかもしれません。

余談ですが、ライブドアショック後2006/01/18に行われた記者会見の議事録PDFでは、深山浩永執行役員(当時)と記者とのやり取りで以下のように発言されており、注文の小口化と約定率の因果関係の説明に一貫性がありません。

深山「[前略]注文件数の半分程度が約定件数であろうという見方をしておりましたが、最近の傾向だと、約定率が若干増加傾向を示しているということがございます。[後略]」

記者「その背景にあるのは何ですか。」

深山「正確にはよく分からないのですが、システム発注等で細かくいっぱい成立させていくということがあるのではないかと想像されます。」

 

閑話休題。

一般的に、取引参加者から見て約定率は高い方が良いのでしょうか、低い方が良いのでしょうか。単純に考えると約定率が低いということは、買いたいのに買えない(あるいは売りたいのに売れない)という状況であるため、高い方が良さそうに思えます。

別の見方をすると、買いたくもない注文(売りたくもない注文)を出して取り消していることになりますので、見せ玉と何が違うのか、とも感じます。

また、Googleで”約定率”を検索してみると(FX業者がうざったいので-FXも指定しています)、約定率が低いことが良いことだと主張しているのはarrowhead関連の記事だけのように見えます(ちなみにFX業者は高約定率を売りにしています)。にちゃんねるのアローヘッドスレでは概ね不評のようです。

 

一方、米国のwebサイトでは、取消率の高さ(つまり約定率の低さ)”cancellation rate”はHigh-Frequency Trading(HFT)関連の話題でしばしば登場しており、賛否両論のように感じました。

これについてはSECwebサイトPress Release: SEC Issues Concept Release Seeking Comment on Structure of Equity Markets(2010/01/13)の一番下のリンク先PDF”The full text of the concept release”及びこれに対する証券会社等からのコメントを読めば現状を理解できる…と思うのですが、英語は不得意なもので…concept release「Fairness of Market Structure」節の以下の文章辺りが該当の箇所でしょうか…

Rule 605 does not require disclosure of the amount of time that canceled non-marketable orders are displayed in the order book of trading center before cancellation. Considering the high cancellation percentage of non-marketable orders, should Rule 605 require the disclosure of the average time that canceled orders were displayed in the order book?

ただ、Jun. 17, 2010 Memorandum from the Division of Trading and Markets regarding a June 16, 2010, meeting with representatives of Tradeworx, Inc. のPDFでは、取消率の高さは問題ではない、と頑なに主張しているようなので、逆に言えばSECは取消率の高さを問題にしている、少なくともSECは取消率の高さが問題ではなかろうかと提言している、のではないかと思われます。

 

そんなこんなで、「約定率が下がりました!」「おお、すごい!」となる程の共通認識は取られていないのではないか、と考えたのですが、実際のところどうなんでしょう。

 

関連エントリ: [読書]どの口が東証システム(arrowhead)開発を指して正攻法だとのたまうのか『システム改革の正攻法』

2010/09/21

[読書]彼女と二人で「C」体験!にあえてツッコむ

ストーリー上の小道具なわけで、無粋かとも思いましたので淡々と。前エントリからの流れということで…

 

出てくるソースはこれだけです。

   1: #include<empirex.h>
   2: class CHeavyInfantry : public CHoplite
   3: {
   4: public:
   5:     int ReflectAnyStrike();

CじゃなくてC++でした。クラス名がCで始まる、メンバ変数名が大文字で始まる、開きカッコの前で改行、というのはMFCのコーディング標準でしたっけ。あと、作中ではF7キーがビルドのショートカットキーになっているので、開発環境はVC6でしょうか[追記: 最新バージョンでもVCのビルドはF7でした。VC#と混同していたようです]。

p.33
ポインタのサイズは一律で4バイトです

64bit環境では通常8バイトです(参考)。この部分、作中に登場する入門書の、ポインタ変数の説明箇所の引用です。ただ、現実には、ポインタ変数が登場する段階で変数のサイズに言及するような入門書はあまり無いと思います…

p.84
「[前略]この基底クラス—"CHearvyInfantry"はC++の標準ライブラリには存在しない。[後略]」
p.88
「"重装歩兵"—"CHearvyInfantry"は、基底クラスなんです」
「このメモで定義されているのは、派生クラス。"DHoplite"のほう」

冒頭のコードの書き方だと、基底クラスはChoplite,その派生クラスがCHeavyInfantryになります。つまり説明が逆なんですが、そういうものだと思ってストーリーを読み進めていく必要があります。実在のC++とは異なるファンタジー言語を設定しているのかな、とも思いましたが、そうすると言語仕様的に変ですね(class,publicはどっちに係るんだろう)。

p.89
「クラスの継承(オーバーライド)—というものがあります。[後略]」

“継承”という漢字に”オーバーライド”というルビが振ってある箇所ですが、継承(インヘリタンス)とオーバーライドは別概念です。

p.211
「…デファインというのは、定数定義のことです」

C++で定数と言えば、const修飾した変数のことでしょう。defineの説明はこちら

 

以上です。作中ではずっとCで通してるので、このコードはCという設定かと思いきや、C++という単語も数回登場します。ところでプログラミング言語C++って絶版になったんですかね…

…見逃していました。

p.220-225

「[前略]”EX_HOPLON”に定義する、六桁の数値だ」
[中略]
「—”010831”だ」
[中略]
—1 file was successful.
の、一行を最後に、ストップする。作業が正常に終了した証だ。

頭が0だと8進数なので、本来はコンパイルエラーになります(8進数で使用できる数字は0から7まで)。実はこの数値を入力した人はコンパイル前に気づいてて…、とかだと話は広がりそうです。

2010/09/20

[読書]どの口が東証システム(arrowhead)開発を指して正攻法だとのたまうのか『システム改革の正攻法』

「システム改革の正攻法」という東証の次世代株式売買システム「arrowhead」を立ち読みして、少し違和感を感じたので購入してみました。

パラパラとめくってみて、うーん、他の人はどんな感想なんだろう、と検索してみたところ、小飼弾さんの書評

なにしろこちらにはソースコードの一部まで乗っているのだ。

という記述を見つけました。おおそんなものが書いてあったのか、と該当箇所を読んでみたところ、全く腑に落ちなかったのでまとめてみました。「第12章 スピード1000倍増の秘密 - 世界最速システムの全貌」 の 「マイクロ秒を惜しみ処理時間を削る」という節です。

p.132 図12-3に対応がまとめてありましたのでここから引用します。

tse01 

  • 設計段階で、業務ロジックを基に実行ステップ数を算出し、そこから処理時間を試算。目標時間を超えるものはステップ数削減のためにロジックや記述を見直す

○。ありだとは思いますが、この節のタイトル「マイクロ秒を惜しみ処理時間を削る」とはちょっとレベル感が違うような気はします。まあ正攻法ということで。

 

  • アプリケーション内で複数のエラー検定(チェック)処理を行う場合、当てはまる確率の高い順に記述
  • 業務処理やデータの特性に合わせた検索方法を採用

◎。これは、今回の発注者(東証)側の体制への取り組みを考えると、非常に効果的に機能したと想像します。

 

  • 呼び出し順序が決まっているいくつかのソフト部品を一つに集約、関数の呼び出し回数を削減

×。関数のインライン化、ということでしょうが、一般的には正攻法ではなくバッドノウハウです。

アンチパターンでは肥満児(The Blob)という名前が付けられています(ただしこのパターンはOOD/Pに対して適用されるもので、本システムに対しては正確な名付けではありません)。また、リファクタリングのモチベーションとなる不吉な匂いの「長すぎるメソッド」にも分類されます。

正攻法としては、関数インライン化はコンパイラに任せることです(C99ではinlineキーワードが標準化されました)。

また、強引にインライン化した際のデメリットとしては、キャッシュメモリが有効に機能しなくなる、スラッシングが発生する、といったことが挙げられます。

「ソフト部品を一つに集約」という表現が曖昧で、もしかするとダイナミックリンクをスタティックリンクに変更する、LTO(Link-Time Optimization)が効かないコンパイラへの対応(コンパイラ事情には疎いのですが、gccでは比較的最近取り入れられたそうです)、といった内容にもとれますが、いずれにせよ保守性とのトレードオフになりますので諸手を挙げて正攻法とは呼べません(どちらかというとバッドノウハウに分類されます)。

 

  • 複数のスレッドによるデータの共有を禁止(データを持ちまわりたい場合は、引数による受け渡しを利用)

×。速度向上につながる理由も分かりませんし、カッコ前後の文章のつながりも分かりません。一般的にはデータは共有した方がパフォーマンスは向上します。引数による受け渡しを行ったからといって共有が禁止できるわけではありません。スレッド間でデータを共有しない一般的な理由は、パフォーマンスに拠るものではなく並行処理におけるアクセス競合を防ぐためです。

 

  • データ操作時の関数は「memxxx」を利用(「strxxx」関数は使わない)

○。strcpy_sを使わずにmemcpyを使用する、memmoveを使わずにmemcpyを使う、といった方針であれば、パフォーマンスとセキュリティリスクのトレードオフで前者を選択したのだな、ということが明確なのですが(ただしそれが正攻法であるかどうかは別問題です)。

要するに文字列を文字列として扱わず固定長バイナリとして扱う、ということなのですが、この対応を行うことの問題点としては

    • 有効バイト以降(‘\0’以降)も意識する必要がある。本システム方針に沿って言えば、本来不要な部分の初期化、代入コストが発生する。
    • 文字列を文字列として扱っている部分との境界(例えば周辺システムとのインタフェース)でも上記を意識する必要がある。
    • 本来未初期化部分であるべきところを正しそうな値に置き換えてしまうことで、動的検査(例えばPurifyPlus)の能力を弱めてしまう。

といったことが挙げられ、個人的には△としたいです。しかし、現実のパフォーマンス差を見ると…という点で○です(私もこういう対応を行うことはありますし…)。

 

  • フラグ(1バイトデータ)の比較には、「memcmp」関数を使わずに直接データを比較
  • 1バイト以外のデータの比較には「memcmp」関数を使う

×。意味不明ですが、おそらくchar flg;char str[10];の場合の差異を言いたいのでしょう。しかしmemcmpがとる引数はvoid*型なのでそもそもchar型変数を引数にとることはできません。char*型変数が指す1バイトのデータ比較であれば、==を使おうがmemcmpを使おうがパフォーマンスは変わりません。

ところで、この記述を正確に読み取ると、intみたいな組み込み型変数もmemcmpを使うようになりますが(通常intは4バイト)、さすがにそんなことはやっていないでしょうね。

 

  • データ項目一つひとつを初期化するのでなく、初期値をセットした変数を一度にコピー(図12-5参照)

後述します。

 

  • 関数の引数にはポインタを使う、繰り返し処理内で無駄な記述をしない、冗長なチェック処理をなくす、無駄なログ出力を止める

○。当たり前と言えば当たり前なのですが、「正攻法」という観点なので。ただし繰り返し処理の中で変数宣言を行うな、といった最適化でどうとでもなるようなものだったら笑います。

ちなみに、私が担当したシステムでは、ログの重要度に応じて非同期で出力するか同期で出力するか切り替える、といったようなことも実装しました。JavaだとLog4jのAppenderで簡単に実現できみたいなんですけどね。

 

後回しにした構造体について。

 tse02

この図からわかることを列挙します。

  • 初期値の代入にはBGAA_Memcpyという関数が使われていますが、以下では文中の説明よりmemcpy相当として考えています。引数からみても、memcpyより高速なことを行っているようには見えないです。
  • コメントのついていない Filter_m[n] はアラインメント調整用のパディングメンバでしょう。OSがLinuxn=5のものがあるということは、64bitなんでしょうかね。
  • アラインメントが決め打ちです。
  • sizeof(int)などが決め打ちです。
  • 初期値をchar配列で定義しており、サイズは構造体に合わせています。

これだけでも個人的には×をつけたいところですが、移植性に関しては考慮する必要が無いという判断なのでしょうし(longを使わずにlong longを使っているところを見るとあまり吹っ切れていないようにも見えますが)、保守性について重視していないこともこれまでの対応で明らかなので、ひとまず置いておきます。

構造体の初期化、というと通常は代入を使うわけですが、それよりもmemcpyの方が高速だ、という判断でmemcpyを使用しているのですから、双方比較してみれば妥当性は確認できます。

今回使用したコードは以下になります。構造体は図12-5の上半分を用いています。また、コンパイル環境はUbuntu10.04 32bit gcc-4.4.3になります。結果は-O3で最適化しています。

   1: #include <stdio.h>
   2: #include <stdlib.h>
   3: #include <string.h>
   4:  
   5: typedef struct {
   6:     char IssueKey[16];
   7:     char SecExKbn[1];
   8:     char MktKbn[2];
   9:     char IssueCd[12];
  10:     char IssueKbn[4];
  11:     char Filter_1[5];
  12:     long long Irate;
  13:     long long RepP;
  14:     char YldRstrn[1];
  15: } LAA01_t;
  16:  
  17: const static LAA01_t init_value = {
  18:     {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20},
  19:     {0x20},
  20:     {0x20,0x20},
  21:     {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20},
  22:     {0x20,0x20,0x20,0x20},
  23:     {0x20,0x20,0x20,0x20,0x20},
  24:     0,
  25:     0,
  26:     {0x20}
  27: };
  28:  
  29: const static char init_value_char[sizeof(LAA01_t)] ={
  30:     0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
  31:     0x20,
  32:     0x20,0x20,
  33:     0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
  34:     0x20,0x20,0x20,0x20,
  35:     0x20,0x20,0x20,0x20,0x20,
  36:     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  37:     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  38:     0x20
  39: };
  40:  
  41:  
  42:  
  43: void assign_operator(LAA01_t *t1, const LAA01_t *t2){
  44:     *t1=*t2;
  45: }
  46:  
  47: void assign_memcpy(LAA01_t *t1, const LAA01_t *t2){
  48:     memcpy(t1,t2,sizeof(LAA01_t));
  49: }
  50:  
  51: void assign_memcpy_char(LAA01_t *t1, const char *c){
  52:     memcpy(t1,c,sizeof(LAA01_t));
  53: }
  54:  
  55:  
  56: int main(int argc, char** argv) {
  57:     LAA01_t t1, t2, t3;
  58:  
  59:     assign_operator(&t1,&init_value);
  60:     assign_memcpy_char(&t2,init_value_char);
  61:     assign_memcpy(&t3,&init_value);
  62:  
  63:     printf("%s[end]\n",t1.IssueKey);
  64:     printf("%s[end]\n",t2.IssueKey);
  65:     printf("%s[end]\n",t3.IssueKey);
  66:     return (EXIT_SUCCESS);
  67: }
  68:  

上記コードの説明を簡単に行います。

  • 初期値としてinit_valueという構造体を定義しています。
  • 東証のコード相当の初期値はchar配列のinit_value_charです。
  • assign_memcpy_charはmemcpy関数でchar配列から値をコピーする関数です。東証のコード相当です。
  • assign_operatorは代入演算子で代入する関数です。
  • assign_memcpyはmemcpy関数で構造体から値をコピーする関数です。参考として作成してみました。

つまり、assign_memcpy_char関数とassign_operatorの差が、memcpyを利用して初期値を設定することのメリットになります。上記コードをコンパイル後、objdump -dコマンドでアセンブラコードを表示し、比較しました。

アセンブラについての知識は全く無いに等しいので検証できるか不安でしたが、杞憂に終わりました。以下がそれぞれの関数の部分についてのコードになります。

   1: 080484e0 <;assign_memcpy_char>:
   2:  80484e0:    55                       push   %ebp
   3:  80484e1:    89 e5                    mov    %esp,%ebp
   4:  80484e3:    8b 55 0c                 mov    0xc(%ebp),%edx
   5:  80484e6:    8b 45 08                 mov    0x8(%ebp),%eax
   6:  80484e9:    8b 0a                    mov    (%edx),%ecx
   7:  80484eb:    89 08                    mov    %ecx,(%eax)
   8:  80484ed:    8b 4a 04                 mov    0x4(%edx),%ecx
   9:  80484f0:    89 48 04                 mov    %ecx,0x4(%eax)
  10:  80484f3:    8b 4a 08                 mov    0x8(%edx),%ecx
  11:  80484f6:    89 48 08                 mov    %ecx,0x8(%eax)
  12:  80484f9:    8b 4a 0c                 mov    0xc(%edx),%ecx
  13:  80484fc:    89 48 0c                 mov    %ecx,0xc(%eax)
  14:  80484ff:    8b 4a 10                 mov    0x10(%edx),%ecx
  15:  8048502:    89 48 10                 mov    %ecx,0x10(%eax)
  16:  8048505:    8b 4a 14                 mov    0x14(%edx),%ecx
  17:  8048508:    89 48 14                 mov    %ecx,0x14(%eax)
  18:  804850b:    8b 4a 18                 mov    0x18(%edx),%ecx
  19:  804850e:    89 48 18                 mov    %ecx,0x18(%eax)
  20:  8048511:    8b 4a 1c                 mov    0x1c(%edx),%ecx
  21:  8048514:    89 48 1c                 mov    %ecx,0x1c(%eax)
  22:  8048517:    8b 4a 20                 mov    0x20(%edx),%ecx
  23:  804851a:    89 48 20                 mov    %ecx,0x20(%eax)
  24:  804851d:    8b 4a 24                 mov    0x24(%edx),%ecx
  25:  8048520:    89 48 24                 mov    %ecx,0x24(%eax)
  26:  8048523:    8b 4a 28                 mov    0x28(%edx),%ecx
  27:  8048526:    89 48 28                 mov    %ecx,0x28(%eax)
  28:  8048529:    8b 4a 2c                 mov    0x2c(%edx),%ecx
  29:  804852c:    89 48 2c                 mov    %ecx,0x2c(%eax)
  30:  804852f:    8b 4a 30                 mov    0x30(%edx),%ecx
  31:  8048532:    89 48 30                 mov    %ecx,0x30(%eax)
  32:  8048535:    8b 4a 34                 mov    0x34(%edx),%ecx
  33:  8048538:    89 48 34                 mov    %ecx,0x34(%eax)
  34:  804853b:    8b 52 38                 mov    0x38(%edx),%edx
  35:  804853e:    89 50 38                 mov    %edx,0x38(%eax)
  36:  8048541:    5d                       pop    %ebp
  37:  8048542:    c3                       ret    
  38:  8048543:    8d b6 00 00 00 00        lea    0x0(%esi),%esi
  39:  8048549:    8d bc 27 00 00 00 00     lea    0x0(%edi,%eiz,1),%edi
   1: 08048470 <;assign_operator>:
   2:  8048470:    55                       push   %ebp
   3:  8048471:    89 e5                    mov    %esp,%ebp
   4:  8048473:    8b 55 0c                 mov    0xc(%ebp),%edx
   5:  8048476:    8b 45 08                 mov    0x8(%ebp),%eax
   6:  8048479:    8b 0a                    mov    (%edx),%ecx
   7:  804847b:    89 08                    mov    %ecx,(%eax)
   8:  804847d:    8b 4a 04                 mov    0x4(%edx),%ecx
   9:  8048480:    89 48 04                 mov    %ecx,0x4(%eax)
  10:  8048483:    8b 4a 08                 mov    0x8(%edx),%ecx
  11:  8048486:    89 48 08                 mov    %ecx,0x8(%eax)
  12:  8048489:    8b 4a 0c                 mov    0xc(%edx),%ecx
  13:  804848c:    89 48 0c                 mov    %ecx,0xc(%eax)
  14:  804848f:    8b 4a 10                 mov    0x10(%edx),%ecx
  15:  8048492:    89 48 10                 mov    %ecx,0x10(%eax)
  16:  8048495:    8b 4a 14                 mov    0x14(%edx),%ecx
  17:  8048498:    89 48 14                 mov    %ecx,0x14(%eax)
  18:  804849b:    8b 4a 18                 mov    0x18(%edx),%ecx
  19:  804849e:    89 48 18                 mov    %ecx,0x18(%eax)
  20:  80484a1:    8b 4a 1c                 mov    0x1c(%edx),%ecx
  21:  80484a4:    89 48 1c                 mov    %ecx,0x1c(%eax)
  22:  80484a7:    8b 4a 20                 mov    0x20(%edx),%ecx
  23:  80484aa:    89 48 20                 mov    %ecx,0x20(%eax)
  24:  80484ad:    8b 4a 24                 mov    0x24(%edx),%ecx
  25:  80484b0:    89 48 24                 mov    %ecx,0x24(%eax)
  26:  80484b3:    8b 4a 28                 mov    0x28(%edx),%ecx
  27:  80484b6:    89 48 28                 mov    %ecx,0x28(%eax)
  28:  80484b9:    8b 4a 2c                 mov    0x2c(%edx),%ecx
  29:  80484bc:    89 48 2c                 mov    %ecx,0x2c(%eax)
  30:  80484bf:    8b 4a 30                 mov    0x30(%edx),%ecx
  31:  80484c2:    89 48 30                 mov    %ecx,0x30(%eax)
  32:  80484c5:    8b 4a 34                 mov    0x34(%edx),%ecx
  33:  80484c8:    89 48 34                 mov    %ecx,0x34(%eax)
  34:  80484cb:    8b 52 38                 mov    0x38(%edx),%edx
  35:  80484ce:    89 50 38                 mov    %edx,0x38(%eax)
  36:  80484d1:    5d                       pop    %ebp
  37:  80484d2:    c3                       ret    
  38:  80484d3:    8d b6 00 00 00 00        lea    0x0(%esi),%esi
  39:  80484d9:    8d bc 27 00 00 00 00     lea    0x0(%edi,%eiz,1),%edi
   1: 08048550 <;assign_memcpy>:
   2:  8048550:    55                       push   %ebp
   3:  8048551:    89 e5                    mov    %esp,%ebp
   4:  8048553:    8b 55 0c                 mov    0xc(%ebp),%edx
   5:  8048556:    8b 45 08                 mov    0x8(%ebp),%eax
   6:  8048559:    8b 0a                    mov    (%edx),%ecx
   7:  804855b:    89 08                    mov    %ecx,(%eax)
   8:  804855d:    8b 4a 04                 mov    0x4(%edx),%ecx
   9:  8048560:    89 48 04                 mov    %ecx,0x4(%eax)
  10:  8048563:    8b 4a 08                 mov    0x8(%edx),%ecx
  11:  8048566:    89 48 08                 mov    %ecx,0x8(%eax)
  12:  8048569:    8b 4a 0c                 mov    0xc(%edx),%ecx
  13:  804856c:    89 48 0c                 mov    %ecx,0xc(%eax)
  14:  804856f:    8b 4a 10                 mov    0x10(%edx),%ecx
  15:  8048572:    89 48 10                 mov    %ecx,0x10(%eax)
  16:  8048575:    8b 4a 14                 mov    0x14(%edx),%ecx
  17:  8048578:    89 48 14                 mov    %ecx,0x14(%eax)
  18:  804857b:    8b 4a 18                 mov    0x18(%edx),%ecx
  19:  804857e:    89 48 18                 mov    %ecx,0x18(%eax)
  20:  8048581:    8b 4a 1c                 mov    0x1c(%edx),%ecx
  21:  8048584:    89 48 1c                 mov    %ecx,0x1c(%eax)
  22:  8048587:    8b 4a 20                 mov    0x20(%edx),%ecx
  23:  804858a:    89 48 20                 mov    %ecx,0x20(%eax)
  24:  804858d:    8b 4a 24                 mov    0x24(%edx),%ecx
  25:  8048590:    89 48 24                 mov    %ecx,0x24(%eax)
  26:  8048593:    8b 4a 28                 mov    0x28(%edx),%ecx
  27:  8048596:    89 48 28                 mov    %ecx,0x28(%eax)
  28:  8048599:    8b 4a 2c                 mov    0x2c(%edx),%ecx
  29:  804859c:    89 48 2c                 mov    %ecx,0x2c(%eax)
  30:  804859f:    8b 4a 30                 mov    0x30(%edx),%ecx
  31:  80485a2:    89 48 30                 mov    %ecx,0x30(%eax)
  32:  80485a5:    8b 4a 34                 mov    0x34(%edx),%ecx
  33:  80485a8:    89 48 34                 mov    %ecx,0x34(%eax)
  34:  80485ab:    8b 52 38                 mov    0x38(%edx),%edx
  35:  80485ae:    89 50 38                 mov    %edx,0x38(%eax)
  36:  80485b1:    5d                       pop    %ebp
  37:  80485b2:    c3                       ret    
  38:  80485b3:    8d b6 00 00 00 00        lea    0x0(%esi),%esi
  39:  80485b9:    8d bc 27 00 00 00 00     lea    0x0(%edi,%eiz,1),%edi

全て同一です。ちなみに最適化しない場合は、memcpyを利用するとインライン化されず関数コールが増える分、memcpyを利用する方がコスト増です。

今回はソースコードを書いて試してみましたが、そもそも、なぜコンパイラは最適な代入処理を行ってくれない、という考えに至るのでしょうか。

上記のような対応を行った結果、保守性、移植性を低下させたにも関わらず、パフォーマンスには全く寄与しない(どころか低下させる可能性がある)ものになっています。評価としては二重×どころでは済みません。

 

これまで示してきた内容より、この書籍が言うところの「正攻法」とは、バッドノウハウを駆使してでもarrowheadの第一優先目標である速度向上を叶える、というものです。しかし一般的にはそれを正攻法とは呼びません。

以上、小飼さんの書評がきっかけということもあり、久しぶりにこちらを意識して書いてみました。

 

最後に。本書の中で鈴木義伯東証CIOが「技術者冥利に尽きる」とおっしゃっていらっしゃることについて。

このような巨大システム構築プロジェクトを予定通り(で良いんでしたっけ?当初は2009年秋だったような気もしますがこれは忘れます)完遂できた、情報システムの最高責任者であるCIOのプロジェクトマネジメント能力は並大抵のものではないと思われます。正直、私は2010年1月4日にarrowheadが稼働できるとは思っていませんでした。

しかし、私が同じような立場に立ったとするならば、目標を達成するために上で述べてきたような(仮に全て速度向上に繋がるとしても)泥臭い対応を行わなければならなかったことや、21世紀にもなってこのような保守性の低いシステムを見続けなければならないだろう若いSEのことを考えると、「技術者冥利に尽きる」などとは決して言うことはできないでしょう。万が一そのような言葉を吐かなければならない状況が予想されるのであれば、ここで記載したような対応をオープンにはしないでしょう。

この「技術者」についての価値観の違いが、冒頭に記載した違和感の正体かな、と考えます。

というか冒頭で示した小飼さんの書評、

全く奇をてらったことがない。まさに正攻法。愚直といってもいい。

自身で示した箇所の内容もちゃんと読んでませんよね…?

 

プログラミング的な部分以外にも言いたいことは出てきそうな予感がしますが、それはまた気が向けば。

2010/09/11

さきゅばす/coroid用ffmpegビルドpatch更新

前回記載した変更点をパッチに反映しました。ダウンロードはこちらから。

2010/09/08

Nixie Clock(Android用秒表示時計) Ver.0.4.0 Xperia対応

ダウンロードはこちらから

Steins;Gateのダイバージェンスメータ風Androidデスクトップウィジェット、Nixie ClockのXperia対応です。

要望を貰ってから大分時間が経ってしまいましたが、PC版発売記念ということでここはひとつ。

コメントでは、Xperiaで表示すると小さくて見づらい、とのことでしたが、別のどこかでは大きすぎワロタみたいなコメントもありまして、Xperiaではどんな表示になっているのだろうと思っていました。

大きすぎ、というのは、時計の描画領域が小さいにも関わらず占有する画面上の領域が大きすぎる、つまりウィジェットの大きさの割に場所とりすぎだろ、ということが言いたいのかな、と理解しました。

今回の対応でHT-03A上で見えるのと同じ大きさになっていると思います。

2010/09/05

さきゅばす/coroid用ffmpegビルドの変更点

以前のパッチ作成時点から、ffmpeg本体に入れられたいくつかの変更のため、そのままパッチを当てられなくなっていました。

この点について簡単にメモしておきます。

configureオプションの変更

--ebable-libfaadと--enable-avfilter-lavfがなくなっていました。

libfaadについては、

FFmpeg rev.23653から、libfaadが削除されました。
HE-AAC v2デコーダーが本体に実装されたので、libfaadは不要になったらしいです。
(: FFmpegのコンパイル (2010/6/15) お気に入りの動画を携帯で見よう より)

ということだそうです。

fvfilter-lavfについては、コミットログに

------------------------------------------------------------------------
r24569 | stefano | 2010-07-28 17:56:49 +0900 (水, 28  7月 2010) | 2 lines
Remove reference to the unexisting movie filter and the corresponding
useless --enable-avfilter-lavf option.
------------------------------------------------------------------------

とありますので、元々意味が無かったんでしょうか。

 

ビルド時のエラー

makeを実行すると以下のエラーで止まります。

libavfilter/parseutils.c: In function 'color_table_compare':
libavfilter/parseutils.c:217:5: error: implicit declaration of function 'strcasecmp'

r23823の変更の影響のようです(参考)。configureコマンドを実行した後にconfig.makファイルを開きCFLAGSの行から-Werror=implicit-function-declarationを削除することで暫定対応できます。

なお、これはIssue2067 mingw broken compilation (error on implicit-function-declaration) によるとMinGW側のバグだそうなので、MinGWを修正してしまう対応を採るのであれば、このissueのリンク先にパッチがあります。

 

構造体の変更

これが一番対応が大変なのですが、AVFilterPicAVFilterLinkが変更されていてそのままではコンパイルできません。AVFilterPicは構造体名の変更、AVFilterLinkはメンバ変数名の変更などがありました。関係するコミットログを抜粋して下に載せておきます。

------------------------------------------------------------------------
r24284 | stefano | 2010-07-17 19:44:14 +0900 (土, 17  7月 2010) | 6 lines

Rename AVFilterPic to AVFilterBuffer.

The struct is going to be used for audio data as well, so the new name
is less misleading.

Patch by S.N. Hemanth Meenakshisundaram smeenaks AT ucsd DOT edu.
------------------------------------------------------------------------
r24732 | stefano | 2010-08-07 10:15:34 +0900 (土, 07  8月 2010) | 11 lines

Rename fields:

AVFilterLink.srcpic    ->  AVFilterLink.src_buf
AVFilterLink.cur_pic   ->  AVFilterLink.cur_buf
AVFilterLink.outpic    ->  AVFilterLink.out_buf

The new names are more generic and more consistent, since the struct
they contain, which was named AVFilterPicRef, has been renamed to
AVFilterBufferRef.

Patch by S.N. Hemanth Meenakshisundaram %smeenaks%ucsd%edu%.
------------------------------------------------------------------------
r24763 | stefano | 2010-08-11 20:06:04 +0900 (水, 11  8月 2010) | 9 lines

Separate video specific BufferRef properties into VideoProps.

Define a new struct AVFilterBufferRefVideoProps and add a type field
to AVFilterBufferRef.

Video specific properties in AVFilterBufferRefVideoProps are now
referred to by *video pointer in AVFilterBufferRef.

Patch by S.N. Hemanth Meenakshisundaram smeenaks->ucsd.edu.

« 2010年8月 | トップページ | 2010年10月 »

other sites

  • follow us in feedly
  • github
  • stackoverflow

ソフトウェアエンジニアとして影響を受けた書籍

  • Christain Bauer: HIBERNATE イン アクション

    Christain Bauer: HIBERNATE イン アクション
    理論と実践が双方とも素晴らしい製品であるHibernate。本書はそのプロダクトを書名に冠していますが、Hibernateを使うつもりがなく、ORマッピングの解説書として読むにしても十分な良書です。Second EditionとしてJava Persistence With Hibernateという書籍も出版されていますが、残念ながら現在のところ 和訳はされていません。-インアクションは2.xの、Java Persistence-は3.1の頃のものなので、最新版とはちょっと違うところもあることに注意。 (★★★★★)

  • アンドリュー・S・タネンバウム: 分散システム 原理とパラダイム 第2版

    アンドリュー・S・タネンバウム: 分散システム 原理とパラダイム 第2版
    クライアント/サーバシステムを構築する上で必要となる知識が総論されてます。Web技術者も、フレームワーク部分を開発するのであれば必読。 (★★★★★)

  • Joel Spolsky∥著: ジョエル・オン・ソフトウェア

    Joel Spolsky∥著: ジョエル・オン・ソフトウェア
    前述の書籍「ソフトウエア開発プロフェッショナル」をより砕いたもの、という感じでしょうか。 前書きではプログラマでなくSE向けの本のように書かれているが、プログラマが読んでも面白い本であると思われます。 SEになった新人(あるいはそういう会社に入る/入りたての人)にとっては、これからどういったことが仕事を遂行していく上で起こりえるのか、どのように考えて行なっていけばいいのか決定する助けになると思います。 元は″Joel on Software″というブログの記事で、web上でも一部日本語で読めます。 http://japanese.joelonsoftware.com/ (★★★)

  • ドナルド・C・ゴース,ジェラルド・M・ワインバーグ: ライト、ついてますか

    ドナルド・C・ゴース,ジェラルド・M・ワインバーグ: ライト、ついてますか
    問題解決(一昔前のの流行語で言うところの『ソリューション』)能力は、システムエンジニアのスキルとして備えるべきもののうちのひとつです。しかし、これは難しい。学校で出されるテストと違い、唯一の、(問題提出者が想定している)解を求めるだけが「問題解決」では無いからです。そもそも、何が問題なのか、それは本当に問題なのか、それは本当に解決すべき問題なのか、その問題解決方法は正しいのか、などを解決しなければ、「その解は正しいのか」に辿りつくことができません。この本の最も良いところのひとつは、本があまり厚くないこと。すぐに読めるし、何回も読み返す気になるでしょう。 (★★★★★)

  • スティーブ・マコネル: ソフトウエア開発プロフェッショナル

    スティーブ・マコネル: ソフトウエア開発プロフェッショナル
    コードコンプリートで有名なスティーブマコネルの著書。新人SEに読んで欲しい。個人として業界の中でどうあるべきか、組織としてどうあるべきか、SEのプロ意識とは?SEの心構え概論、といったところでしょうか。また、業界における資格の重要性についても説かれています。この業界では資格が特に軽んじられる傾向がありますが、この傾向はどんな弊害をもたらすのか、将来的にこの業界は資格に対してどのような姿勢で臨んでいくべきなのか。日経BP社では(他の出版社もだが)最近、似たような類いのあまり面白くない書籍が乱出版されていますが、この本は別格だと思うので安心して購入して欲しいと思います。 (★★★★★)

無料ブログはココログ