簡単な速度比較4 文字列連結
今日は今読んでいる本に書いてあった内容が気になったのでテストしてみました。
その内容とは
String型の変数A,B,Cがあったとします。
A = B + C
とした場合、AはBとCの参照を持ちます。
その状態でB(もしくはC)の値を変更するとB(もしくはC)は新しく領域を確保し、
そこに変更した値が入ります。
※かなり自分の言葉に直してしまいましたがだいたいこんな事が書いてあったと思います。
そこで気になった事は
Aは参照を持つわけだから単純に文字列の結合、代入は非常に高速である。
しかし代入後、元の変数に変更がかかると新たに領域を確保する必要がある為、
パフォーマンスが低下するのでは無いかと。
まぁ基本的に代入した元の変数をあれやこれやと変更するシチュエーションなんて
あまり無いわけで、思い浮かぶシチュエーションはバグの温床になる様な使い方なので
この検証自体あまり意味の無いものの様な気がしますが、一応試してみました。
/** ソース */
using System;
using System.Runtime.InteropServices;
class sampleClass1{
[DllImport("kernel32.dll")]
extern static short QueryPerformanceCounter(ref long x);
[DllImport("kernel32.dll")]
extern static short QueryPerformanceFrequency(ref long x);
public static int Main(){
long ctr1 = 0, ctr2 = 0, freq = 0;
if (QueryPerformanceCounter(ref ctr1)!=0){
String a = "";
String a1 = "";
String a2 = "";
for (long i=0; i<1000000; i++){
String b = "a1";
String c = "a2";
a = b + c;
a1 = "b";
a2 = "c";
if( i == 0 ) Console.WriteLine( a + "," + b + "," + c );
}
QueryPerformanceCounter(ref ctr2); // 時間の計測を終了します。
Console.WriteLine("開始値: " + ctr1);
Console.WriteLine("終了値: " + ctr2);
QueryPerformanceFrequency(ref freq);
Console.WriteLine("QueryPerformanceCounter の最小分解能: 1/" + freq + " 秒。");
Console.WriteLine("時間: " + (ctr2 - ctr1) * 1.0 / freq + " 秒。");
}
return 0;
}
}
class sampleClass2{
[DllImport("kernel32.dll")]
extern static short QueryPerformanceCounter(ref long x);
[DllImport("kernel32.dll")]
extern static short QueryPerformanceFrequency(ref long x);
public static int Main(){
long ctr1 = 0, ctr2 = 0, freq = 0;
if (QueryPerformanceCounter(ref ctr1)!=0){
String a = "";
for (long i=0; i<1000000; i++){
String b = "a1";
String c = "a2";
a = b + c;
b = "b";
c = "c";
if( i == 0 ) Console.WriteLine( a + "," + b + "," + c );
}
QueryPerformanceCounter(ref ctr2); // 時間の計測を終了します。
Console.WriteLine("開始値: " + ctr1);
Console.WriteLine("終了値: " + ctr2);
QueryPerformanceFrequency(ref freq);
Console.WriteLine("QueryPerformanceCounter の最小分解能: 1/" + freq + " 秒。");
Console.WriteLine("時間: " + (ctr2 - ctr1) * 1.0 / freq + " 秒。");
}
return 0;
}
}
/* ソース **/
/** 実行結果 */
d:\プログラム>sampleChain1
a1a2,a1,a2
開始値: 15389500331030
終了値: 15389681236464
QueryPerformanceCounter の最小分解能: 1/1000290000 秒。
時間: 0.180852986633876 秒。
d:\プログラム>sampleChain2
a1a2,b,c
開始値: 15391185512763
終了値: 15391382638861
QueryPerformanceCounter の最小分解能: 1/1000290000 秒。
時間: 0.197068948005079 秒。
/* 実行結果 **/
/** ildasm */
// sampleClass1
IL_0039: ldstr "a1"
IL_003e: stloc.s V_7
IL_0040: ldstr "a2"
IL_0045: stloc.s V_8
IL_0047: ldloc.s V_7
IL_0049: ldloc.s V_8
IL_004b: call string [mscorlib]System.String::Concat(string,
string)
IL_0050: stloc.3
IL_0051: ldstr "b"
IL_0056: stloc.s V_4
IL_0058: ldstr "c"
IL_005d: stloc.s V_5
IL_005f: ldloc.s V_6
IL_0061: ldc.i4.0
IL_0062: conv.i8
// sampleClass2
IL_002b: ldstr "a1"
IL_0030: stloc.s V_5
IL_0032: ldstr "a2"
IL_0037: stloc.s V_6
IL_0039: ldloc.s V_5
IL_003b: ldloc.s V_6
IL_003d: call string [mscorlib]System.String::Concat(string,
string)
IL_0042: stloc.3
IL_0043: ldstr "b"
IL_0048: stloc.s V_5
IL_004a: ldstr "c"
IL_004f: stloc.s V_6
IL_0051: ldloc.s V_4
IL_0053: ldc.i4.0
IL_0054: conv.i8
/* ildasm **/
この結論から確かに代入の対象になった変数の書き換えが遅い事が判明しました。
ただIntの時は常に実行結果は同じ時間がかかっていたのにStringの比較になってから
プログラムの計測した時間が微妙にぶれるようになりました。
原因はわかりませんが、一応速度差はこの様になりました。
ただこの速度差を重視するかどうかは人それぞれの様な気もします。
故意にこの様なコードを書く人はあまりいないと思うし、普通にプログラムを
組む分には誤差程度かもしれません。
とは言ったものの、私はこういうコードを極力減らすようにしてしまうと思いますが。
プログラマーにとってこういう取捨選択案外あってそれでソースコードや開発手法等に
個性が出てくるものです。
ただ一つ言える事はチームで開発する場合は自分の個性は極力潜める事。
協調性のある行動を取れる人になれる事が大事かと思います。
タイトルと結論が全く関係無いのは愛嬌と言う事で(*゜▽゜ノノ゛☆
簡単な速度比較3
日曜はお休みしてしまいました。
さて速度比較の続きですが、今日はStringで試してみたいと思います。
さっそくソースです。
/** ソース */
using System;
using System.Runtime.InteropServices;
// Stringをnullで初期化
class sampleClass1{
[DllImport("kernel32.dll")]
extern static short QueryPerformanceCounter(ref long x);
[DllImport("kernel32.dll")]
extern static short QueryPerformanceFrequency(ref long x);
public static int Main(){
long ctr1 = 0, ctr2 = 0, freq = 0;
if (QueryPerformanceCounter(ref ctr1)!=0){
for (long i=0; i<100000000; i++){
String a = null;
}
QueryPerformanceCounter(ref ctr2); // 時間の計測を終了します。
Console.WriteLine("開始値: " + ctr1);
Console.WriteLine("終了値: " + ctr2);
QueryPerformanceFrequency(ref freq);
Console.WriteLine("QueryPerformanceCounter の最小分解能: 1/" + freq + " 秒。");
Console.WriteLine("時間: " + (ctr2 - ctr1) * 1.0 / freq + " 秒。");
}
return 0;
}
}
// Stringを""で初期化
class sampleClass2{
[DllImport("kernel32.dll")]
extern static short QueryPerformanceCounter(ref long x);
[DllImport("kernel32.dll")]
extern static short QueryPerformanceFrequency(ref long x);
public static int Main(){
long ctr1 = 0, ctr2 = 0, freq = 0;
if (QueryPerformanceCounter(ref ctr1)!=0){
for (long i=0; i<100000000; i++){
String a = "";
}
QueryPerformanceCounter(ref ctr2); // 時間の計測を終了します。
Console.WriteLine("開始値: " + ctr1);
Console.WriteLine("終了値: " + ctr2);
QueryPerformanceFrequency(ref freq);
Console.WriteLine("QueryPerformanceCounter の最小分解能: 1/" + freq + " 秒。");
Console.WriteLine("時間: " + (ctr2 - ctr1) * 1.0 / freq + " 秒。");
}
return 0;
}
}
// Stringを"abcdefghijklmnopqrstuvwxyz"で初期化
class sampleClass3{
[DllImport("kernel32.dll")]
extern static short QueryPerformanceCounter(ref long x);
[DllImport("kernel32.dll")]
extern static short QueryPerformanceFrequency(ref long x);
public static int Main(){
long ctr1 = 0, ctr2 = 0, freq = 0;
if (QueryPerformanceCounter(ref ctr1)!=0){
for (long i=0; i<100000000; i++){
String a = "abcdefghijklmnopqrstuvwxyz";
}
QueryPerformanceCounter(ref ctr2); // 時間の計測を終了します。
Console.WriteLine("開始値: " + ctr1);
Console.WriteLine("終了値: " + ctr2);
QueryPerformanceFrequency(ref freq);
Console.WriteLine("QueryPerformanceCounter の最小分解能: 1/" + freq + " 秒。");
Console.WriteLine("時間: " + (ctr2 - ctr1) * 1.0 / freq + " 秒。");
}
return 0;
}
}
/* ソース **/
/** 実行結果 */
d:\プログラム>sampleString1
開始値: 12065979907598
終了値: 12066688345410
QueryPerformanceCounter の最小分解能: 1/1000290000 秒。
時間: 0.708232424596867 秒。
d:\プログラム>sampleString2
開始値: 12068098674440
終了値: 12068807330977
QueryPerformanceCounter の最小分解能: 1/1000290000 秒。
時間: 0.708451086185006 秒。
d:\プログラム>sampleString3
開始値: 12070231692938
終了値: 12070940903640
QueryPerformanceCounter の最小分解能: 1/1000290000 秒。
時間: 0.709005090523748 秒。
/* 実行結果 **/
結論としてはなにで初期化しようがあんまり速度的には変わらないと言う事でしょうか。
ildasmでそれぞれを比較してみます。
// Stringをnullで初期化
IL_0023: nop
IL_0024: ldnull
IL_0025: stloc.s V_4
// Stringを""で初期化
IL_0023: nop
IL_0024: ldstr ""
IL_0029: stloc.s V_4
// Stringを"abcdefghijklmnopqrstuvwxyz"で初期化
IL_0023: nop
IL_0024: ldstr "abcdefghijklmnopqrstuvwxyz"
IL_0029: stloc.s V_4
上記結果を見てもこの3種類の命令はどれも似たようなスピードで実行されるのがわかりました。
ただ厳密には上から順に早いみたいなのでその差が気になる人はnullで初期化する事をお勧めします。
簡単な速度比較2
前回に続きnullをセットする方がなぜ遅いかについて説明したいと思います。
(かなり予想のレベルなので間違えているかもしれませんが)
※ildasmを使った結果です。
.method public hidebysig static int32 Main() cil managed
{
.entrypoint
// コード サイズ 204 (0xcc)
.maxstack 3
.locals init (int64 V_0,
int64 V_1,
int64 V_2,
int64 V_3,
valuetype [mscorlib]System.Nullable`1<int32> V_4,
int32 V_5,
bool V_6)
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: conv.i8
IL_0003: stloc.0
IL_0004: ldc.i4.0
IL_0005: conv.i8
IL_0006: stloc.1
IL_0007: ldc.i4.0
IL_0008: conv.i8
IL_0009: stloc.2
IL_000a: ldloca.s V_0
IL_000c: call int16 sampleClass1::QueryPerformanceCounter(int64&)
IL_0011: ldc.i4.0
IL_0012: ceq
IL_0014: stloc.s V_6
IL_0016: ldloc.s V_6
IL_0018: brtrue IL_00c4
IL_001d: nop
IL_001e: ldc.i4.0
IL_001f: conv.i8
IL_0020: stloc.3
IL_0021: br.s IL_0032
IL_0023: nop
IL_0024: ldloca.s V_4
IL_0026: initobj valuetype [mscorlib]System.Nullable`1<int32>
IL_002c: nop
IL_002d: ldloc.3
IL_002e: ldc.i4.1
IL_002f: conv.i8
IL_0030: add
IL_0031: stloc.3
IL_0032: ldloc.3
IL_0033: ldc.i4 0x5f5e100
IL_0038: conv.i8
IL_0039: clt
IL_003b: stloc.s V_6
IL_003d: ldloc.s V_6
IL_003f: brtrue.s IL_0023
IL_0041: ldloca.s V_1
IL_0043: call int16 sampleClass1::QueryPerformanceCounter(int64&)
IL_0048: pop
IL_0049: ldstr bytearray (8B 95 CB 59 24 50 3A 00 20 00 ) // ...Y$P:. .
IL_004e: ldloc.0
IL_004f: box [mscorlib]System.Int64
IL_0054: call string [mscorlib]System.String::Concat(object,
object)
IL_0059: call void [mscorlib]System.Console::WriteLine(string)
IL_005e: nop
IL_005f: ldstr bytearray (42 7D 86 4E 24 50 3A 00 20 00 ) // B}.N$P:. .
IL_0064: ldloc.1
IL_0065: box [mscorlib]System.Int64
IL_006a: call string [mscorlib]System.String::Concat(object,
object)
IL_006f: call void [mscorlib]System.Console::WriteLine(string)
IL_0074: nop
IL_0075: ldloca.s V_2
IL_0077: call int16 sampleClass1::QueryPerformanceFrequency(int64&)
IL_007c: pop
IL_007d: ldstr bytearray (51 00 75 00 65 00 72 00 79 00 50 00 65 00 72 00 // Q.u.e.r.y.P.e.r.
66 00 6F 00 72 00 6D 00 61 00 6E 00 63 00 65 00 // f.o.r.m.a.n.c.e.
43 00 6F 00 75 00 6E 00 74 00 65 00 72 00 20 00 // C.o.u.n.t.e.r. .
6E 30 00 67 0F 5C 06 52 E3 89 FD 80 3A 00 20 00 // n0.g.\.R....:. .
31 00 2F 00 ) // 1./.
IL_0082: ldloc.2
IL_0083: box [mscorlib]System.Int64
IL_0088: ldstr bytearray (20 00 D2 79 02 30 ) // ..y.0
IL_008d: call string [mscorlib]System.String::Concat(object,
object,
object)
IL_0092: call void [mscorlib]System.Console::WriteLine(string)
IL_0097: nop
IL_0098: ldstr bytearray (42 66 93 95 3A 00 20 00 ) // Bf..:. .
IL_009d: ldloc.1
IL_009e: ldloc.0
IL_009f: sub
IL_00a0: conv.r8
IL_00a1: ldc.r8 1.
IL_00aa: mul
IL_00ab: ldloc.2
IL_00ac: conv.r8
IL_00ad: div
IL_00ae: box [mscorlib]System.Double
IL_00b3: ldstr bytearray (20 00 D2 79 02 30 ) // ..y.0
IL_00b8: call string [mscorlib]System.String::Concat(object,
object,
object)
IL_00bd: call void [mscorlib]System.Console::WriteLine(string)
IL_00c2: nop
IL_00c3: nop
IL_00c4: ldc.i4.0
IL_00c5: stloc.s V_5
IL_00c7: br.s IL_00c9
IL_00c9: ldloc.s V_5
IL_00cb: ret
} // end of method sampleClass1::Main
これはsampleInt1.exeの結果です。
基本的にsampleInt2、sampleInt3、sampleInt4共にプログラムはほぼ同じなので
sampleInt2、3,4に関しては差分のみ記します。
※sampleInt2
IL_0020: stloc.3
IL_0021: br.s IL_002d
IL_0023: nop
IL_0024: ldc.i4.0
IL_0025: stloc.s V_4
IL_0027: nop
※sampleInt3
IL_0020: stloc.3
IL_0021: br.s IL_0032
IL_0023: nop
IL_0024: ldloca.s V_4
IL_0026: initobj valuetype [mscorlib]System.Nullable`1<int32>
IL_002c: nop
※sampleInt4
IL_0020: stloc.3
IL_0021: br.s IL_0033
IL_0023: nop
IL_0024: ldloca.s V_4
IL_0026: ldc.i4.0
IL_0027: call instance void valuetype [mscorlib]System.Nullable`1<int32>::.ctor(!0)
IL_002c: nop
これを見るとわかりますが、int?、Nullable<int>は普通のintではなく、System.Nullable
と言う型を使っている事がわかります。
この様な理由で単純にintに0を設定するよりnullableにnullを設定する方が時間がかかる
事になります。
あと一つ問題としてはnullableにはnullを設定するより0を設定する方が早いと言う結論ですが、
たぶんnullableが内部で持つ値は初期値が0の為、0で初期化する場合はインスタンスを生成
するだけでよく、nullで初期化する場合はインスタンス生成後にnullで初期化をしてあげる必要が
あるのでは無いかと思います。
そこで試しにnullableの初期化を0ではなく、2や100を設定してプログラムを実行したところ
d:\プログラム>test
開始値: 11831667877930
終了値: 11832678501496
QueryPerformanceCounter の最小分解能: 1/1000290000 秒
時間: 1.01033057013466 秒。
この様な結果を得る事が出来ました。
つまり0以外はインスタンス生成後に初期化処理をする必要がある為、少し時間がかかる
ものと思われます。
この結果からnullableで初期化する場合は特別な理由が無い限り、0で初期化する事が
望ましいのでは無いかと言う結論になると思います。
と、まぁ今回はint型の速度比較のつもりがそもそも違う型を同じ型だと思って比較してしまった
時点でイタタタタ(x_x;)な感じがしました。
今回の様な事が無いように次回はString型で比較してみたいと思います。
コンパイル色々
前回はコンパイラがどこにあるのかを説明しましたが
今回はそのコンパイラを使うにあたってやっておいた方が
良いと思える事について書きたいと思います。
前回csc.exeと言うコンパイラについて説明しました、
c:\winnt\microsoft.net\frameworkの中になるので
コマンドラインから実行する為にはそのディレクトリまで移動する
必要があります。
しかしわざわざそこまで移動するのもめんどくさいし、もしコンパイラが
ある場所にexeが作成されてしまったら大変です。
これを改善するためには環境変数を変更します。
(Windows2000環境でのお話です。)
マイコンピュータを右クリックしてプロパティを選択します。
(Windows2000ではシステムのプロパティと言う画面が開きます)
「詳細」タブを選択して「環境変数」ボタンをクリックします。
システムの環境変数と書かれた下にあるリストボックスに
変数 値
Path ほにゃらら
と書かれていると思うのでそのPathの行をダブルクリックしてください。
たぶん編集画面が表示されるのでそこにcsc.exeのあるパスを追記してください。
(すでにパスが入っている場合はセミコロンで区切ってください)
追記したらOKボタンで閉じてください。
そしてコマンドプロンプトを開きcscを打ち込んでください。
カレントディレクトリがどこであってもC#コンパイラを実行できると思います。
また「csc ソースファイル名」と入力するとexeは現在いるディレクトリに作成されます。
まぁexeを作りたい場所でコンパイルすれば良い話ですが
ソースとexeのフォルダをわけたい事もあると思うのでそういう場合は
csc /out:出力パス ソースファイル名
と、する事でexeの出力場所を変える事が出来ます。(ついでにexe名も指定できるようになります)
コンパイラ実行時のパラメータは色々あるので試してみるのも面白いかもしれません。
0から始めるC#
- 「C# 番外編」では本編の方で説明しきれない細かい内容等を
載せていきたいと思います。
まず一回目の今回はどうやったらC#を使えるの?から説明したいと思います。
私も先週からC#を勉強し始めた人なんですが、その前の週に
某(大きい)カメラ屋さんに行ってきました。
まぁC#やるならVisual Studio買わないといけないだろうなぁと思っていったわけですが。。。
そこで見た光景は
Visual Studio 2005
3万~30万 也 ヽ(`Д´)ノ(たけぇ~よ)
もちろん見るだけで帰りました。
次の週、同僚からコンパイラならただで配っているとの朗報を聞き、
さっそく調べてみることに。
な~んと!( ̄□ ̄;)!!
- よくよく調べたら自分のPCに入ってるじゃないですか。
OSのバージョンとWindows Updateをちゃんとやっているかどうかにも変わってきますが
c:\Winnt\Microsoft.net\framework\の下に
v1.0.○○○
や
v1.1.○○○
や
v2.0.○○○
と言うフォルダがあればそれが.Netです。
各フォルダの中にはcsc.exeというものが含まれていますが、
これがC#のコンパイラになります。
試しに実行してみて下さい。
d:\プログラム>csc fatal error CS2008: 入力が指定されていません。 |
こんな感じに出るはずです、 Compiler version 8.00.50727.42となっていますが
自分の環境で見た限りだと バージョン8以降が巷で言われているC#2.0に相当する様です。
これさえあればただでC#使いたい放題です。
お試しでやってみたい方には最適な方法かもしれません。(Visual Studio高いしね)
簡単な速度比較1
前回予告した通り今回は簡単な速度比較をしてみたいと思います。
某掲示板で見かけた内容ですがとある方が
「インスタンスの生成時の初期化でnewをするなんてコストが高い事をするべきで
ない。初期化はnullでするべきだ」
と、語っていた方がいました。
C#ではどうなのか興味があったので試してみました。
※ソース
using System.Runtime.InteropServices;
// Nullableにnullで初期化
class sampleClass1{
[DllImport("kernel32.dll")]
extern static short QueryPerformanceCounter(ref long x);
[DllImport("kernel32.dll")]
extern static short QueryPerformanceFrequency(ref long x);
public static int Main(){
long ctr1 = 0, ctr2 = 0, freq = 0;
if (QueryPerformanceCounter(ref ctr1)!=0){
for (long i=0; i<100000000; i++){
Nullable<int> a = null;
}
QueryPerformanceCounter(ref ctr2); // 時間の計測を終了します。
Console.WriteLine("開始値: " + ctr1);
Console.WriteLine("終了値: " + ctr2);
QueryPerformanceFrequency(ref freq);
Console.WriteLine("QueryPerformanceCounter の最小分解能: 1/" + freq + " 秒。");
Console.WriteLine("時間: " + (ctr2 - ctr1) * 1.0 / freq + " 秒。");
}
return 0;
}
}
// intに0で初期化
class sampleClass2{
[DllImport("kernel32.dll")]
extern static short QueryPerformanceCounter(ref long x);
[DllImport("kernel32.dll")]
extern static short QueryPerformanceFrequency(ref long x);
public static int Main(){
long ctr1 = 0, ctr2 = 0, freq = 0;
if (QueryPerformanceCounter(ref ctr1)!=0){
for (long i=0; i<100000000; i++){
int a = 0;
}
QueryPerformanceCounter(ref ctr2); // 時間の計測を終了します。
Console.WriteLine("開始値: " + ctr1);
Console.WriteLine("終了値: " + ctr2);
QueryPerformanceFrequency(ref freq);
Console.WriteLine("QueryPerformanceCounter の最小分解能: 1/" + freq + " 秒。");
Console.WriteLine("時間: " + (ctr2 - ctr1) * 1.0 / freq + " 秒。");
}
return 0;
}
}
// int?にnullで初期化
class sampleClass3{
[DllImport("kernel32.dll")]
extern static short QueryPerformanceCounter(ref long x);
[DllImport("kernel32.dll")]
extern static short QueryPerformanceFrequency(ref long x);
public static int Main(){
long ctr1 = 0, ctr2 = 0, freq = 0;
if (QueryPerformanceCounter(ref ctr1)!=0){
for (long i=0; i<100000000; i++){
int? a = null;
}
QueryPerformanceCounter(ref ctr2); // 時間の計測を終了します。
Console.WriteLine("開始値: " + ctr1);
Console.WriteLine("終了値: " + ctr2);
QueryPerformanceFrequency(ref freq);
Console.WriteLine("QueryPerformanceCounter の最小分解能: 1/" + freq + " 秒。");
Console.WriteLine("時間: " + (ctr2 - ctr1) * 1.0 / freq + " 秒。");
}
return 0;
}
}
// int?に0で初期化
class sampleClass4{
[DllImport("kernel32.dll")]
extern static short QueryPerformanceCounter(ref long x);
[DllImport("kernel32.dll")]
extern static short QueryPerformanceFrequency(ref long x);
public static int Main(){
long ctr1 = 0, ctr2 = 0, freq = 0;
if (QueryPerformanceCounter(ref ctr1)!=0){
for (long i=0; i<100000000; i++){
int? a = 0;
}
QueryPerformanceCounter(ref ctr2); // 時間の計測を終了します。
Console.WriteLine("開始値: " + ctr1);
Console.WriteLine("終了値: " + ctr2);
QueryPerformanceFrequency(ref freq);
Console.WriteLine("QueryPerformanceCounter の最小分解能: 1/" + freq + " 秒。");
Console.WriteLine("時間: " + (ctr2 - ctr1) * 1.0 / freq + " 秒。");
}
return 0;
}
}
※結果
d:\プログラム>sampleInt1
開始値: 2524982841724
終了値: 2525985623567
QueryPerformanceCounter の最小分解能: 1/1000310000 秒。
時間: 1.00247107696614 秒。
d:\プログラム>sampleInt2
開始値: 2528005937504
終了値: 2528708171601
QueryPerformanceCounter の最小分解能: 1/1000310000 秒。
時間: 0.702016471893713 秒。
d:\プログラム>sampleInt3
開始値: 2530182871156
終了値: 2531185940354
QueryPerformanceCounter の最小分解能: 1/1000310000 秒。
時間: 1.0027583429137 秒。
d:\プログラム>sampleInt4
開始値: 2532427548899
終了値: 2533329863481
QueryPerformanceCounter の最小分解能: 1/1000310000 秒。
時間: 0.902034951165139 秒。
それぞれ
sampleClass1がsampleInt1.exe
sampleClass2がsampleInt2.exe
sampleClass3がsampleInt3.exe
sampleClass4がsampleInt4.exe
に対応しています。
この結果からC#ではnullで初期化する方が遅い事がわかります。(結論)
\(*`∧´)/んなわけあるはずが無く、これにはわけがあります。
まぁプリミティブにnullを設定している時点でC#を知らない人でも「おや?」と
思うはずです。
この様になってしまう理由については次回説明したいと思います。
※2006.7.1 修正
インスタンスの精製時 → インスタンスの生成時
C#でHello World
毎度お決まりのあれです。
プログラムの本を読んだ事がある人はまたあれかと思うその一文
「Hello World」
以下ソースコードです。
using System;
class sampleClass{
public static int Main(){
Console.WriteLine("Hello World!");
return 0;
}
}
まぁなんて言うかそのまんまですね。
結果はこんな感じです。
#コンパイル
| d:\プログラム>csc sample1.cs Microsoft(R) Visual C# 2005 Compiler version 8.00.50727.42 for Microsoft(R) Windows(R) 2005 Framework version 2.0.50727 Copyright (C) Microsoft Corporation 2001-2005. All rights reserved |
#実行
| d:\プログラム>sample1 Hello World! |
そして今気付きました!
プログラムは簡単だけどこのブログにそれっぽく載せるのは非常に大変!ヽ(`Д´)ノ
最悪画像で載せた方が楽かもしれないなぁ。
今日は時間が無いのでこのくらいで、
次回はちょっとしたスピード比較を考えています。
でわでわ。
当面の予定
「プロフェッショナル C# 上」
は3章まで読みました。
感想としてはC#はVC++を起点とし、使いやすさでJAVAに歩み寄り
危険なコードを隠すと言う行為でVBに歩み寄った言語な印象でした。
ただVBに近づいた分使いづらいくなった箇所を新しい機能で補完している
その為、switchステートメントやoutキーワード等にちょっと違和感を感じました。
あとJAVADOCのまねっこのようなXMLですが、これは前々から欲しいなと思って
いた機能なのでまねっこでも歓迎です。
ただXML形式だと閉じタグとか書くのがめんどくさいですね。
Visual Studioだとそこらへんを自動的に作ってくれるそうですが、メモ帳ベースな
私には辛い感じがしました。(マクロで対応するかな)
当面の予定ですが、どんなシステムでも必ず使う機能。
「ログ」
これから手をつけようと思います。
ただ、まだ勉強中の身なので作り始めるのはもうちょっと先になりそうです。
次回から今読んでいる
「プロフェッショナル C# 上」
のコードを実際に試してみた結果等も少し載せてみようと思います。
でわでわ。(^-^)ノ~~
- シモン ロビンソン, ジャイ グリン, クレイグ マックイーン, オリー コーン, バートン ハーヴェイ, Simon Robinson, Jay Glynn, Craig McQueen, Ollie Cornes, Burton Harvey
- プロフェッショナルC#〈上〉基本編
ブログ始めました。
今日からブログを始めます。(〃∇〃)
ブログと同時にC#の勉強も始めました。
今参考にしている本は
「プロフェッショナル C# 上」
と言う本です。
まだ読み初めで2章まで読んだけれど、C#と.Netがどれだけすごいかと言う事を
大雑把に説明しているけれども、Windows Meを賞賛している所を見るとあんまり
真に受けちゃいけないのかもしれないと思った。
しかしこの本をプログラムを始める初心者が読んだら.Netってすごいなぁとか
思っちゃうんだろうな。ヽ(゚◇゚ )ノ
まぁ唯一心に残った事は.Netは実行時に実行する部分だけコンパイルされるって事と
DLLはアセンブリと呼ばれるものにパワーアップしたと言う事かな。
C#はソースコード自体まったく見た事無いし、本当に初めてだから今本を読んで
さらっと流している部分も実は重要だったりしちゃうかもしれないけど、それはその時
考えるとしよう。
一応次回は当面の予定について書こうと思う。
それじゃ、また明日~。
※不定期更新です。
- シモン ロビンソン, ジャイ グリン, クレイグ マックイーン, オリー コーン, バートン ハーヴェイ, Simon Robinson, Jay Glynn, Craig McQueen, Ollie Cornes, Burton Harvey
- プロフェッショナルC#〈上〉基本編

