2

Delphiを使用して、リレーショナルデータベースのデータからXMLドキュメントを作成しています。小さなデータセットでも問題なくテストできますが、データセットのサイズを本番レベルに拡張しようとすると、ノードの作成中にEOutOfMemory例外が発生します。

フォームにドロップされたTXMLDocument(ベンダーとしてMSXML)を使用していますが、コードは通常次のようになります。

  DS := GetDS(Conn, 'SELECT Fields. . . FROM Table WHERE InsuredID = ' +IntToStr(AInsuredID));

  try

    while not DS.Eof do
      with ANode.AddChild('LE') do
      begin
        AddChild('LEProvider').Text := DS.FieldByName('LEProvider').AsString;
        // Need to handle "other" here
        AddChild('Date').Text       := DateToXMLDate(DS.FieldByName('LEDate').AsDateTime);
        AddChild('Pct50').Text      := DS.FieldByName('50Percent').AsString;
        AddChild('Pct80').Text      := DS.FieldByName('80Percent').AsString;
        AddChild('Actuarial').Text  := DS.FieldByName('CompleteActuarial').AsString;
        AddChild('Multiplier').Text := DS.FieldByName('MortalityMultiplier').AsString;
        DS.Next;
      end;

  finally

    DS.Free;

  end;

このセクション、およびさまざまなデータベーステーブルに適用される他の多くの同様に構築されたセクションでは、何度も実行されました。この例では、ANodeは、コンテナーとして使用するために関数に渡されるIXMLNodeです。

結果として得られるディスク上のXMLファイルが10メガバイトを超えるとは思わない。XMLNodeの作成と廃棄でメモリリークが発生していると思いますが、問題を追跡する方法を理解するのに十分なインターフェイスに精通していません。

4

3 に答える 3

3

TXMDocument は DOM スタイルのインターフェイスであり、ドキュメント全体をメモリに保持します。メモリはそのようにかなり早く使い果たされます。結果のファイルがそれほど大きくない場合でも。単純な XML を書き出すのに TXMLDocument は必要ありません。xml 形式のファイルに直接書き込んでみませんか?

そうは言っても、ヒープの断片化によるエラーであるか、実際のメモリリークである可能性もあります。ここに記載されているようなツールを試してみてください: Profiler and Memory Analysis Tools for Delphi

于 2009-09-30T18:43:32.913 に答える
0

これらの各呼び出しの結果は、コンパイラによって暗黙的に宣言AddChildされた一時変数に格納されます。IXmlNodeそれらは、現在のサブルーチンが戻ったときに (通常または例外によって) 自動的にクリーンアップされる必要があります。独自の変数を宣言することで、それらの有効期間をより明示的にすることができます。

var
  le, child: IXmlNode;
begin
  DS := GetDS(Conn, Format(Query, [AInsuredID]));
  try
    while not DS.Eof do begin
      le := ANode.AddChild('LE');
      child := le.AddChild('LEProvider');
      child.Text := DS.FieldByName('LEProvider').AsString;
      // Need to handle "other" here
      child := le.AddChild('Date');
      child.Text := DateToXMLDate(DS.FieldByName('LEDate').AsDateTime);
      child := le.AddChild('Pct50');
      child.Text := DS.FieldByName('50Percent').AsString;
      child := le.AddChild('Pct80');
      child.Text := DS.FieldByName('80Percent').AsString;
      child := le.AddChild('Actuarial');
      child.Text := DS.FieldByName('CompleteActuarial').AsString;
      child := le.AddChild('Multiplier');
      child.Text := DS.FieldByName('MortalityMultiplier').AsString;
      DS.Next;
    end;
  finally
    DS.Free;
  end;
end;

上記のコードには、暗黙的なインターフェイス変数はありません。コンパイラは呼び出しごとに新しい暗黙的変数を宣言しますAddNodeが、上記のコードは、child新しい子ノードごとに再利用できるため、必要な変数は 2 つだけであることを示しています。

ただし、そのコードだけで極端な量のメモリが使用されることはありません。本当に必要なくなったオブジェクトへの参照を保持している可能性が高いか、一部のインターフェイス オブジェクトの循環参照を作成している可能性が高くなります。MSXML ライブラリは独自の循環参照を作成するべきではありませんが、ここで実行されている可能性のあるすべてのコードを示していません。

于 2009-09-30T18:50:36.503 に答える
0

DOM ではなく SAX パーサーを使用してみてください。DOM は、XML ファイル全体の表現をメモリに保持します。

ここで試してください

于 2009-09-30T22:12:45.463 に答える