9

Java SAX を使用して、非常に大きな XML ファイルを解析しています。characters実装は次のようになります。

@Override
public void characters(char ch[], int start, int length) throws SAXException {
    String value = String.copyValueOf(ch, start, length);
    ...
}

( ch[]SAX によって渡される配列はかなり長くなる傾向があります)

しかし、最近パフォーマンスの問題が発生しており、プロファイラーは、CPU 使用率の 20% 以上がString.copyValueOf(内部で呼び出さnew String(ch,start,length)れた) の呼び出しを上回っていることを示しています。

文字の配列から文字列を取得し、開始インデックスと長さを or より効果的に取得する方法はありますString.copyValueOf(ch, start, length)new String(ch,start,length)?

4

3 に答える 3

2

@Andremoniy が述べたように、String オブジェクトを使用する場合は、常に作成する必要があり、内容がコピーされます。

パーサーを高速化する唯一の方法は、新しく作成する文字列オブジェクトの数を最小限に抑えることです。

xml-structure のすべての要素に、開始タグと終了タグの間に生データが含まれているとは思いません。

そのため、データが重要な要素内にいる場合にのみ、文字列を作成することをお勧めします。さらに、可能な要素を何らかの方法で制限することをお勧めします。たとえば、階層レベルまたは親要素によって文字列比較の数を減らします。ただし、これはxml構造に依存します。

protected boolean readChars = false;
protected int level = -1;

@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
    ++level;

    if (level == 4) {
        if (qName.equalsIgnoreCase("TextElement")) {
            readChars = true;
        }
    }
 }

@Override
public void characters(char ch[], int start, int length) throws SAXException {
    if (readChars) {
        String value = String.copyValueOf(ch, start, length);
        ...
        readChars = false;
    }
}

@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
    --level;
}
于 2013-06-06T07:56:20.143 に答える
1

おそらく組み合わせて、characters1 つのタグ内で複数回呼び出される可能性があり、要素レベルでStringBuilderを保持することが適切な場合があります。これはSystem.arrayCopy.

于 2013-06-06T08:17:33.697 に答える