C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[23]: DataSetの破棄について [1]


(過去ログ 140 を表示中)

[トピック内 29 記事 (21 - 29 表示)]  << 0 | 1 >>

■81924 / inTopicNo.21)  Re[15]: DataSetの破棄について
  
□投稿者/ sk (12回)-(2016/11/24(Thu) 11:04:14)
No81921 (魔界の仮面弁士 さん) に返信
> ■No81901 (sk さん) に返信

> タイマーを使わずに無限ループさせてみましたが、やはり 57時間ともたずに、
> 型付きな DataSet1 生成が停止してしまいました。

GCによる回収が追い付かなくて‥という理由ではなさそうということですね。


こちらでは、素のDataSetに手動でテーブルを追加して、条件を変えて観察しています。

@Table = 1 ,Column = 10 の場合
 35時間17分20秒 4,294,967,246回で停止。

ATable = 81 ,Column = 10 の場合
 29時間29分8秒 53,024,288回で停止。

BTable = 0で確認中。

引用返信 編集キー/
■81926 / inTopicNo.22)  Re[16]: DataSetの破棄について
□投稿者/ 魔界の仮面弁士 (982回)-(2016/11/24(Thu) 13:29:07)
No81924 (sk さん) に返信
> 素のDataSetに手動でテーブルを追加して

コードから ds.Tables.Add を呼び出している、ということでしょうか。
それとも、TableAdapter 無しの型付き DataSet を用意した、という意味でしょうか。


> @Table = 1 ,Column = 10 の場合
>  35時間17分20秒 4,294,967,246回で停止。

&HFFFFFFCE ですね。64bit なら &H00000000FFFFFFCE 。

UInt32.MaxValue - 4294967246 は 49 なので、
仮に UInt32 な uncheced カウンターが使われていた場合、
これに 50 を加えることで、オーバーフローして
値が 0 に戻ってしまう計算ですが…何だか怪しそうです。



> ATable = 81 ,Column = 10 の場合
>  29時間29分8秒 53,024,288回で停止。

UInt32.MaxValue ÷ 81 = 53,024,287 余り 48

81 × 53,024,287 = 4,294,967,247 (&H00000000FFFFFFCF) … UInt32 で表現可能
81 × 53,024,288 = 4,294,967,328 (&H0000000100000020) … UInt32 だと溢れる


なにか因果関係があるように見えなくもない…。
引用返信 編集キー/
■81931 / inTopicNo.23)  Re[17]: DataSetの破棄について
□投稿者/ sk (13回)-(2016/11/24(Thu) 15:04:49)
No81926 (魔界の仮面弁士 さん) に返信
> ■No81924 (sk さん) に返信

> コードから ds.Tables.Add を呼び出している、ということでしょうか。
> それとも、TableAdapter 無しの型付き DataSet を用意した、という意味でしょうか。

わかりにくくて申し訳ありません。
TableAdapter 無しの型付き DataSet を用意したということです。


>>@Table = 1 ,Column = 10 の場合
>> 35時間17分20秒 4,294,967,246回で停止。
>
> &HFFFFFFCE ですね。64bit なら &H00000000FFFFFFCE 。
>
> UInt32.MaxValue - 4294967246 は 49 なので、
> 仮に UInt32 な uncheced カウンターが使われていた場合、
> これに 50 を加えることで、オーバーフローして
> 値が 0 に戻ってしまう計算ですが…何だか怪しそうです。
>
>
>
>>ATable = 81 ,Column = 10 の場合
>> 29時間29分8秒 53,024,288回で停止。
>
> UInt32.MaxValue ÷ 81 = 53,024,287 余り 48
>
> 81 × 53,024,287 = 4,294,967,247 (&H00000000FFFFFFCF) … UInt32 で表現可能
> 81 × 53,024,288 = 4,294,967,328 (&H0000000100000020) … UInt32 だと溢れる
>
>
> なにか因果関係があるように見えなくもない…。

こちらでもオーバーフローについては懐疑でしたが、
その場合、何かしらの情報(メッセージ、落ちる、エラー、イベント)があるという
認識でした。。
さっぱりです‥。

引用返信 編集キー/
■81933 / inTopicNo.24)  Re[18]: DataSetの破棄について
□投稿者/ 魔界の仮面弁士 (983回)-(2016/11/24(Thu) 16:29:18)
No81931 (sk さん) に返信
> こちらでもオーバーフローについては懐疑でしたが、
> その場合、何かしらの情報(メッセージ、落ちる、エラー、イベント)があるという
> 認識でした。。

処理の高速化のため、オーバーフローチェックが省略されているのかも知れません。

https://msdn.microsoft.com/ja-jp/library/system.reflection.emit.opcodes.add%28vs.90%29.aspx

》 オーバーフローは、整数演算については検出されません。
》 整数加算では、飽和させず、ラップします。たとえば、
》 8 ビット整数で value1 が 255 に、value2 が 1 に設定されている場合、
》 ラップされた結果は 256 ではなく 0 になります。



VB の場合、[コンパイラの詳細設定]-[整数オーバーフローのチェックを解除]を
有効にしておくと、下記のコードが System.OverflowException を発することなく、
「4294967294」「4294967295」「0」「1」「2」と表示されるようになります。

Dim counter = &HFFFFFFCEui
For i = 48ui To 52ui
  Console.WriteLine(counter + i)
Next



C# にも同様のコンパイラオプションがありますが、それとは別に、
checked / unchecked という構文を持っており、任意の箇所で局所的に
演算のオーバーフローチェックの有無を切り替えられるようになっています。


uint counter = 0xFFFFFFCEu;
for (uint i = 48u; i <= 52u; i++) unchecked {
  Console.WriteLine(counter + i);
}


そして IL レベルにおいても、オーバーフローを検出しない加算命令
0x58 (add) とは別に、オーバーフローチェック付きの加算命令
0xd6 (add.ovf) および 0xd7 (add.ovf.un) が存在してます。


※型付きの DataSet(または DataTable)の InitClass メソッドの先で
 どのような呼び出しが行われているのかは未調査です。
引用返信 編集キー/
■81935 / inTopicNo.25)  Re[19]: DataSetの破棄について
□投稿者/ 魔界の仮面弁士 (984回)-(2016/11/24(Thu) 17:20:56)
2016/11/24(Thu) 17:23:50 編集(投稿者)

No81933 (魔界の仮面弁士) に返信
>>こちらでもオーバーフローについては懐疑でしたが、
>>その場合、何かしらの情報(メッセージ、落ちる、エラー、イベント)があるという
>>認識でした。。
> 処理の高速化のため、オーバーフローチェックが省略されているのかも知れません。

もしも 32bit 整数の桁あふれが要因だとすれば、原因は DataColumn かも知れません。


型付き DataTable のコンストラクタ
 → 型付き DataTable の InitClass メソッド
  → System.Data.DataColumn のコンストラクタ
   → System.Data.Bid クラスの Trace メソッドに渡すために
    DataColumn の ObjectId プロパティを読み込む

Bid.Trace は、"System.Data.dll" の DllBidTraceCW API に対する
アンマネージな呼び出しなので、何をするものなのかは追跡できませんでしたが、
問題は、そこに渡している「ObjectId プロパティ」の値。

Refence Source でいえば、下記に当たります。
https://referencesource.microsoft.com/#System.Data/System/Data/DataColumn.cs#138


この ObjectId プロパティのバッキング フィールドである "_objectID" は、
単純に連番で管理されているようです。

private static int _objectTypeCount; // Bid counter
private readonly int _objectID = System.Threading.Interlocked.Increment(ref _objectTypeCount);
https://referencesource.microsoft.com/#System.Data/System/Data/DataColumn.cs,f184a72cba6d0022


連番生成のために Interlocked.Increment を呼び出していますが、
これはオーバーフローしないメソッドなわけで…。
まだ確定ではないですが、なんだか怪しくないですかね?

Dim a As Integer = Integer.MaxValue
Console.WriteLine("0x{0:X8} {0:N0}", a) '0x7FFFFFFF 2,147,483,647
System.Threading.Interlocked.Increment(a)
Console.WriteLine("0x{0:X8} {0:N0}", a) '0x80000000 -2,147,483,648

a = -2
Console.WriteLine("0x{0:X8} {0:N0}", a) '0xFFFFFFFE -2
System.Threading.Interlocked.Increment(a)
Console.WriteLine("0x{0:X8} {0:N0}", a) '0xFFFFFFFF -1
System.Threading.Interlocked.Increment(a)
Console.WriteLine("0x{0:X8} {0:N0}", a) '0x00000000 0
System.Threading.Interlocked.Increment(a)
Console.WriteLine("0x{0:X8} {0:N0}", a) '0x00000001 1
引用返信 編集キー/
■81961 / inTopicNo.26)  Re[20]: DataSetの破棄について
□投稿者/ sk (14回)-(2016/11/25(Fri) 10:44:08)
No81935 (魔界の仮面弁士 さん) に返信
> 2016/11/24(Thu) 17:23:50 編集(投稿者)

> 連番生成のために Interlocked.Increment を呼び出していますが、
> これはオーバーフローしないメソッドなわけで…。
> まだ確定ではないですが、なんだか怪しくないですかね?
>
> Dim a As Integer = Integer.MaxValue
> Console.WriteLine("0x{0:X8} {0:N0}", a) '0x7FFFFFFF 2,147,483,647
> System.Threading.Interlocked.Increment(a)
> Console.WriteLine("0x{0:X8} {0:N0}", a) '0x80000000 -2,147,483,648

なるほど。
結局オーバーフローせずに異常な状態に陥っている可能性があるということですね。

引用返信 編集キー/
■81962 / inTopicNo.27)  Re[21]: DataSetの破棄について
□投稿者/ 魔界の仮面弁士 (988回)-(2016/11/25(Fri) 12:01:50)
No81961 (sk さん) に返信
>>まだ確定ではないですが、なんだか怪しくないですかね?

連続して呼び出した場合は停止するようですが、
_objectTypeCount を直接書き換えるだけでは停止しませんでした。


> 結局オーバーフローせずに異常な状態に陥っている可能性があるということですね。

まだまだ眉唾ではありますが、停止に至るまでの回数を見る限りでは
32bit 境界で何かが起きている可能性は高そうです。


で、先の Bid.Trace ですが、こういう役割があるようです。

https://blogs.msdn.microsoft.com/jpsql/2011/11/07/howto-bid/
https://msdn.microsoft.com/ja-jp/library/ms971550.aspx
引用返信 編集キー/
■81969 / inTopicNo.28)  Re[22]: DataSetの破棄について
□投稿者/ sk (15回)-(2016/11/25(Fri) 18:14:23)
No81962 (魔界の仮面弁士 さん) に返信
> ■No81961 (sk さん) に返信

> まだまだ眉唾ではありますが、停止に至るまでの回数を見る限りでは
> 32bit 境界で何かが起きている可能性は高そうです。

いや、十分説明するに足る見解だと思います。


> で、先の Bid.Trace ですが、こういう役割があるようです。
>
> https://blogs.msdn.microsoft.com/jpsql/2011/11/07/howto-bid/
> https://msdn.microsoft.com/ja-jp/library/ms971550.aspx

こんなものがあるんですね。
これを使えば現象発生時の_objectTypeCountが分かりそうですね。
ちょっといじってみます!

引用返信 編集キー/
■82272 / inTopicNo.29)  Re[23]: DataSetの破棄について
□投稿者/ sk (16回)-(2016/12/26(Mon) 17:25:48)
> 魔界の仮面弁士 さんに返信

結局、原因はわかりませんでしたが、Newをし続けると
32bit境界でオーバーフローすると客先に説明しました。
解せない部分はありますが、クローズとさせて頂きます。

環境まで作って確認していただき大変助かりました。
本当にありがとうございました。
解決済み
引用返信 編集キー/

<前の20件
トピック内ページ移動 / << 0 | 1 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -