2007-09-11
■[DirectX][XNA]Gamefest Japan 2007, Runtime Library
Gamefest Japan 2007,申し込んでたのに忙しくて行けませんでした……
でまああちこちの報告を見ながら「ええのぅ」と思ってるわけですが……ちょっと気になる点もいくつか.
Xbox LIVE アーケードでリリースされたタイトルはマーケットプレースから購入しただけで即プレイ可能だが、そうではないアマチュアが作成したXNA GSベースで開発したゲームをプレイするのがかなり面倒であることが改善されていない。
まず、PCが必要で、そのPCにC#環境とXNA環境をインストールして、初めてネット等からダウンロードしたゲームが実行可能になる。ゲームがどんなにカジュアルでわかりやすい内容であっても、ゲームが遊べるようになるまでのプロセスがヘビーなのだ。ランタイムが再配布できれば、Windows環境下で一発単体実行というのも可能なのだが。
西川善司の3Dゲームファンのための「XNA Game Studio 2.0」講座 XNA2.0でXbox LIVE アーケードデビューするまでの道のりは?
西川さん,もしかして XNA Framework の再配布ファイルが公開されていることに気づいてない?
ということはその辺の話は全然なかったのかなー
ついでに思い出したんですが,開発者に D3DX 等の DLL を起動時チェックを実装するよう,いい加減 Microsoft から働きかけて欲しいような.Gamefest みたいなイベントは良い機会だと思うんですけどねぇ.
ブートストラップを工夫するなり DLL の遅延ロードなりでこのエラーを潰しておかないと,このダイアログを読んでユーザーが意味を理解できるわけないでしょうと.Raymond Chen も同じことを言うと思います.
過去のエントリ
2007-09-02
2007-09-01
■[.NET]One-liner 言語としての C# 3.0 はきっとその域に達している
id:siokoshou:20070901#p2 がおもしろかったので C# コンパイラのメソッドルックアップをチェックするコードを書いてみました.
(from mi in new MethodInfo[]{ Reflector.Function<string>.Bind((Base _b, string _s) => () => _b.Method(_s)), Reflector.Function<string>.Bind((Derived _d, string _s) => () => _d.Method(_s)), Reflector.Function<string>.Bind((Hoge _h, string _s) => () => _h.Method(_s)) } let paramTypeStrs = from pi in mi.GetParameters() select pi.ParameterType.ToString() let paramStr = paramTypeStrs.Aggregate( (accum, next) => accum + " -> " + next ) select mi.DeclaringType + "." + mi.Name + " : " + paramStr + " -> " + mi.ReturnType).ToList().ForEach(Console.WriteLine);
嘘ですごめんなさい.普通に書くならこんな感じ.id:NyaRuRu:20070826:p2 で書いた Strong-typed reflection も再掲.
using System; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Collections.Generic; public class Program { public static void Main() { var funcs = new MethodInfo[] { Reflector.Function<string>.Bind((Base _b, string _s) => () => _b.Method(_s)), Reflector.Function<string>.Bind((Derived _d, string _s) => () => _d.Method(_s)), Reflector.Function<string>.Bind((Hoge _h, string _s) => () => _h.Method(_s)) }; var seq = from mi in funcs let paramTypeStrs = from pi in mi.GetParameters() select pi.ParameterType.ToString() let paramStr = paramTypeStrs.Aggregate((accum, next) => accum + " -> " + next) select mi.DeclaringType + "." + mi.Name + " : " + paramStr + " -> " + mi.ReturnType; // (追記) 上の文字列連結はこちらの方がベター? // let paramStr = String.Join( " -> ", paramTypeStrs.ToArray() ) seq.ToList().ForEach(Console.WriteLine); Console.ReadKey(); } } public class Base { public virtual string Method(string s) { return "Base.Method(string)"; } } public class Derived : Base { public override string Method(string s) { return "Derived.Method(string)"; } public virtual string Method(object o) { return "Derived.Method(object)"; } } public class Hoge { public string Method(string s) { return "Hoge.Method(string)"; } public string Method(object o) { return "Hoge.Method(object)"; } } public static class Reflector { static MethodInfo GetMethodInfo(this Expression expression) { var findfunc = null as Func<Expression, MethodInfo>; findfunc = expr => { switch (expr.NodeType) { case ExpressionType.Lambda: return findfunc((expr as LambdaExpression).Body); case ExpressionType.Quote: return findfunc((expr as UnaryExpression).Operand); case ExpressionType.Call: var mce = expr as MethodCallExpression; return mce != null ? mce.Method : null; case ExpressionType.MemberAccess: var me = expr as MemberExpression; var pi = me.Member as PropertyInfo; return pi != null ? pi.GetGetMethod(true) : null; default: return null; } }; return findfunc(expression); } public sealed class Function<TResult> { public static MethodInfo Bind( Expression<Func<Expression<Func<TResult>>>> expr) { return expr.GetMethodInfo(); } public static MethodInfo Bind<TArg0>( Expression<Func<TArg0, Expression<Func<TResult>>>> expr) { return expr.GetMethodInfo(); } public static MethodInfo Bind<TArg0, TArg1>( Expression<Func<TArg0, TArg1, Expression<Func<TResult>>>> expr) { return expr.GetMethodInfo(); } public static MethodInfo Bind<TArg0, TArg1, TArg2>( Expression<Func<TArg0, TArg1, TArg2, Expression<Func<TResult>>>> expr) { return expr.GetMethodInfo(); } } public sealed class Function { public static MethodInfo Bind<TArg0>( Expression<Func<TArg0, Expression<Action>>> expr) { return expr.GetMethodInfo(); } public static MethodInfo Bind<TArg0, TArg1>( Expression<Func<TArg0, TArg1, Expression<Action>>> expr) { return expr.GetMethodInfo(); } public static MethodInfo Bind<TArg0, TArg1, TArg2>( Expression<Func<TArg0, TArg1, TArg2, Expression<Action>>> expr) { return expr.GetMethodInfo(); } public static MethodInfo Bind<TArg0, TArg1, TArg2, TArg3>( Expression<Func<TArg0, TArg1, TArg2, TArg3, Expression<Action>>> expr) { return expr.GetMethodInfo(); } } }
LINQ 構文でだらだらと書いて改行潰せばワンライナーなので,それなりにその域には達しちゃった言語なのかもしれません.まあ LISP みたいなのは別格としても,C あたりの構文からスタートして,よくぞここまで練り上げた,と.
LINQ 構文のために大量に簡約ルールを追加したのもありますが,裏方サポートとして,id:NyaRuRu:20070827:p2 で書いたように「式」が増えたのと,Extension Method の導入によって method chain が楽になったのも大きいかな.
とはいえ,コマンドラインから直接叩くことを考えると,C# では参照設定や using 前提なのが邪魔だったりするのかも.
2007-08-28
■[Vista]MMCSS とネットワークパケット受け取りの抑制
Vista のファイルコピーが遅い件について に,Mark Russinovich 氏の最近のポスト,『Vista Multimedia Playback and Network Throughput』の件を追記.
簡単に要約しておくとこんな話です.
- Vista で Media Player を起動するとネットワークするープットが低下する件がネットで話題になっているが,Multimedia Class Scheduler Service (MMCSS) の影響という推測は正しい
- MMCSS は,10 msec ごとに最大 8 msec の間,Playback スレッドの優先度クラスを realtime range に引き上げる
- ネットワークパケットの受け取りは次の順序で行われる.これらの処理は,ユーザモードスレッドよりも高い割り込みレベルで実行されるため,スレッド優先度に関わらず優先される.
- 割り込みによる Deferred Procedure Call (DPC) のキューイング
- 割り込みレベルが DPC レベルでの,ドライバコールバック
- 高頻度でのネットワークパケットの受け取りは,容易に CPU 時間を食いつぶす
- このような高頻度でのネットワークパケットの受信が,Playback スレッドへの遷移を無視できないほど遅延させてしまうことが分かった.
- MMCSS では,Playback スレッド使用時に,NDIS ドライバを制御して,ネットワークパケットの受け取りに制限を持たせることにした.
- 制限値は 10 パケット/msec.Ethernet の標準的なパケットサイズ 1500 byte では,理論値約 15 MB /sec ということになる
- 複数のネットワークアダプタが存在するときに,パケット数の受け取り上限がさらに低下する.(これはバグという扱いらしい)
- 2 つのネットワークアダプタが存在すると,(1 枚あたり?) 8 パケット/msec
- 3 つのネットワークアダプタが存在すると,(1 枚あたり?) 6 パケット/msec
- 受け取りパケット数はパフォーマンスカウンタの "packets received per second" で見ることができる
関連記事
2007-08-27 c:¥TMP
■イルカは工場で生産された.後の神である.
一万年後の考古学者が,「なぜこの世界でイルカは神なのだろう?」という謎を解くためにタイムマシンに乗ってやってきて,アクションとラブロマンスの末,ついに MS Office と出会うという話を考えた.
というかアノ言及せずにはいられない感が既にヤバい.人はイルカを畏れている.
■[.NET]全てが E になる
C# 3.0 におけるルール E の存在.
ジェットコースターのような先週,私は一足先に解答編を聞いてしまったのですが.
言われてみればとてもシンプルなルール.いやほんと,波村さんに言われるまで全然気づきませんでした.
var x = new MyClass() { ID = 123 }; var y = new List<MyClass>() { new MyClass(){ID = 1}, new MyClass(){ID = 2} }; var z = new { ID = 1, Name = "Foo" };
記法が変? 必要な理由が分からない?
全てはルール E の必然.S では駄目だった.だから E.
static void Main(string[] args) { Expression<Func<int, IEnumerable<List<MyClass>>>> expr = X => from Y in Enumerable.Range(0, X) from Z in Enumerable.Range(X, Y) select new List<MyClass>() { new MyClass{ID = X}, new MyClass{ID = Y}, new MyClass{ID = Z} }; Console.WriteLine(expr.ToString()); }
X => Range(0, X).SelectMany(Y => Range(X, Y), (Y, Z) => new List`1() {Void Add(MyClass)(new MyClass() {ID = X}), Void Add(MyClass)(new MyClass() {ID = Y}), Void Add(MyClass)(new MyClass() {ID = Z})})
うーん,『C# 3.0を256倍使うための本 邪悪編』書きたくなってきたかも.需要は皆無に見えますけど.
内容は邪悪な型推論とか邪悪な partial の使い方とかとか邪悪なメタプログラミングとか.とにかく邪悪な方向で.