Ognacの雑感

木漏れ日々

目次

Blog 利用状況

書庫

ギャラリ

構造体はVBerに嫌われているの?

あるプロジェクトで 要素の少ないObjectを構造体でコーディングしました。
   <StructLayout(LayoutKind.Explicit)> _
   Public Structure struct_A
      Public A As Integer
      Public B As Short
   End Structure
という感じで実装しました。PLから言われたいちゃもん(もとい注文)は、「構造体はC++/C#系の人は適切に使い分けるが VBerは馴染みがないのでStructは使わないでくれ」
反論しても不毛だと察して素直に(?)従ったのですが、そんなもんかなぁ。なんか違うぞ。ブツブツ...orz.

それはともかく、 要素数+ OverHeadが 20byte? 以下なら 構造体のほうがコストが低いと認識してます。
バウンダリーや参照のOffsetの関係が絡むので、ClassはStructに比べてインスタンス生成はコスト高になります。
 どれ位の差があるのか気になったので計測してみました。 昨今は StopWatch Classが標準で付いているのでWrap測定が楽なので重宝します。
私の測定方法は, 1メソッドの測定時間から1秒間に処理できそうな回数を算出し、その回数をLoopでまわし、所要時間から逆算する方法で求めてます。
上記のInter/Short を構造体とClassで定義して測定すると new() に費やしたコストは
  Class : 0.02  mSec
  Struct: 0.006 mSec
となりました。これだけ明確に差が出るとは改めてビツクリ。
 クラスと構造体は適時に使い分ける必要を実感した次第です。上記のPLさんは何を根拠に構造体を否定したのだろう。彼のいうように、VBerが不勉強であるならば、指導してあげるべきではないの?
単なる思い込みで判断している気がするのだが。

投稿日時 : 2008年1月29日 0:48

Feedback

# re: 構造体はVBerに嫌われているの? 2008/01/29 1:05 はつね

本人が不勉強なだけでしょう。

# re: 構造体はVBerに嫌われているの? 2008/01/29 1:26 れい

ベンチマークを公開するには情報がちょっと足りないですよ。
せめてCPUとメモリぐらいは。

http://www.microsoft.com/japan/msdn/net/general/ms973265.aspx

> 彼のいうように、VBerが不勉強であるならば、指導してあげるべきではないの?

いろんなレベルの人がいますからねぇ。
トータルで最も生産性が高くなるようにするにはどうしたらいいのか、
簡単に答えはでないですね。
人を管理するのは大変です。

# re: 構造体はVBerに嫌われているの? 2008/01/29 1:27 渋木宏明(ひどり)

アロケートのパフォーマンスだけで評価するのは公平じゃないような気がします。

値型の場合、配列やコレクションと組み合わせて使う場合に発生する、コピーに要する時間が気になります。

# re: 構造体はVBerに嫌われているの? 2008/01/29 1:47 NAL-6295

その、スピードが必要ではない局面であれば、特に使い分けはしないですね。
そして、あんまりその局面に出会ったことが無いですね。

# re: 構造体はVBerに嫌われているの? 2008/01/29 5:29 渋木宏明(ひどり)

たかだかこれくらいの操作でも、アロケートの性能差は覆ってしまいます。

要素の追加や上書き更新が多いシナリオには向かないと思います。

static void Main(string[] args)
{
int length = 1000000;

Stopwatch sw = new Stopwatch();

{
List<Class> list = new List<Class>();

sw.Start();

for (int i = 0; i < length; i++)
{
list.Add(new Class());
}

sw.Stop();

System.Console.Out.WriteLine("class = " + sw.ElapsedMilliseconds / 1000.0);
}

{
List<Struct> list = new List<Struct>();

sw.Start();

for (int i = 0; i < length; i++)
{
list.Add(new Struct());
}

sw.Stop();

System.Console.Out.WriteLine("struct = " + sw.ElapsedMilliseconds / 1000.0);
}
}

# re: 構造体はVBerに嫌われているの? 2008/01/29 7:26 こぐま

業務アプリの場合は、間違った使い分けをされるよりはクラスに統一するのも一つの手かもしれないですね...
# 構造体にすべき要素自体が少ないですし...

当然 Framework などでは正しく使い分けるべきだと思ってます。

# re: 構造体はVBerに嫌われているの? 2008/01/29 10:29 じゃんぬねっと

×VBerは馴染みがないのでStructは使わないでくれ
  ↓
○VBerは値型とか参照型とかわかんないから Type を使ってくれ

# re: 構造体はVBerに嫌われているの? 2008/01/29 10:37 ghost_shell

>クラスと構造体は適時に使い分ける必要を実感した次第です。
>単なる思い込みで判断している気がするのだが。

これはこれで思い込みをしてないか――

根拠としているパフォーマンス評価が現実に即しているとはいえないのと、パフォーマンスだけの観点だけでstructかclassを決めようとしていると思えてしまう点が

――心配になりました。

# re: 構造体はVBerに嫌われているの? 2008/01/29 12:03 Ognac

皆様、コメント、ご指摘ありがとうごさいます。
(考察不足なエントリーでした。反省事項が多々ありました。)
構造体とクラスはパフォーマンス面だけの比較では一面しか見てないことになります。
Heap領域の配置やGCの対象有無などやアロケートでの差は、渋木さんのサンプルが多いに参考になりました。これ踏まえて比較しないとご指摘のように不公平になりますね。
エントリーでは 20byte以下は構造体が有利と書きましたが, 4byte Boundary とoffset 4byteで16byte以下が有利との情報も耳にしたのですが、未確認です。 sizeof は unsafeモードなので、直接比較できないかと。
Collection.ADD で帳消しになり逆転されるのは以外でした。値型の複製コストを復習しなければ。
危うく私が思い込みに嵌るところでした。ありがとうこざいました。

因みに稼動機種は Athron 64*2 (3800) で memory 4G です。
 Class/Struct の差を認識したうえでのコードと認識しないでClassのみのコードが、結果的には同じなのも........www...ですね。

# re: 構造体はVBerに嫌われているの? 2008/01/29 13:01 よねけん

こんにちは。

>パフォーマンスだけの観点だけでstructかclassを決めようとしていると思えてしまう点が

私も同じこと思いました。
Structureにするかどうかはその型が本質的に値を意味するかどうかで行うべきだと思います。
後はP/Invokeがらみとか。

私の場合、(速度の要求されない)業務系アプリでは基本的にClassしか使いませんね。データベースとの連携やネットワークとかハードディスクの読み書きとか比較にならないボトルネックが他にあるからStructureの出番はないですね。
自分が関わるタイプの開発なら、そのPLさんの判断で十分ですね。

どうでもいいことだけど、LayoutKind.Explicitを指定しているのにFieldOffsetの指定がないのが少し気になりました。

# re: 構造体はVBerに嫌われているの? 2008/01/29 14:57 THREE-ONE

定数クラスは必ず構造体で定義されていたプロジェクトを見たことがあります。
いまだになぜか理解できていません。
よく考えたら、私は構造体を定義したことがないなぁ。

# re: 構造体はVBerに嫌われているの? 2008/01/29 15:18 渋木宏明(ひどり)

Struct が常にパフォーマンス的に不利なわけではないんですよ。

配列やコレクションと組み合わせる場合でも、頻繁に要素の追加や丸ごとの上書き更新がなければ問題はないわけです。

ただ、それだと使い勝手的にどうかなってトコがあるので、例えばゲームとか、特にパフォーマンスが重要なシナリオに限られるんじゃないかと思います。(あと P/Invoke みたいな「構造体じゃないとダメ」なとことか)

なんて感じなので、僕的には「Struct でないと目標の達成が難しいところ *以外*」はクラスを使ってます。

# re: 構造体はVBerに嫌われているの? 2008/01/29 15:27 なちゃ

>Collection.ADD で帳消しになり逆転されるのは以外でした。値型の複製コストを復習しなければ。

複製コストは複製コストですが、そう単純な話でもないと思いますよ。

# re: 構造体はVBerに嫌われているの? 2008/01/29 22:07 Ognac

うーん。奥が深い。単純な切り口では判断できない例ですね。実態の更新具合などを考慮して最適判断するのもコストが要することを考えると、構造体を使わないのも一つの方法なんですね。
P/Invoke での必然性があるとき以外は、知らなくっても実害はでない。<== 「知らなくて良い」ではないですよね。
私も本質は知らなかったので大きいことは言えませんが...orz

>どうでもいいことだけど、LayoutKind.Explicitを指定しているのにFieldOffsetの指定がない(略)
ご愛敬ということで (^^

タイトル
名前
Url
コメント