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

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

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

Re[4]: Split関数の代替について


(過去ログ 46 を表示中)

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

■25034 / inTopicNo.1)  Split関数の代替について
  
□投稿者/ なかた (1回)-(2008/09/14(Sun) 10:44:58)

分類:[VB6 以前] 

はじめまして。VB6.0でCSVをファイルマッピングで読み込み、Split関数で改行コードで配列に分割するプログラムを作っています。

40MBのCSVでファイルの読み込みは数秒ですが、Splitで改行コード(vbcrlf)で配列に分割するのに30秒〜40秒くらいかかります。
改行コードで配列に分割するという処理をSplit関数以外の方法でSplit関数より高速に行う方法はありますか?

よろしくお願いします。
引用返信 編集キー/
■25037 / inTopicNo.2)  Re[1]: Split関数の代替について
□投稿者/ 魔界の仮面弁士 (852回)-(2008/09/14(Sun) 11:36:34)
No25034 (なかた さん) に返信
> はじめまして。VB6.0でCSVをファイルマッピングで読み込み、
CreateFileMapping API 等でしょうか?


> Splitで改行コード(vbcrlf)で配列に分割するのに30秒〜40秒くらいかかります。
これはつまり、
 Dim csv As String
 csv = [サイズ40MB相当の文字列]
の処理は、(ファイルマッピング等により)数秒程度まで短縮できたが、その後の
 list = Split( [サイズ40MB相当の文字列], vbCrLf)
の処理に、数十秒かかるという事でしょうか?


手元の環境で試してみましたが、15列×3.6万行の CSV データ
(サイズでいうと、45,961,380 バイト) のファイルでも、API 無しで
読み込みから Split まで、6 秒未満程度で完了するのですが…。


Option Explicit

Private CSV As String
Private rows() As String
Private Sub Command1_Click()
    Dim before As Single
    Dim after As Single
    before = Timer
    
    rows = Split(CSV, vbCrLf)
    
    after = Timer
    Debug.Print "Split:"; after - before, "("; before, after; ")"
End Sub

Private Sub Form_Load()
    Dim before As Single
    Dim after As Single
    before = Timer

    Dim stm As ADODB.Stream
    Set stm = New ADODB.Stream
    stm.Type = adTypeBinary
    stm.Open
    stm.LoadFromFile "C:\Book1.csv"
    Dim b() As Byte
    b = stm.Read(adReadAll) '
    stm.Close
    CSV = StrConv(b, vbUnicode)

    after = Timer
    Debug.Print " Load:"; after - before, "("; before, after; ")"
End Sub

引用返信 編集キー/
■25038 / inTopicNo.3)  Re[2]: Split関数の代替について
□投稿者/ 魔界の仮面弁士 (853回)-(2008/09/14(Sun) 12:06:49)
No25037 (魔界の仮面弁士 さん) に返信
>>Splitで改行コード(vbcrlf)で配列に分割するのに30秒〜40秒くらいかかります。
> 手元の環境で試してみましたが、15列×3.6万行の CSV データ
> (サイズでいうと、45,961,380 バイト) のファイルでも、API 無しで
> 読み込みから Split まで、6 秒未満程度で完了するのですが…。

もしかして、カンマ区切りでも分割し、二次元配列あるいはジャグ配列にしているのかと思い、
コードに手を加えてみましたが、それでも +3.5 秒程度の増加にしかなりませんでした。

数十秒という結果にならない所を見ると、
 ・データ内容の違い(カンマを含むデータなども考慮している?)
 ・実行環境による違い(マシンスペック、あるいは常駐セキュリティソフトによる速度低下など)
 ・そもそものコードの違い
など、他の要因があるのかも知れませんが、これ以上は分かりません。m(_ _;)m


Private CSV As String
Private rows() As String
Private matrix() As Variant

Private Sub Command2_Click()
    rows = Split(CSV, vbCrLf)
    ReDim matrix(UBound(rows))

    Dim n As Long
    For n = LBound(rows) To UBound(rows)
        matrix(n) = Split(rows(n), ",")
    Next
End Sub

# OS: WindowsXP Service Pack 3
# VB: Visual Basic 6.0 Service Pack 6
# PC: DELL DIMENSION C521
# CPU: AMD Athlon 64 3800+ (2.0GHz)
# MEM: 2048MB

引用返信 編集キー/
■25059 / inTopicNo.4)  Re[3]: Split関数の代替について
□投稿者/ なかた (2回)-(2008/09/14(Sun) 23:04:33)
ご回答いただきありがとうございます。

今、手元にVB環境が無いので確認ができないのですが読み込むCSVの行数が30万行ありました。
(1行あたりのデータ量が少ない為です)
行数に比例して時間がかかるのでしょうか?

VBのSplit関数と同等の処理をより高速に処理する方法はありますか?
引用返信 編集キー/
■25060 / inTopicNo.5)  Re[4]: Split関数の代替について
□投稿者/ 魔界の仮面弁士 (854回)-(2008/09/15(Mon) 00:21:32)
No25059 (なかた さん) に返信
> 行数に比例して時間がかかるのでしょうか?

試しに、300万行(94.2MB) のファイルを使って実行したところ、7回平均で144秒程度かかりました。

# OS: Windows Vista Business (x64) Service Pack 無し
# VB: Visual Basic 6.0 Service Pack 6
# PC: HP Compaq 2710p Tablet
# CPU: 超低電圧版 Core 2 Duo U7500 (1.06GHz)
# MEM: 4096MB

環境が異なるので、単純な比較はできませんが、
   3.6万行 : 2.8〜3.2秒 : 私の環境  (No25037)  …… 単純計算で「1.1〜1.2万行/秒」
  30.0万行 :  30〜40秒  : なかたさん(No25034)  …… 単純計算で「0.8〜1.0万行/秒」
 300.0万行 : 140〜150秒 : 私の環境  (No25060)  …… 単純計算で「2.0〜2.1万行/秒」
という結果でした。

HDD速度やメモリ量など、マシンスペックやデータ量にもよるのでしょうが、
どうやら秒間1〜2万行が Split の処理限界といったところなのかも知れません。

引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -