HIDORI on The Web

マネージコードしか書きたくない

RE: BUILD での注目点

with one comment

ネタ元: BUILD での注目点 « ++C++; // 未確認飛行 C ブログ

BUILD 面白そう (^o^)

早くも、Windows 8 は Windows 7 よりも良いものになりそうな予感。

ということで、以下、Iネタ元読んでて思ったことなどなど。

ISO イメージのマウント

ISO イメージのマウントは、Windows 7 時点でそれっぽい API が定義されていました。

この API は、API 引数でイメージの種類(=.iso, .vhd など)を指定する仕様でしたが、Windows 7/Windows Server 2008 R2  でちょっと試した範囲では、.iso イメージマウントに関しては期待通りの動作をしてくれませんでした。

Windows 7/Windows Server 2008 R2 時点では「API 的には整備されているけど、実際にはその背後でうごめくプロバイダが提供されていなくて、結局のところ利用不可」てことだった模様。

ちなみに、Widnows 8 での ISO イメージマウントがこの API によって可能となるのかなどは現時点では不明(だよね?)

Protogon ファイルシステム

ファイルシステムがより多くのメタ情報を持つこと自体はいいことなんだけど、相互運用どーするかもちゃんと考えてねと。

かつて、WinFS のデモが盛んに行わていた時代に、演者に「マシン間でファイルをコピーしたらメタ情報は落ちちゃうの?」と何度か質問をしたことがあるけど、結局、真正面から答えてくれた人はひとりもいなかった。たまたまかもしれんけど ;-p

Windows 7 の「ライブラリ」は大好きな機能だけど、これも結構制約が多い(=Linux ベースの NAS のフォルダなんかは事実上追加できなかったりする)のが難点。

あまり先取りしすぎないように気をつけてください。

Windows Live ID と、クラウドを使った設定の同期

Windows Live Mesh で一部できてるけど、これをもっと推し進める感じかな?

AD と共存できるといいんだけど…

Trident

IE のレンダリングエンジンは IE4 あたりからずーっと Trident って名前だったはず。

Visual Studio 2012

公式にはまだ製品名決まってないはず。

でも、「製品名に 2013 を冠するはずはない」と信じてるwので、2012 年(年度?)中にどばっと、いろいろ製品が出てくるはず。

Written by Hiroaki SHIBUKI

9月 13th, 2011 at 1:17 am

Posted in イベント

Tagged with , ,

