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

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

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

Re[6]: XMLファイル保存


(過去ログ 171 を表示中)

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

■98671 / inTopicNo.1)  XMLファイル保存
  
□投稿者/ VB201初心者 (4回)-(2021/12/14(Tue) 15:04:24)

分類:[.NET 全般] 

Visual Basic 2010
XMLファイル保存
Windowsへの保存を速くする方法は、
ありますでしょうか?
HDD、SSDへの見た目上の保存は、それほど遅くないのですが
その後のWindowsへの保存に時間がかかるようです

電源ぶち切り形のPCとかを利用した時に時間がかかります。
何かいい方法がありますでしょうか?

''' <remarks></remarks>
Public Shared Sub Serialize(Of T)(ByVal objTarget As T, ByVal strFileName As String)

'DataContractSerializerオブジェクトを作成
'オブジェクトの型を指定する
Dim objSerializer As New System.Runtime.Serialization.DataContractSerializer(GetType(T))

'ファイルを開く
Using fs As New System.IO.FileStream(strFileName, System.IO.FileMode.Create)
'ファイルに保存
objSerializer.WriteObject(fs, objTarget)
End Using
End Sub

引用返信 編集キー/
■98673 / inTopicNo.2)  Re[1]: XMLファイル保存
□投稿者/ Azulean (1213回)-(2021/12/14(Tue) 20:47:40)
No98671 (VB201初心者 さん) に返信
> Windowsへの保存を速くする方法は、
> ありますでしょうか?

何か誤解されているように見えます。


> HDD、SSDへの見た目上の保存は、それほど遅くないのですが
> その後のWindowsへの保存に時間がかかるようです

本来は、Windows が管理するメモリバッファに書き込み→ HDD/SSD の物理媒体に書き込みという流れですので、このご質問の流れにはなりません。
見た目上、C:\ なり、D:\ なりのドライブに書き込みが完了したように見えても、あくまで「Windows が管理するメモリに書き込んで、HDD/SSD への反映待ち」になっているだけです。

Windows のバッファを無効にすれば、確かに HDD/SSD への書き込みと完全に同期しますが、遅くなるだけですよ?


> 電源ぶち切り形のPCとかを利用した時に時間がかかります。
> 何かいい方法がありますでしょうか?

言われていることがすべて真実であれば、どうしようもありません。
遅延バッファから HDD/SSD への書き込みは、HDD/SSD の速度に依存しますので、本来の実力値そのままのはずです。



ところで、本当に HDD/SSD への書き込みがボトルネックなんでしょうか?
どの部分が遅いのか、どのように測定・観察されているのでしょうか?
引用返信 編集キー/
■98677 / inTopicNo.3)  Re[2]: XMLファイル保存
□投稿者/ VB201初心者 (5回)-(2021/12/16(Thu) 20:41:03)
No98673 (Azulean さん) に返信
> ■No98671 (VB201初心者 さん) に返信
>>Windowsへの保存を速くする方法は、
>>ありますでしょうか?
>
> 何か誤解されているように見えます。
>
>
>>HDD、SSDへの見た目上の保存は、それほど遅くないのですが
>>その後のWindowsへの保存に時間がかかるようです
>
> 本来は、Windows が管理するメモリバッファに書き込み→ HDD/SSD の物理媒体に書き込みという流れですので、このご質問の流れにはなりません。
> 見た目上、C:\ なり、D:\ なりのドライブに書き込みが完了したように見えても、あくまで「Windows が管理するメモリに書き込んで、HDD/SSD への反映待ち」になっているだけです。
>
> Windows のバッファを無効にすれば、確かに HDD/SSD への書き込みと完全に同期しますが、遅くなるだけですよ?
>
>
>>電源ぶち切り形のPCとかを利用した時に時間がかかります。
>>何かいい方法がありますでしょうか?
>
> 言われていることがすべて真実であれば、どうしようもありません。
> 遅延バッファから HDD/SSD への書き込みは、HDD/SSD の速度に依存しますので、本来の実力値そのままのはずです。
>
>
>
> ところで、本当に HDD/SSD への書き込みがボトルネックなんでしょうか?
> どの部分が遅いのか、どのように測定・観察されているのでしょうか?

UWF対応のPCの場合、シャットダウン操作をせずにブレーカーなどをONからOFFしてぶち切り操作を行います。
保存操作をして5,6秒ですぐブレーカーをOFFするとファイルが壊れるようです。

引用返信 編集キー/
■98680 / inTopicNo.4)  Re[3]: XMLファイル保存
□投稿者/ Azulean (1216回)-(2021/12/17(Fri) 00:12:20)
2021/12/17(Fri) 00:14:22 編集(投稿者)

引用( > で始まる行)は必要最小限にしましょう。
そうしないと読みづらくなりますので。


No98677 (VB201初心者 さん) に返信
> UWF対応のPCの場合、シャットダウン操作をせずにブレーカーなどをONからOFFしてぶち切り操作を行います。
> 保存操作をして5,6秒ですぐブレーカーをOFFするとファイルが壊れるようです。

であれば、5-6 秒では足りないと言うことでしょう。
UWF の場合、再起動後に捨てられる領域への一時書き込み動作などもあるでしょうから、より遅くなるとは思います。

そして、それが速くできる可能性は薄く、できたとしても、その 10 秒とかかかる同期待ちの間、アプリの終了待ちをできるかどうかじゃないですかね。
UWF 環境で実験したことはないので、FlushFileBuffers で実現できるかも不明。
https://docs.microsoft.com/ja-jp/windows/win32/api/fileapi/nf-fileapi-flushfilebuffers


UWF はディスク書かないわけではないので、AC を直接切る運用は危ない気はしますけれども。


// タイトルにあった、XML とは無関係の話ですね。
引用返信 編集キー/
■98681 / inTopicNo.5)  Re[4]: XMLファイル保存
□投稿者/ VB201初心者 (6回)-(2021/12/17(Fri) 01:04:24)
No98680 (Azulean さん) に返信
> 2021/12/17(Fri) 00:14:22 編集(投稿者)
>
> 引用( > で始まる行)は必要最小限にしましょう。
> そうしないと読みづらくなりますので。
>
>
> ■No98677 (VB201初心者 さん) に返信
>>UWF対応のPCの場合、シャットダウン操作をせずにブレーカーなどをONからOFFしてぶち切り操作を行います。
>>保存操作をして5,6秒ですぐブレーカーをOFFするとファイルが壊れるようです。
>
> であれば、5-6 秒では足りないと言うことでしょう。
> UWF の場合、再起動後に捨てられる領域への一時書き込み動作などもあるでしょうから、より遅くなるとは思います。
>
> そして、それが速くできる可能性は薄く、できたとしても、その 10 秒とかかかる同期待ちの間、アプリの終了待ちをできるかどうかじゃないですかね。
> UWF 環境で実験したことはないので、FlushFileBuffers で実現できるかも不明。
> https://docs.microsoft.com/ja-jp/windows/win32/api/fileapi/nf-fileapi-flushfilebuffers
>
>
> UWF はディスク書かないわけではないので、AC を直接切る運用は危ない気はしますけれども。
>
>
> // タイトルにあった、XML とは無関係の話ですね。

ありがとうございます。検討させていただきます。

後、できれば最初に投降したXMLファイルの保存よりもっと高速に保存できる方法があれば
教えていただきたく思います。
DLL関数化するとか、何か他の関数があるとかあれば教えてください。

引用返信 編集キー/
■98682 / inTopicNo.6)  Re[5]: XMLファイル保存
□投稿者/ KOZ (192回)-(2021/12/17(Fri) 01:35:56)
No98681 (VB201初心者 さん) に返信
> 後、できれば最初に投降したXMLファイルの保存よりもっと高速に保存できる方法があれば
> 教えていただきたく思います。

電源停止の対策なら、FileStream の FileOptions.WriteThrough を試してみては?
ディスクに直接書き込むオプションです。

書き込み自体は遅くなりますが、処理は確実です。
引用返信 編集キー/
■98683 / inTopicNo.7)  Re[5]: XMLファイル保存
□投稿者/ Azulean (1217回)-(2021/12/17(Fri) 06:51:07)
2021/12/17(Fri) 07:04:28 編集(投稿者)

No98681 (VB201初心者 さん) に返信
> 後、できれば最初に投降したXMLファイルの保存よりもっと高速に保存できる方法があれば
> 教えていただきたく思います。

コードによるので、コードを開示しない状態では議論が成り立ちません。

シリアライズする量や制約によってはそれ以上速くならないこともありますので。


基本的にはプロファイラー(どのコードにどの程度のコストがかかっているかを調べるツール)を用いて把握しながら、シリアライズする量の削減、XML 内の表現の変更によるコスト削減を考えるところです。

たとえば、巨大な配列をそのまま XML に埋め込んでいたら XML が肥大化、かつ遅くなりますが、BASE64 エンコードで保存するとマシになるとかありますが、出力される XML フォーマットは変わってしまいます。フォーマット変化を受け入れられないなら高速化できないという例ですね。
引用返信 編集キー/
■98684 / inTopicNo.8)  Re[1]: XMLファイル保存
□投稿者/ 魔界の仮面弁士 (3252回)-(2021/12/17(Fri) 10:07:23)
2021/12/17(Fri) 10:14:44 編集(投稿者)

No98671 (VB201初心者 さん) に返信
> 電源ぶち切り形のPCとかを利用した時に時間がかかります。

「電源ブチ切り」は株式会社インタフェースの登録商標ですね。
「電源ぶち切り形」がそれと同じものを指しているかは別として。


> HDD、SSDへの見た目上の保存は、それほど遅くないのですが
> その後のWindowsへの保存に時間がかかるようです

UWF オーバーレイ領域の場合、再起動後や強制断後には変更が失われ、
UWF 有効化直前の状態に戻りますよね。「Windows への保存」は行われないのでは…?

除外対象のフォルダーもしくはボリュームに対する操作であれば
実際に CF や SSD に対しても書き込まれますが、それは保護の対象外だと思います。

また、ストレージへの保存にはライトキャッシュのフラッシュ遅延があるので、
書き込みした瞬間にストレージに保存されるわけではありません。

ストレージへの保存を目的とした、UWF 領域外への書き込みが前提なら、
 Const FILE_FLAG_NO_BUFFERING As Integer = &H20000000
 Dim fo As FileOptions = FileOptions.WriteThrough Or FileOptions.SequentialScan Or CType(FILE_FLAG_NO_BUFFERING, FileOptions)
でどうでしょう。(手元に環境が無いので試せませんが…)
https://docs.microsoft.com/en-us/windows/win32/fileio/file-buffering

ライトキャッシュを使わない分、見た目上のアクセス時間は少しのびるかもしれませんが、
メモリキャッシュを経由せずにストレージへの保存が行われるので、
保存精度はあがる気がします。
FILE_FLAG_NO_BUFFERING 指定だと、ボリューム セクタの倍数単位での
アクセスが必要らしいので、この設定が弾かれるようであれば、
KOZ さんが書かれていた WriteThrough (FILE_FLAG_WRITE_THROUGH) だけでも。
引用返信 編集キー/
■98685 / inTopicNo.9)  Re[2]: XMLファイル保存
□投稿者/ 魔界の仮面弁士 (3253回)-(2021/12/17(Fri) 11:45:48)
No98684 (魔界の仮面弁士) に追記
> また、ストレージへの保存にはライトキャッシュのフラッシュ遅延があるので、
> 書き込みした瞬間にストレージに保存されるわけではありません。

WriteThrough 指定以外の手段として…
FileStream での出力後に、明示的に
 fs.Flush(flushToDisk:=True)
を呼び出してみるのはどうでしょうか。(当方未検証)

ちなみに引数無しの fs.Flush() は、False 指定と同義です。


OS のライトキャッシュのフラッシュ操作は非同期的ですが、
Flush メソッドの引数に True を渡した場合、
内部的に FlushFileBuffers API が呼び出されることで
即時的にメモリバッファの内容がファイルへと書き込まれます。
引用返信 編集キー/
■98697 / inTopicNo.10)  Re[3]: XMLファイル保存
□投稿者/ くま (65回)-(2021/12/18(Sat) 00:48:37)
組み込み系の話ですが

組み込み系OS「Windows 10 IoT」の特色とは?
https://www.tegakari.net/2020/07/windows-10-iot/

(8)Unified Write Filter

にも記載があるのですがUWFはあくまで「起動時の状態を保護しておく」のが目的ですから
起動していたアプリの更新された情報の保護では使えないと思いますけど...。

というより発想を変えられたほうが良いかと思います。

今回xmlに保存しておきたいのは「あるクラスの値の状態を保存しておきたい」からだと思います。
よって「あるクラスの値が変更されるたびにxmlファイルに保存」しておけば
電源が切られてもその位置での値は保存されます。

サンプルです
「Class1」というクラスの値をxmlに保存するとします。
「Class1」には[Value1]と[Value2]のプロパティを用意
各値が変更された時に"D:\Class1.xml"として自動保存されます。
引用返信 編集キー/
■98698 / inTopicNo.11)  Re[4]: XMLファイル保存
□投稿者/ くま (66回)-(2021/12/18(Sat) 00:49:03)
Public Class Class1

    Private _Value1 As String = ""
    Public Property Value1 As String
        Get
            Return Me._Value1
        End Get
        Set(value As String)
            Me._Value1 = value
            Call SaveClass1(Me) '値が変更された時ファイルに保存を行う
        End Set
    End Property

    Private _Value2 As String = ""
    Public Property Value2 As String
        Get
            Return Me._Value2
        End Get
        Set(value As String)
            Me._Value2 = value
            Call SaveClass1(Me) '値が変更された時ファイルに保存を行う
        End Set
    End Property

End Class

Module Module1
    Const fileName As String = "D:\class1.xml"

    'Class1をxmlファイルで保存
    Public Sub SaveClass1(ByRef cls As Class1)
        Try
            Dim serializer As New System.Xml.Serialization.XmlSerializer(GetType(Class1))
            Using sw As New System.IO.StreamWriter(fileName, False, New System.Text.UTF8Encoding(False))
                serializer.Serialize(sw, cls)
            End Using
        Catch ex As System.IO.IOException
            'xmlファイルを読込時発生するので無条件でスルー
        End Try
    End Sub

    'xmlファイルを読み込みClass1に展開
    Public Sub LoadClass1(ByRef cls As Class1)
        If System.IO.File.Exists(fileName) Then
            Dim serializer As New System.Xml.Serialization.XmlSerializer(GetType(Class1))
            Using sr As New System.IO.StreamReader(fileName, New System.Text.UTF8Encoding(False))
                cls = DirectCast(serializer.Deserialize(sr), Class1)
            End Using
        Else
            cls = New Class1
        End If
    End Sub

End Module

テスト用フォーム
Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button2.Click
        'ストップウォッチを開始する 
        Dim sw As New System.Diagnostics.Stopwatch()
        sw.Start()

        Dim cls As Class1 = Nothing
        Call LoadClass1(cls)
        cls.Value1 = "test3"
        cls.Value2 = "test4"

        'ストップウォッチを止め結果を表示する 
        sw.Stop()
        Debug.Print("{0}", sw.Elapsed)
    End Sub
End Class

引用返信 編集キー/
■98699 / inTopicNo.12)  Re[5]: XMLファイル保存
□投稿者/ くま (67回)-(2021/12/18(Sat) 00:54:13)
環境によって変わるかもしれませんが(OSや記録媒体、値の変更回数等)
私の環境ではxmlファイルへの書き込みを追加してもそれほど遅くなったようにはなりませんでした。
よければお試しください


引用返信 編集キー/
■98700 / inTopicNo.13)  Re[4]: XMLファイル保存
□投稿者/ 魔界の仮面弁士 (3255回)-(2021/12/18(Sat) 08:41:10)
No98697 (くま さん) に返信
> よって「あるクラスの値が変更されるたびにxmlファイルに保存」しておけば
> 電源が切られてもその位置での値は保存されます。

保存中に終了されてしまった場合に備えて、ファイルを毎回上書きするのではなく、
別のファイルに保存するのも良いかもしれません。

たとえば奇数回目は File1.xml、偶数回目は File2.xml に保存するなど。

そしてロード時は、ファイルのタイムスタンプを見て新しい方を読み込む仕組みにしつつ、
そのファイルが破損していた場合は、もう一方のファイルから読み取るようにするなど。
引用返信 編集キー/
■98704 / inTopicNo.14)  Re[5]: XMLファイル保存
□投稿者/ ???? (3回)-(2021/12/18(Sat) 13:33:40)
2021/12/18(Sat) 13:35:06 編集(投稿者)

訂正
引用返信 編集キー/
■98705 / inTopicNo.15)  Re[6]: XMLファイル保存
□投稿者/ くま (68回)-(2021/12/18(Sat) 13:35:29)
No98700 (魔界の仮面弁士 さん) に返信
> 保存中に終了されてしまった場合に備えて、ファイルを毎回上書きするのではなく、
> 別のファイルに保存するのも良いかもしれません。
>
> たとえば奇数回目は File1.xml、偶数回目は File2.xml に保存するなど。

今回処理がややこしそうだったので省いたのですが
たしかに2ファイルなら簡単そうですですね。

後無条件でプロパティに設定時保存ですが「値が変わったら」にすれば回数も減ると思います。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

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

管理者用

- Child Tree -