++C++; // 未確認飛行 C ブログ

http://ufcpp.net/

Archive for 4月 2014

Singleton

leave a comment »

こないだ見かけた話題。

singletonといえば?

SingletonList

Roslynのコード中に、こんなメソッドがあるみたいです。

/// <summary>
/// Creates a singleton list of syntax nodes.
/// </summary>
/// <typeparam name=”TNode“>The specific type of the element nodes.</typeparam>
/// <param name=”node“>The single element node.</param>
/// <returns></returns>
public static SyntaxList<TNode> SingletonList<TNode>(TNode node) where TNode : SyntaxNode
{
return new SyntaxList<TNode>(node);
}

場所はここ。

http://roslyn.codeplex.com/SourceControl/latest#Src/Compilers/CSharp/Source/Syntax/SyntaxFactory.cs

Singletonパターン

プログラミングの分野では、singletonっていうと、プログラム稼働中にただ1つしかインスタンスがないもののことを指す場合が多いわけですが。singletonパターン(その、インスタンスの唯一性を保証するためのパターン)が有名なので。

ところが、上記のコードは見ての通り、メソッドを呼び出すたびに新しいインスタンスを作って返していると。それで、「どうしてsingletonじゃないのに名前にsingletonって入ってるの?私のsingletonの理解が間違ってる?」みたいな話が。

集合論のsingleton

まあそりゃ、そのsingletonじゃないから。

上記コードのsingletonは、集合論で使われる数学用語。日本語訳だと単集合になってるみたい。ただ1つの元からなる集合。

数学って、極力少ないルール(公理、証明不可能な最低限の決め事)を使ってより多くの結果を導けることが、理論の「よさ」の1つの指標になります。特に集合論は現代数学の基礎中の基礎なので、ものすごいシンプルなルールしか持っていません。例えば以下のような。

  1. 集合xとyの対 {x, y} を作れる
  2. 含まれる要素が全て等しいとき、2つの集合が等しいと判定する
  3. 自分自身を含む集合は認めない

ここで、1番目のルールから、同じ集合、xとxの対 {x, x} も作れます。ところが、2のルールを見ての通り、集合は含まれている要素の有無だけを見て等価判定するので、要素の重複を区別できません。結果的に、{x, x} と {x} は同じ集合ということになります。

で、x から {x} という集合を作れたわけですが、3のルールから、{x}、つまり、「xだけを含む集合」はxではないということになります。この、xから作った、xを1つだけ含む集合がsingletonになります。

上記コードはどう見てもsingleton(nodeを1つだけ含むSyntaxNodeを作った)なわけです。

+1

少々余談になりますが、この意味(集合論上の)singletonの利用場面を1つ。

集合論では、少ないルールから出発してる手前、ちょっとした操作をするのにも一工夫必要になったりします(動機としては逆で、ルールを減らすために工夫してる)。

例えば、自然数の構築。自然数を作るには「ある数よりも1つ大きい数が作れる」みたいなルールが必要になりますが、集合論的には以下のようにして「+1」を作ります。

  • ある集合xと、そのsingleton {x}の和集合x∪{x}を作る

ちなみにこのためには、先ほどのルールに加えて、以下の2つのルール(公理)も必要。

  1. 要素を持たない集合{} が存在する(空集合)
  2. 2つの集合x, yの両方の元を持つ別の集合 x∪y が作れる(合併集合)

要素を持たない集合(空集合)を0扱いして、以下、

  • 1 = 0∪{0} = {}∪{0} = {0}
  • 2 = 1∪{1} = {0}∪{1} = {0, 1}
  • 3 = 2∪{2} = {0, 1}∪{2} = {0, 1, 2}
  • 4 = 3∪{3} = {0, 1, 2}∪{3} = {0, 1, 2, 3}

みたいな感じで「+1」していきます。

だからといって、singleton?

singletonなことはわかった。でも、その名前どうなの?

「singletonパターンと紛らわしいから」って理由もなくはないんですけども、どちらかというと、汎用性に欠けるから。

なんというか例えば、以下のようなメソッドもあるわけじゃないですか(この例はSystem.Concoleクラスからとってきたもの)。

public static void Write(string format, object arg0);
public static void Write(string format, object arg0, object arg1);
public static void Write(string format, object arg0, object arg1, object arg2);
public static void Write(string format, params object[] arg);

引数が1つだけのもの、2つだけのもの、3つのもの、そして、配列で任意の長さの引数を渡せるもの。これとの類推で行くなら、以下のような名前でもいいわけです。

public static SyntaxList<TNode> List<TNode>(TNode node) where TNode : SyntaxNode
public static SyntaxList<TNode> List<TNode>(TNode node1, TNode node2) where TNode : SyntaxNode
public static SyntaxList<TNode> List<TNode>(TNode node1, TNode node2, TNode node3) where TNode : SyntaxNode
public static SyntaxList<TNode> List<TNode>(IEnumerable<TNode> nodes) where TNode : SyntaxNode

(ちなみに、4 つ目、つまり、IEnumerableを受け取るやつは、実際にListっていうメソッドがSyntaxFactory.cs内にあります。)

1つ目にSingletonListなんて名前を付けてしまったら、2つ、3つとなるたびに、Singleton, Doubleton, Tripleton, … みたいに名前つけるんですかね?みたいなことになってしまいます(もっとも、今回のRoslynのコード上、2つ、3つの場合を使う要件はないんで、別にこれでいいんですけども。名前自体が違う方が、引数を間違える人的ミスは減りますし)。

結果

  • いやいや、どう見てもsingletonだよ
  • singletonなんだけど、singletonって名前はどうなの?
広告

Written by ufcpp

2014年4月13日 at 01:47

カテゴリー: 未分類

ソースコード共有と#if

leave a comment »

いわゆるifdefコードの難しさ。

昨日、クロスプラットフォームな開発をしてる人から、「universal Windows apps の共有プロジェクトって、#if を正しく認識してるの?リネームとかのリファクタリング的な意味で」という疑問をいただいたので試してみた結果。

image

ダメでした。ええ、ダメでした(とりあえずConnectに登録済み)。

クロスプラットフォーム開発してて、どうしても#if/#elseするしかない場面ってごろごろあって、「動く」という意味では全然問題ないものの、こういうリファクタリングでいつも困るそうで。手元の環境で #if の対象になってない部分のコードで、どうしても修正ミスが残って、後から問題が発覚するという。

Written by ufcpp

2014年4月12日 at 19:15

カテゴリー: .NET

RyuJIT SIMD対応

leave a comment »

なんか週明けてからもブログが。

//build/で出てた、RyuJIT CTP3のSIMD対応の話の詳細。あと、SIMD命令ってのが何なのかっていうそもそもの説明付き。

Written by ufcpp

2014年4月8日 at 23:17

カテゴリー: .NET

C# before/after

leave a comment »

//build/ のセッション、やっとお目当てにあたりは見れたかなぁ。

The Future of C#」のデモが、Roslyn使ったVisual Studio拡張とか次期C#の新機能紹介とかまとまっててよさげ。

で、このデモ中のコードが新機能紹介として優秀な感じだったので、before/after的に並べてみる。具体的にどういう文法なのかはこないだ書いたので今日は割愛。

(多少コードはいじってたり。いじった結果→ プロジェクト一式(ZIP圧縮))

左がC# 5.0、右が次期C#で書き直したもの。

image

image

image

Written by ufcpp

2014年4月6日 at 21:22

カテゴリー: C#

Universal Windows Apps

leave a comment »

ここ数日ブログに書いた話はCTP (Community Technology Preview: 要はアルファ版。リリース版は結構将来の話)なものばかりでしたが。

RC (Release Candidate: リリース間近。重大なバグフィックス除けばほぼそのままリリース)の話も1つ。

Visual Studio 2013 Update 2 RCを入れると、Windows Phone 8.1アプリの開発ができるようになります。

