8

XmlUnit を使用して 2 つの XML ファイルから違いを取得するアプリケーションがあります。しかし問題は、XmlUnit が JDOM を使用していることです。私のxmlファイルは最大1GBです!

これらの xml を JDOM ドキュメントに格納するには、RAM が多すぎます。

SlimJDOMFactory を使用しようとしましたが、それでも RAM の使用量が多すぎます!!

実際には、XML ファイル内を前後に移動する必要があります。JDOM がなければ、簡単な方法は見つかりませんでした。

誰でも助けることができますか?

JDOM ドキュメントの作成方法に関するコードのサンプルを次に示します。

    private org.jdom2.Document refDocJdom2;
    private org.jdom2.Document resDocJdom2;
    SAXBuilder sxb = new SAXBuilder(); 
    sxb.setJDOMFactory(new SlimJDOMFactory());

    popmsg("Validating reference file...");
    try {
        refDocJdom2 = sxb.build(referenceXML_Path); 
    } catch (Exception e) { 
        JOptionPane.showMessageDialog(null, "Error while parsing   Reference : "+referenceXML_Path+" file.\nCheck XML file validity.");
        return;
    }
    popmsg("Reference file validated");

    popmsg("Validating result file....");
    try {
        resDocJdom2 = sxb.build(resultXML_Path); 
    } catch (Exception e) { 
        JOptionPane.showMessageDialog(null, "Error while parsing result "+resultXML_Path+" file.\nCheck XML file validity.");
        return;
    }
    popmsg("Result file validated");
    popmsg("Validation Done.");

    getDifferencies(referenceXML_Path, resultXML_Path);
    d2 = new Date();

  }
public void getDifferencies(String fileRef, String fileRes) throws SAXException, IOException {
    popmsg("Documents : VALID XML format");
    popmsg("Shearching for differencies....");

    Reader refReader;

    refReader = new FileReader(fileRef);
    Reader resReader = new FileReader(fileRes);
    Diff aDifference = new Diff(refReader, resReader);

    if(refReader != null){
        refReader.close();
    }
    refReader = null;

    if(resReader != null){
        resReader.close();
    }
    resReader = null;

    //TODO
     //     XMLUnit.setIgnoreWhitespace(true);

    myDetailledDiff = new DetailedDiff(aDifference);
    myDetailledDiff.overrideDifferenceListener(new IgnoreNamedElementsDifferenceListener());
    myDetailledDiff.overrideElementQualifier(new ElementNameAndAttributeQualifier()); 
    allDiffs = myDetailledDiff.getAllDifferences();
    myDetailledDiff = null;

    popmsg("Got all differencies...\nGoing to Sort them now...");

    popmsg("Diff SIZE : "+allDiffs.size());
    myDiffsList = new ArrayList<MyDifference>(allDiffs.size());
    if(allDiffs.size() > 0){
        Difference aDiff;
        for (int i = 0; i < allDiffs.size(); i++){
            aDiff =  (Difference) allDiffs.get(i);

            myDiffsList.add(new MyDifference(aDiff, refDocJdom2, resDocJdom2));

            if(myDiffsList.size() == LIMIT)
                return ;
            if (i%25 == 0 && i!= 0){
                popmsg("**************************************************\t"+i+"\n");
            }
        }

        allDiffs.clear();
        allDiffs = null;

    }else{
        popmsg("NO DIFERENCIES");
    }
}
4

1 に答える 1

10

JDOM は、XML ドキュメント全体をメモリに読み込みます。これは、メモリベースの XML モデル (XOM/DOM/JDOM など) では「正常」です。これは、これらのシステムのよく知られた弱点でもあります。最終的に、この問題を解決する方法はありませんが、XML 全体のインメモリ表現を保持したままです。

XML ドキュメント (通常は UTF-8) を読み取る場合、ディスク上の 1 GB のデータは通常、メモリ内の文字数 (約 2 GB) に比例して変換されます。これは、1 GB の XML ドキュメントに対して「予算」を設定する必要があります。

SlimJDOMFactory は、新しいものへの参照を保持する代わりに、XML 内で文字列を再利用し、本質的に文字列値の重複を排除します。これは、同じ名前の要素、タグ、およびその他の構造が多数ある場合に非常に便利です。たとえば、SlimJDOMFactory を使用しない場合、1M<tag />の要素を持つ XML ドキュメントには、それぞれ独自の名前を持つ 1M の異なる Element インスタンスが含まれますtag。仮定tag約 32Byte オブジェクトの場合、これらの文字列を格納するには約 32MB が必要になります。SlimJDOMFactory はそれをわずか 32 バイトに減らしますが、それは「これまでのところ」しか進んでおらず、ドキュメントが大きくなるにつれてより多くのスペースが必要になるという事実を解決しません.....実行すると「遅延」するだけですメモリ不足です。良い面と悪い面の両方の影響があります....: 良いです。スキャンに使用されるメモリが少なくなるため、ガベージ コレクションの時間が短縮されます。私のテストでは、数回の GC サイクルでもメモリ内に存在するドキュメントの場合、メモリ内フットプリントが小さいことの正味の利点がすぐに実現され、解析側のパフォーマンス コストが「回収」されることが示されています。

この問題の一般的な解決策は次のとおりです。

  1. SAXを直接使用し、メモリ内モデルをまったく持たない....
  2. 入力ファイルを小さなチャンクに分割します。これは通常の解決策であり、多くの理由で非常に理にかなっています (待ち時間が短縮される、ファイルを並行して解析できるなど)。
  3. XML をまだ有効な XML であるセクションに論理的に分割し、ファイルのサブセットで特別な InputStreams を使用してファイルの一部を解析します。
  4. システムにメモリを追加します。
  5. 必要のないことがわかっているコンテンツをスキップするカスタム JDOMFactory を使用します (JDOMFactory は、ドキュメントの SAXBuild プロセスの一部として呼び出されます...そのため、実際には、必要になることがわかっているサブセットだけにファイルの内容を「トリム」することができます.. .... それでも、メモリ内の JDOM ドキュメントとナビゲート可能なドキュメント (残っているもの) になります。

これらのソリューションはどれも「優れた」ものではありませんが、インメモリ XML システムを使用することで得られるものです。

于 2014-05-23T12:33:01.327 に答える