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

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

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

WriteLineよりもvbNewLineの方が高速な理由

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

■97828 / inTopicNo.1)  WriteLineよりもvbNewLineの方が高速な理由
  
□投稿者/ ガチャピン (1回)-(2021/07/22(Thu) 22:12:28)

分類:[.NET 全般] 

2021/07/22(Thu) 22:12:56 編集(投稿者)
VB2015に関する質問です。

文字列を出力するのに
StringWriterとStreamWriterを使います。

改行するのに普通はWriteLineを使っているのですが、
Write(vbNewLine)でも改行できるため、どちらの方が高速だろうかと思って
計算時間を比較したところ、予想外にWrite(vbNewLine)の方が2倍程度高速であることが分かりました。

以下のテストしたコードです。


        Dim DataNum As Integer = 10000000


        Dim sw As New Stopwatch
        sw.Restart()


        Using writer2 As New StringWriter


            For i As Integer = 1 To DataNum


                '173 ms
                '   writer2.Write(vbNewLine)

                '350 ms
                '  writer2.WriteLine("")


                '640 ms
                'writer2.WriteLine("aaaaaaaaaaaa")

                '360 ms
                writer2.Write("aaaaaaaaaaaa")
                writer2.Write(vbNewLine)

                '247ms
                ' writer2.Write("aaaaaaaaaaaa" & vbNewLine)

            Next i



        End Using


        MsgBox(sw.ElapsedMilliseconds)


コードの判読性を比較すると

writer2.Write("aaaaaaaaaaaa" & vbNewLine)
よりも
writer2.WriteLine("aaaaaaaaaaaa")
の方が読みやすいと思います。

しかし、
writer2.Write("aaaaaaaaaaaa" & vbNewLine)
の方が高速であることが分かりました。

ではなぜWriteLineはこのように低速なのでしょうか?
内部ではWrite(vbNewLine)を実行しているわけではないのでしょうか?

もし、高速化できる方法があればお教えください。


引用返信 編集キー/
■97829 / inTopicNo.2)  Re[1]: WriteLineよりもvbNewLineの方が高速な理由
□投稿者/ サバ (5回)-(2021/07/23(Fri) 16:38:24)
"aaaaaaaaaaaa" & vbNewLineはコンパイル時に一つの文字列に置き換えられるから実行が速いのだろうね

WriteLineはGitHubでTextWriterのソース見ればわかるけれどもcharの配列を作成して\r\nを追加してるから遅いのだろうね

StringWriterはStringBuilderをラップしてるだけなのでStringBuilderを直接使った方が速いんじゃないかと思うけれども誤差みたいなものかなとも思う

文字列が固定なら"aaaaaaaaaaaa" & vbNewLineのような形でコンパイル時の定数化を使った方がよくて結合する文字列が動的で結合する数が2,3個ならStringBuilderの作成がボトルネックになってString.Concatの方が速くなるんじゃないかな知らないけど

Paizaのプログラミングコンテストで実行のスピード勝負になったときには扱う文字列が英数字だけなのを良いことに文字列ではなくてバイナリを直接読み書きするってことみんなやってた

引用返信 編集キー/
■97830 / inTopicNo.3)  WriteLineよりもvbNewLineの方が高速な理由
□投稿者/ ガチャピン (2回)-(2021/07/24(Sat) 11:47:09)
2021/07/24(Sat) 11:47:33 編集(投稿者)
ありがとうございます。


> Paizaのプログラミングコンテストで実行のスピード勝負になったときには扱う文字列が英数字だけなのを良いことに文字列ではなくてバイナリを直接読み書きするってことみんなやってた


これって文字列を読み込んで、何か処理をしてから
再度文字列を書き込むというものですか?


私がいまやりたいのは
single配列を文字列に変換して
CSVファイルとして保存することなのですが、
Encoding.ASCIIを自作することで高速化することはできるのでしょうか?