Windows Phone 8.1アプリは、以下で説明していくような意味でWindows 8.1アプリと“同一アプリ”として開発できて、この仕組みを「ユニバーサル アプリ」(universal Windows apps)って呼びます。

ユニバーサル アプリ

Visual Studio上で、(ユニバーサル アプリ)と付いたプロジェクト テンプレートを使って新規プロジェクトを作るか、もしくは、Windows 8.1アプリに対して「Windows Phone 8.1の追加」、Windows Phone 8.1アプリに対して「Windows 8.1の追加」という操作をすると、プロジェクトが以下のような状態になります。

この状態のアプリを「ユニバーサル アプリ」と言うみたい。

ちゃんと、JavaScript版もC++/CX版もあります。

image

image

開発者視点で言うとポイントが4つくらい。

  1. WinRTの互換性向上、Windows 8.1とWindows Phone 8.1でほぼ共通のAPI化
  2. 共有プロジェクト(.shproj)が作れるようになった
  3. PCLの利便性が向上
  4. Win8.1/WinPhone8.1アプリは、Windowsストア上で同一アプリとして扱われる

ほぼ共通のAPI

ユニバーサル アプリといいつつ、実際のところ、胆となるのはWindows 8.1アプリとWindows Phone 8.1アプリのAPI統合みたい。要するに、共通して使える.NET標準APIとWinRT APIが実用レベルに増えた。

やろうと思えばXAMLとかも完全コピペで(後述する共有プロジェクト使えば単一ソースコードで)作れそうな程度には共通っぽい。

個別にXAMLを書くモチベーションは、画面サイズの違いによる再デザインくらい。「Phone版は画面はみ出てもいいや」とか「ViewBox使って単に拡大して画面サイズ合わせればいいや」とかくらいの適当なので良ければ、ほんとうに単一ソースコードで開発できそう(それでストア審査通るかは別として)。

共有プロジェクト

新しいプロジェクト タイプとして、共有プロジェクトができたみたい。上記のスクリーンショットで言うところの、HubApp1.Sharedプロジェクト。

このプロジェクト中に追加したファイルは、Windows 8.1用プロジェクト(HubApp1.Windows)とWindows Phone 8.1用プロジェクト(HubApp1.WindowsPhone)の両方に含まれている扱いを受けるようです。PCL (Portable Class Library)と違って、ライブラリDLLができるとかではなく、ソースコードやリソースがプロジェクト内に含まれるものとしてそれぞれをビルドします。

各ファイルを「リンクとして追加」するのとかPCLとかと比べて何が嬉しいかというと、以下のような感じ。

  • 画像リソースとかのアセットも含めて共有可能
  • XAMLとかリソースのパスが狂って参照できなくなる問題もない
  • #ifdefによる条件コンパイルなども利用可能
  • 管理が楽。個別のプロジェクト側と共有プロジェクト側の間で、D&Dでファイルを移すだけで 個別⇔共有 の切り替え可能

この共有プロジェクトの仕組みを普通に使えるのは、現状ではユニバーサル アプリのみみたい。ただ、ユニバーサル アプリの.csprojファイルの中身を参考にして、自分で.csprojファイルを書き換えれば他のプロジェクトでもファイル共有くらいはできそう(IntelliSenseとかが正しく動く保証がないけども)。

PCLの利便性向上

  • Visual Studio 2013 Express for Windows (無償版、Windowsストア アプリ開発用)からPCLプロジェクトを参照できるように
  • クラス ライブラリ(単一環境用)プロジェクトとPCLプロジェクトを一本化
    • ただし、現状Windowsストア用のみ
      • 「.NET Framework 4.5」のみなPCLは作れないみたい
    • つまり、PCLプロジェクトのターゲットを「Windows 8.1」のみ/「Windows Phone 8.1」のみに設定可能に
      • 代わりに、ターゲットが「Windows 8.1」のみ/「Windows Phone 8.1」のみなプロジェクト テンプレートは廃止
  • PCLプロジェクト内でWinRTを参照可能に
    • プロジェクト テンプレートで「クラス ライブラリ(ユニバーサル アプリ用ポータブル)」を選ぶと、WinRTが参照されてる状態のPCLができる
    • WinRT XAMLコントロールなんかもPCLとして作れるように