[C#] LINQ to SQL の実行速度を3倍に加速するっ!

without comments

どーも最近、ダメな子扱いされがちな LINQ to SQL ですが、クエリ結果を(ほぼ)透過的にキャッシュすることで実行速度を約3倍に加速してみました。

使い方はひじょーにカンタン。

通常

var connectionString = Properties.Settings.Default.Database1ConnectionString;

using (var db = new DataClasses1DataContext(connectionString))
{
    var array = db.Products.Where(__ => __.Price > 500).OrderBy(_ => _.Price).Take(200).ToArray();
}

みたいに書くところを

var connectionString = Properties.Settings.Default.Database1ConnectionString;

using (var connection = new Mjollnir.Data.SqlClient.SqlConnection(connectionString, new MemoryCache()))
using (var db = new DataClasses1DataContext(connection))
{
    var array = db.Products.Where(__ => __.Price > 500).OrderBy(_ => _.Price).Take(200).ToArray();
}

のように、データベース接続を別クラスに差し替えるだけ。

実際には少しばかりの準備(=プロジェクトに上記 SqlConnection の代替えクラスおよび SqlCommand の代替えクラス、キャッシュ実装クラスを追加)は必要だけど、クエリの記述や結果の扱いに変更を加えないで済むのがミソ。

これでどれくらいのパフォーマンス向上があるかとゆーと…

Id int
Name nvarchar(100)
Price int

とゆー構成で1000項目が登録されたテーブルに対して

private static IEnumerable
 ExecuteQuery(DataClasses1DataContext db, int queries)
{
    var list = new List
();

    for (int i = 0; i < queries; i++)
    {
        list.Add(db.Products.Where(__ => __.Price > 500).OrderBy(_ => _.Price).Take(200).ToArray());
    }

    return list;
}

とゆータスク(queries = 10 に設定)を100件連続して実行した場合の実行時間は以下のとおり。

  1回目 2回目 3回目 4回目 5回目
通常の LINQ to SQL 5.453s 3.693s 2.811s 2.84s 2.827s
LINQ to SQL + サンプルキャッシュ実装 0.942s 0.909s 0.906s 0.909s 0.906s

てなカンジ。

概ね3倍のパフォーマンス向上が見られるのでありました。

↑と同じ設定のタスクを ThreadPool を使って同時並行に実行すると

  1回目 2回目 3回目 4回目 5回目
通常の LINQ to SQL 0.964s 0.972s 0.976s 1.004s 0.987s
LINQ to SQL + サンプルキャッシュ実装 0.277s 0.271s 0.27s 0.288s 0.269s

とゆー結果。あれ?思ったほど伸びてない (^^;

実行時間そのものはマルチスレッド化によって短縮されているものの、「約3倍のパフォーマンス向上」てとこには変化ナシ…

サンプルではローカルのファイルアタッチ DB を相手にしているので、そのせいかな?

ネットワーク接続の DB なら、キャッシュヒットした時の利益はひとしおなので、もうちょっと差が出るハズ。

ところで、実は「LINQ to SQL のパフォーマンスを向上する」のであれば

  • CompiledQuery を利用する
  • 結果セットをキャッシュする

のが定番コース。

なのに、なんでわざわざこんな風変わりなアプローチをしているのかとゆーと…

↑で挙げた代表的な2つの手法には

  • クエリ実行のコードの書き換えが必要(=透過的でない)
  • SqlDependency によるキャッシュエントリの効率的なエクスパイアを実行しづらい

という短所があるから。

前者は(必要なら)我慢するとしても、後者はもうちょっとどーにかしたいところ。

で、今回採用した「LINQ to SQL の DataContext に、DbConnection.CreateCommand() で DbCommand.ExecuteReader メソッドの処理を外部に移譲する DbCommand 派生クラスインスタンスを返す DbConnection 派生クラスインスタンスを渡す(長っ)」という手法なら

  • DataContext を new する時のコードをホンの少し書き換えるだけ
  • 結果セットのキャッシュを SqlCommand 相当のクラス内で行うので、SqlDependency を容易に扱える

となるワケ。(SqlDependency を使ったキャッシュ実装はまだ作ってないけど (^^;)

あと、LINQ to SQL のクエリ結果と違って、この層なら結果セットに含まれる値の型はごくシンプルなモノばかりなので

LINQ to SQL のクエリ結果を分散ストレージにキャッシュする

なんてことも理論的には可能だったりする。

てか、実のところ、今回の投稿はそれを検討するため下地だったりなんかして (^^;

なお、サンプルプロジェクトは VS2010 で作ったけど、ターゲットは .NET3.5SP1 なので、ソースファイルを抜き出してプロジェクトを再構成すれば VS2008 でも動作するはず。

Written by Hiroaki SHIBUKI

2月 3rd, 2011 at 2:40 am

Posted in 技術情報

Tagged with

PowerShell でジェネリックメソッドを呼び出す

with one comment

PowerShell の長所の一つとして「.NET Framework との親和性が高い」ことが挙げられるわけですが、いかんせんジェネリックメソッドの呼び出しはちょとシンドイ。

というわけで、ジェネリックメソッド呼び出しのメンドクサさを隠蔽すべく

Param(
    [Parameter(Mandatory=$True, HelpMessage="ジェネリックメソッドを公開する型を指定します。")]
	[ValidateNotNull()]
	[Type] $Type,

    [Parameter(Mandatory=$True, HelpMessage="ジェネリックメソッドの名前を指定します。")]
	[ValidateNotNullOrEmpty()]
	[String] $MethodName,

    [Parameter(Mandatory=$True, HelpMessage="ジェネリック型パラメータに与える Type 型の配列を指定します。")]
	[ValidateNotNullOrEmpty()]
	[Type[]] $GenericArgumentTypes,

    [Parameter(HelpMessage="ジェネリックメソッド呼び出しの対象となるオブジェクトインスタンスを指定します。")]
	[Object] $Object = $Null,

	[Parameter(HelpMessage="ジェネリックメソッド呼び出しの引数となる Object 型の配列を指定します。")]
	[ValidateNotNull()]
	[Object[]] $ArgumentList = @())

Trap { break }

$MethodInfo = $Type.GetMethods() |
    Where-Object {$_.Name -eq $MethodName} |
    Where-Object {$_.IsGenericMethod} |
    Where-Object {$MethodInfo.GetGenericArguments().Length -eq $GenericArgumentTypes.Length} |
	Select-Object -First 1

$GenericMethodInfo = $MethodInfo.MakeGenericMethod($GenericArgumentTypes)

$GenericMethodInfo.Invoke($Object, $ArgumentList)

なんてスクリプトを書いてみた。

使い方は

Invoke-GenericMethod.ps1 -Type Linq.Enumerable -MethodName Repeat -GenericArgumentTypes Int32 -ArgumentList @(9,4)

みたいな感じ。

これは、C# の

Enumerable.Repeat<int>(9, 4);

に相当。

ちょっと引数が多いけど、汎用的に仕上げたかったのでこんなモンでしょう。

必要に応じて

Function EnumerableRepeat([Int32] $Element, [Int32] $Count)
{
    Invoke-GenericMethod.ps1 -Type Linq.Enumerable -MethodName Repeat  -GenericArgumentTypes Int32 -ArgumentList @(9,4)
}

みたいなラッパ関数を書くってのも手。

Written by Hiroaki SHIBUKI

1月 17th, 2011 at 12:08 am

「RSS 配信」をしばらく休止します

without comments

Web 移転にともない、http://hidori.jp/rss/ でサービスしている開発系掲示板の「RSS 配信」がしばらくの間、全面的に停止します。

ホスティングサーバ上で動作するように改訂が必要なので、再開にはかなり時間がかかりそうです。

# RSS のリクエスト URL は維持する方向で努力します。

Written by Hiroaki SHIBUKI

8月 15th, 2010 at 4:00 pm

Posted in おしらせ

Web サーバーを移転しました

without comments

ながらく自宅サーバーで hidori.jp ドメインの Web サーバーを運用してきましたが、データジャパンが運営するホスティングサービス ExpressWeb に移転しました。
まだ WordPress を入れただけなので、ぼちぼち整備していきたいと思います。

Written by Hiroaki SHIBUKI

8月 15th, 2010 at 3:00 pm

Posted in おしらせ

文字列の中から数字だけ取り出すには?

without comments

ネタ元: 文字列の中から数字だけ取り出すには?

文字列に含まれた複数の数字列を取り出して連結。

もっと簡潔に…書けるかなぁ?


using System;
using System.Linq;
using System.Text.RegularExpressions;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            string text = "あ1いう3え4お56789";

            Console.WriteLine(
                string.Concat(Regex.Matches(text, @"\d+").Cast().Select(_ => _.Value).ToArray()));
        }
    }
}

追記: 2010-06-04

Twitter でいくつかフィードバックを貰ったので、再考。

正規表現を使ってないので、この系統の方が性能的には有利なはず。

でも、char[] から string を得るのに string(char []) を使っているところが、ワンライナー的には許せないw

using System;
using System.Linq;
using System.Text.RegularExpressions;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            string text = "あ1いう3え4お56789";

            Console.WriteLine(
                new string(text.Where(_ => char.IsDigit(_)).ToArray()));
        }
    }
}