英語は含んでおらず
数値しかないため、




    Function aaa(stringValue$) As Byte()

        Dim charArray As Char() = stringValue.ToCharArray()

        Dim StNum As Integer = charArray.Length - 1
        Dim Hai(StNum) As Byte

        For i = 0 To StNum

            Dim Ch As Char = charArray(i)

            If Ch = "0" Then

                Hai(i) = 48

            ElseIf Ch = "1" Then

                Hai(i) = 49

            ElseIf Ch = "2" Then

                Hai(i) = 50

            ElseIf Ch = "3" Then

                Hai(i) = 51

            ElseIf Ch = "4" Then

                Hai(i) = 52

            ElseIf Ch = "5" Then

                Hai(i) = 53

            ElseIf Ch = "6" Then

                Hai(i) = 54

            ElseIf Ch = "7" Then

                Hai(i) = 55

            ElseIf Ch = "8" Then

                Hai(i) = 56

            ElseIf Ch = "9" Then

                Hai(i) = 57

            ElseIf Ch = "." Then

                Hai(i) = 46

            ElseIf Ch = "," Then

                Hai(i) = 44

            End If


        Next i

        Return Hai

    End Function


というようなメソッドを自作してみたのですが
10倍くらい遅くなってしまいました。


引用返信 編集キー/
■97831 / inTopicNo.4)  Re[3]: WriteLineよりもvbNewLineの方が高速な理由
□投稿者/ サバ (6回)-(2021/07/24(Sat) 13:11:07)
No97830 (ガチャピン さん) に返信
> 私がいまやりたいのは
> single配列を文字列に変換して
> CSVファイルとして保存することなのですが、
> Encoding.ASCIIを自作することで高速化することはできるのでしょうか?

いやー厳しいんじゃないかなー僕は自然数2,3個読み書きするだけだったからよかったけどSingleの配列はEncoding.ASCIIに任せるのがいいと思う

CSVの書き込みはそんなに遅くないと思うんだよねカンマでガチャーンしてドーンと書き込んで終わりだから素朴な実装が最適だと思う

ファイルが複数に分かれるようだったらパラレルで複数のファイルに書き込むことで処理時間は短縮できそうな気はする

それで要件満たせなかったら言語変えるとかかなーC言語とC++は難しそうだから僕ならGo言語の勉強を始めてみるかなー

引用返信 編集キー/
■97832 / inTopicNo.5)  Re[4]: WriteLineよりもvbNewLineの方が高速な理由
□投稿者/ kuma (1回)-(2021/07/24(Sat) 23:58:18)
テキストファイルの処理で重要なのは一度にどれだけ読み書きするかになります。
ガチャピンさんの言われる通りで
1.[1文字書き込みを100回] より [100文字書き込みを1回]のほうが早いです。
2.[100文字書き込まれているファイルに1文字追加]するより[1文字書き込まれているファイルに1文字追加]のほうが早いです。

1.の理由は文字をバイナリ変換するEncoding.ASCIIなどの処理が回数が多い程遅くなる
2.の理由はファイルの最終位置まで移動するまでに時間がかかる為です。

CSVとの事なので例えば100行までString型の配列で保持して(初めに1度のみ配列数を設定)
OKパターン
Dim Line() As String
Redim Line(0 to 99)

NGパターン
Redim Line(0 to 0)
Redim preserve Line(0 to 1)
...

Joinでまとめて
Dim Lines As string = String.Join(vbNewline, Line) & vbNewline

あとはファイルへ出力するだけで速さが変わります。
まあメモリ自体は消費しますが、昔のPCとはくらべものにならないほど空メモリも今はありますので問題ないかと
それでも遅い場合はWindows APIでStringをByte配列にコピーしてとかありますがあまり手間かけるとメンテで困りますから。

CSVなら1行辺り平均何文字で何行必要か書いてもらえればアドバイスもしやすいですね。
>
引用返信 編集キー/
■97833 / inTopicNo.6)  Re[5]: WriteLineよりもvbNewLineの方が高速な理由
□投稿者/ kuma (2回)-(2021/07/25(Sun) 00:06:12)
あと
OKパターン
Dim Line() As String
Redim Line(0 to 99)
Line(0)="aaaaa"
Line(1)="bbbbb"
...
Dim Lines As string = String.Join(vbNewline, Line) & vbNewline

NGパターン
Dim Lines As string = ""
Lines &= "aaaaa" & vbNewline
Lines &= "bbbbb" & vbNewline

今のPCで差がわかるかな?

引用返信 編集キー/

このトピックをツリーで一括表示


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

このトピックに書きこむ