現状ではやたらと「Windowsストア用のみ」状態ですけども、「計画としては対応プラットフォームを広げていきたい」とのことらしいので今後に期待。

Windowsストア上では1つのアプリ扱い

上記スクリーンショットの通り、内部的には「2つのプロジェクトでソースコード共有」で、「パッケージ(appx)も2つ作られる」わけですが、これをWindowsストアに上げる際には1つのアプリとして扱ってもらえるそうです。

「1つ」ってのは、以下のような意味合い。

  • 同じアプリIDが割り当てられる
  • 課金の口が共通。有料アプリなら、片方で買えばもう片方でも使える
  • ローミング(OneDrive経由のデータ同期)が共通
  • プッシュ通知(Windows Notification Service)が共通

みんな、「※」と書いただけで「※ただし日本は除く」って意味にとってくれるのはどういうことなの。

Visual Studio 2013 Update 2 RCをインストールすると、Windows Phone 8.1のエミュレーターもついてくるわけですが。エミュレーターでアプリが動いても、実機が世の中に出回ってないことにはねぇ…

とりあえず、de:codeを期待して待っていればいいんでしょうか…

ちなみに、Visual Studio 2013 Update 2 RC自体は日本語対応済みです。各種プロジェクト テンプレート・項目テンプレートもちゃんと日本語。

Written by ufcpp

2014年4月6日 at 20:53

カテゴリー: .NET, C#

//build/ .NET関連

leave a comment »

//build/ のセッション動画・資料を眺め中。

あと、それ関連のブログとか。

.NET関連は、以下のセッションの資料の最後の方のまとめの表がなかなかによさげ。

↓それのコピペ。

Technology

Info

Download

JIT “RyuJIT”

http://aka.ms/RyuJITinfo

http://aka.ms/RyuJIT

SIMD

http://aka.ms/SIMDInfo

http://aka.ms/SIMD

.NET Compiler Platform

(“Roslyn”)

http://aka.ms/NETCompilerPlatform

http://roslyn.codeplex.com

http://aka.ms/NetCompilerPlatformDownload

.NET support on Azure Mobile Services

http://aka.ms/azuremobileservicesnet

http://aka.ms/VS2013Update2

ASP.NET Updates in VS 2014 Update 2

http://aka.ms/VS2013Update2Info

http://aka.ms/VS2013Update2

Universal Windows apps

http://aka.ms/universalprojects

http://aka.ms/VS2013Update2

.NET Native

http://aka.ms/dotnetnative

http://aka.ms/dotnetnativedownload

Xamarin

http://xamarin.com

http://xamarin.com

.NET Foundation

http://www.dotnetfoundation.org

na

Orleans

http://aka.ms/orleans

http://aka.ms/orleans

以下、いくつか補足。

Roslynのソースコードを試してみるなら

C#チーム/VBチームのブログで手順説明あり。

このブログは、上半分がEnd-User Preview(Visual Studio拡張)の説明で、下半分がソースコードがらみ。

ソースコードがらみのは、gitリポジトリのcloneの仕方から懇切丁寧に説明してる(ただ、記事中でgitのURLがhttpになってるけども、httpsにしないとcloneできない)。Anders Hejlsbergが//build/ day 2 キーノートでやってたみたいな文字列リテラル構文の書き換え(≪≫をパースできるようにする)のサンプルの説明付き。

注意点として、RoslynのビルドがRoslyn自体を使ってること。End-User Previewを入れてないとビルドできない。あと、VSIX(Visual Studio拡張)パッケージにビルドされるので、Visual Studio 2013 SDKも必要。作られたVSIXパッケージをインストールすれば、自分で書き替えた独自C#拡張がVisual Studioから使える状態に。

RyuJITのSIMD対応を試してみるなら

MSDN SamplesにSIMD用のサンプルコードがあるのでこちらを参照。