さらに追記: 2010-06-04

お題を消化するだけならコレが最強w

^ による否定をすっかり忘れてたヨ…

あーんど、なんでもかんでも LINQ ろうと思ってはいけないね (^^;

using System;
using System.Text.RegularExpressions;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            string text = "あ1いう3え4お56789";

            Console.WriteLine(
                Regex.Replace(text, @"[^\d]", string.Empty));
        }
    }
}

Written by Hiroaki SHIBUKI

6月 4th, 2010 at 10:37 am

Posted in 技術情報

Tagged with ,

0 から 1000 までに含まれる ‘0’ を数える

without comments

ネタ元: gist: 415551 – from http://d.hatena.ne.jp/os0x/20081115/1226770265- GitHub

Sum() しない版。

足し算で「個数を求める」のではなく、「数える」という点を強調したつもり。

あと、ネストをするとラムダ式の引数の名前考えるのがめんどくさい (^^; ので、SelectMany() を使って、早い段階でフラットな IEnumerable に変換してしまっているのもミソ。

using System;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(
                Enumerable.Range(0, 1001).SelectMany(_ => _.ToString()).Count(_ => _ == '0'));
        }
    }
}

Written by Hiroaki SHIBUKI

5月 27th, 2010 at 6:16 pm

Posted in 技術情報

Tagged with ,

勝手に競演

without comments

ネタ元: 夢の競演みたび

そのままだと面白くないので、複数除外できるようにしてみた。

簡素さを優先するとこんな感じ。excludes を何度も舐めるのが美しくないけど。

result を何度も列挙するような場合、result.ToArray() すればいいよね。

1回しか回さないなら、これでおk。

