2017-10-14 38 views
1

私の質問にはすでに回答がありましたが、事前に申し訳ありませんが、数日前から検索しています。Excel VBA - populatingバリアント配列がメモリ使用量を増やす

バリアントの配置中にメモリが絶えず消費されるという問題があります。配列の大きさは、最初の大きさになると、メモリ消費量がどのくらい増えるのかが分かります。私は、コードの小片は言葉よりも良いそれを説明すると思います。このコードで

Sub test() 
Dim Arr(1 To 1000000, 1 To 10) As Variant 
Dim i As Long, j As Integer 

For i = 1 To 1000000 
    For j = 1 To 10 
     Arr(i, j) = "AAAAAAAAA" 
    Next j 

Next i 

End Sub 

私の経験はある - 配列寸法メモリ短所後。増加する。 160 MB(これは10 * 1 000 000 * 16)です。実行が終了した後、私は約400 MBの追加があります!興味深いことに、文字列AAAAを数字で置き換えると、この問題はなくなります。

実際のプログラム(これは単なるテストコードです)では、私はより大きな配列を持っています。 600 MBですが、コード実行の最後にメモリ使用量は3.4 GBです!その結果、 "メモリ不足"エラーが発生します。

誰でもこれを説明できますか?事前に

おかげで、 デン

+0

なぜ文字列を配列に格納すると、その配列を格納するために使用されるメモリが増加するのは驚くべきことですか?文字列自体はバリアント変数のメモリには格納されません。いずれにしても、Excel VBAはおそらくそのサイズのデータ​​にとって間違ったツールです。おそらく、Rのようなものを使用して(おそらく、特定のフロントエンドを維持したい場合は、Excelとやりとりすることができます)、戦略的な良い動きになるかもしれません。 –

+0

以下は、大量の文字列を格納するために大規模な配列を使用してメモリを大量に使用する理由を理解するのに役立ちます。http://bytecomb.com/vba-internals-whats-in-a-variable/ –

+0

私は親切ですこの仕事のために縛られるべきである。配列を宣言したため、メモリ消費量が増えるとは思っていませんでした。これは、必要なメモリを確保することを期待していました。この場合、16倍の16倍の倍数の列があります。配列が宣言されているときは、タスクマネージャで+160MBを参照してください。しかし、実行中にメモリ使用量が増えると、別の400 Mbがあるので、そのアレイサイズで合計660 Mbになりますか?そして、配列を倍精度で満たすとき、なぜメモリ消費は増加しないのですか?私は提案されたトピックを見ましたが、私は読んでリンク、ありがとう。 – Den

答えて

2

何バリアントが文字列が含まれている場合、実際の文字列データが内部に格納されていないことに起因する見ています。バリアントは16バイトで構成されます。これらの16バイトのレイアウトはhereと記載されています。これらのバイトのうち8つはタイプ情報のようなものを含み、他の8つはそのデータが数値であるときに実際のデータを含むことに注意してください。データが文字列の場合、これらの8バイトでは不十分です。代わりに、これらの8バイトには、文字列の長さを保持する4バイト、文字列内の実際の文字(文字あたり2バイト)、および2文字のNULL終端文字で構成されるBSTR構造体へのポインタが含まれています。長さ9の文字列の場合、それは24バイトになります。したがって、その文字列(およびそれが指すバリアント)を格納するために合計16 + 24 = 40バイトになります。これは、そのように格納するときに、1000万個の文字列を格納するために少なくとも400 MB必要な理由を説明します。

ご覧のとおり、バリアントはメモリ豚です。このためにExcel VBAを実際に使用する必要がある場合は、ペストのようなバリアントの配列を避ける必要があります。文字列自体はあまり効率的ではありません。おそらく、文字のASCIIコードをバイトとして保存したり、必要に応じて分割できる複数の文字列を1つの文字列に結合したりすることができます。

+0

John、シンプルで明確な説明をいただきありがとうございます!それは今や理解しています。私は基本的に変種が悪いと非効率であることを知っていたが、私は彼らがとても悪いことを知らなかった。私のデータは実際にはほとんど数字ですが、データ列のヘッダーが入っています。この場合、バリアントを使用するほうが簡単でした。なぜなら、テキストファイルをバイナリとして読み込んでデータを取得して、バリアント配列に分割して書き込む文字列を取得するという理由があります。しかし、問題が生じるので、ヘッダーには小さな文字列配列を、データには別のダブル配列を使用する必要があります。 – Den

関連する問題