こちらの注意点は、RyuJIT CTP3だけ入れてもダメで、レジストリを書き換えないとSIMD対応が有効にならないこと。サンプル中に、レジストリ書き換えのbat(enable-jit.bat)が入っているので、サンプルを試してみる前にこのbatを実行しておく。

↑これをやっておかないと、ビルドできるし正常動作するけども、SIMD使われなくてまったく速くならない。ただ単に、Vector2f型とかが普通の.NETコードとして実行されるだけ(試しに自作してみた自前Vector型と全く同じ性能だった)。

SIMD対応はまだ不安定で、すべての.NETプログラムが動く保証がないそうなので、試した後はレジストリを戻さないと危険で、そのためのbatもある(disable-jit.bat)。

Written by ufcpp

2014年4月5日 at 20:32

カテゴリー: .NET, C#

C# vNext (Roslyn)での async/await の仕様変更

leave a comment »

そういえば。昔、こんな話題が。

これの「Lift Your Way out of Garbage Collection」の節のあたりに書いてあること。大まかにいうと、

  • 非同期メソッド内のローカル変数は全部フィールドに変更される
  • それが原因で、オブジェクトの寿命が延びてGC性能を多少落とす
  • 将来的に、このC#/VBコンパイラーの挙動は変更するかも

という内容。

今がその「将来」か?ということで、Roslynの新しいC#コンパイラーの生成結果をのぞいてみた。

元コード

以下のようなコードを、C# 5.0のコンパイラーと、Roslynの新コンパイラーでビルドして、その結果をIL Spyでのぞいてみる。

static async Task X()
{
var a = ReadInt();
var x = ReadInt();
Console.WriteLine(x);

await Task.Delay(1);

++a;
var y = ReadInt();
Console.WriteLine(y);
Console.WriteLine(a);
}

static int ReadInt()
{
return int.Parse(Console.ReadLine());
}

ちなみに、RoslynをインストールしちゃうとVisual Studioが新しいコンパイラーしか使わなくなるんで、コマンドラインで直にコンパイル。

コンパイラーは以下の場所を探せば見つかるはず。

  • 現状のコンパイラー: Windowsフォルダーの下、Microsoft.NET\Framework64\v4.0.30319 (バージョン違いの場合、64 が付かなかったり v の後ろの数字が違う)にある csc.exe
  • Roslynのコンパイラー: Visual Studio拡張のインストールフォルダー内を rcsc.exe で検索
    • VS拡張は ユーザー名\AppData\Local\Microsoft\VisualStudio\12.0\Roslyn\Extensions に入ってる

実行ファイル名は rcsc.exe に変わっているものの、コンパイル オプションとかは今まで通りみたい。

結果

ちゃんと変更されてた。

image

(フィールド名とかは読めるように書き換えています。コンパイラーの生成するコードはもっと難読化されたようなひどい変数名。)

現状の何が問題かというと、awaitをまたがないものでも無関係に全部、ローカル変数がフィールド化されてたこと。

一方で、新コンパイラーでは、ちゃんとawaitをまたぐかどうかを判定して、またいでいるものだけをフィールド化。

このサンプルで言うと、変数 a だけがawaitをまたいでいて、x と y はまたいでいない。現コンパイラーだと a, x, y 全部フィールドになっていて、新コンパイラーだと a だけがフィールドになる。

変更の影響

まあ、実のところ破壊的変更になるわけですが。とはいえ、めったなことではこの変更の影響を受けないはず。

この変更の影響を受けるとすると、GCのタイミングに依存するようなコードを書いた場合(デストラクターを持っていて、かつ、デストラクターの実行順序によって挙動が変わるとか)。そんなコード書くことは普通ないので問題は出ないでしょう。

(というか、元のコードでもコンパイラーの最適化の有無で参照が消えたりするはずで、元々GCのタイミングに依存するようなコード書いたらまともに動かないはずですけども。)

Written by ufcpp

2014年4月5日 at 17:36

カテゴリー: C#

Tagged with ,