using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var source = new[]
            {
                new { Name = "しゅうたん",   Type = "アメショ" },
                new { Name = "ろり",         Type = "アメショ" },
                new { Name = "みずきちゃん", Type = "スコティ" },
                new { Name = "マグさん",     Type = "ほげ" },
                new { Name = "?",           Type = "もげ" },
            };

            var excludes = new[] { "ほげ", "もげ" };

            var result = source.Where(_ => !excludes.Contains(_.Type));

            foreach (var item in result)
            {
                System.Console.Out.WriteLine("Name = {0}, Type = {1}", item.Name, item.Type);
            }
        }
    }
}

Written by Hiroaki SHIBUKI

5月 27th, 2010 at 12:38 am

Posted in 技術情報

Tagged with ,

【緩募】イベントのエレガントな発火

with 2 comments

Name プロパティの変更を通知するイベントの場合、イベント発火は通常

// Name プロパティが変更されたことを通知します。
public event EventHandler NameChanged;

// NameChanged イベントを発火します。
protected void OnNameChanged()
{
    if (this.NameChanged != null)
    {
        this.NameChanged(this, new EventArgs());
    }
}

なんてしておいて

this.OnNameChanged(); // NameChanged イベントを発火

とするのがお定まりなワケですが、この OnNameChanged() をもうちっとばかり美しく書きたいわけデス。

とりあえず

// 指定されたイベントを発火します。
public static void Fire(this EventHandler eventHandler, object sender)
{
     if (eventHandler != null)
     {
         eventHandler(sender, new System.EventArgs());
     }
}

// 指定されたイベントを発火します。
public static void Fire<TEventArgs>(this EventHandler<TEventArgs> eventHandler, object sender, TEventArgs eventArgs) where TEventArgs : EventArgs
{
     if (eventHandler != null)
     {
         eventHandler(sender, eventArgs);
     }
}

てな拡張メソッドを用意して

// NameChanged イベントを発火します。
protected void OnNameChanged()
{
    this.NameChanged.Fire(this);
}

なんて感じに書けるようにはしてみました。

これだと、sealed なクラスでは

public string Name
{
    get { return this.name; }
    set { this.name = value; this.NameChanged.Fire(this); }
}

てな感じで OnXXX() とオサラバすることもできて、なかなかイイ感じです。

んが、これだと EventHandlerEventHandler<TEventArgs> にしか対応出来ないところが微妙デス。

このままでは、例えば PropertyChanged イベントみたいなイベントデリゲートが定義済みのイベントには通用しなかったりするわけです。

PropertyChanged イベントはマイブーム(笑)なので、特別に

// 指定されたイベントを発火します。
public static void Fire(this PropertyChangedEventHandler eventHandler, object sender, PropertyChangedEventArgs eventArgs)
{
     if (eventHandler != null)
     {
         eventHandler(sender, eventArgs);
     }
}

てのも書いちゃったけど、XXXEventHandler が登場する度に専用の Fire() を書くなんてのはやってらません ;-p

なんかいいアイデア無いでしょうか?

Written by Hiroaki SHIBUKI

4月 23rd, 2010 at 11:17 pm

Posted in 未分類

XBOX360: Borderlands

without comments

久々に XBOX360 の新作をやってみた。

今回やってみたのはコレ。

Borderlands
http://www.xbox.com/ja-JP/games/b/borderlands/ 

「RPG と FPS の融合」という煽り文句に期待と不安 (^^; を抱きつつ起動。

海外タイトルの日本語版ということで、もっとバタ臭い絵柄かと思ってたけど、意外とあっさりめな感じで好感触。

「あっち系」のテイストは残したまま、日本のアニメっぽい雰囲気もありつつで、ざっくり言うと海外版の「AKIRA」みたいな感じかな?

ゲームの世界観は「マッドマックス」や「北斗の拳」系の「荒野+パンクな悪者」という組み合わせ。(+ほんの少しサイバー?)

とりあえずチュートリアル兼の1面だけやってみたけど、最初、何をどーすればいいかよく分からなかった (^^;

行き先はパートナーのロボットが教えてくれるし、コントローラの操作もヘルプがあるんだけど、「何が拾えるのか」とか「どこに出入口があるのか」なんてのが分かりにくいと感じた。日本製のヌルイ RPG とかやってる報い???

確定申告も終わったことだし、しばらくやりこんでみよっと ;-)

Written by Hiroaki SHIBUKI

3月 17th, 2010 at 10:40 am

Posted in ゲーム

Tagged with