197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes/*
297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * Copyright (C) 2010 Google Inc.
397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes *
497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * you may not use this file except in compliance with the License.
697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * You may obtain a copy of the License at
797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes *
897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * http://www.apache.org/licenses/LICENSE-2.0
997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes *
1097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * Unless required by applicable law or agreed to in writing, software
1197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
1297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * See the License for the specific language governing permissions and
1497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes * limitations under the License.
1597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes */
1697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes
1797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughespackage benchmarks;
1897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes
1997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport com.google.caliper.Param;
2097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport com.google.caliper.Runner;
2197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport com.google.caliper.SimpleBenchmark;
2297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport java.io.ByteArrayInputStream;
2397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport java.io.ByteArrayOutputStream;
2497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport java.io.FileInputStream;
2597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport java.io.IOException;
2697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport java.lang.reflect.Constructor;
2797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport java.util.Arrays;
2897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport java.util.List;
2997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport javax.xml.parsers.DocumentBuilder;
3097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport javax.xml.parsers.DocumentBuilderFactory;
3197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport javax.xml.parsers.SAXParser;
3297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport javax.xml.parsers.SAXParserFactory;
3397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport org.w3c.dom.Document;
3497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport org.w3c.dom.Node;
3597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport org.xml.sax.Attributes;
3697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport org.xml.sax.SAXException;
3797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport org.xml.sax.helpers.DefaultHandler;
3897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughesimport org.xmlpull.v1.XmlPullParser;
3997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes
4097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughespublic class XmlParseBenchmark extends SimpleBenchmark {
4197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes
4297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    @Param String xmlFile;
4397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    ByteArrayInputStream inputStream;
4497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes
4597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    static List<String> xmlFileValues = Arrays.asList(
4697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes            "/etc/apns-conf.xml",
4797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes            "/etc/media_profiles.xml",
4897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes            "/etc/permissions/features.xml"
4997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    );
5097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes
5197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    private SAXParser saxParser;
5297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    private DocumentBuilder documentBuilder;
5397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    private Constructor<? extends XmlPullParser> kxmlConstructor;
5497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    private Constructor<? extends XmlPullParser> expatConstructor;
5597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes
5697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    @SuppressWarnings("unchecked")
5797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    @Override protected void setUp() throws Exception {
5897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        byte[] xmlBytes = getXmlBytes();
5997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        inputStream = new ByteArrayInputStream(xmlBytes);
6097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        inputStream.mark(xmlBytes.length);
6197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes
6297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
6397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        saxParser = saxParserFactory.newSAXParser();
6497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes
6597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
6697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        documentBuilder = builderFactory.newDocumentBuilder();
6797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes
6897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        kxmlConstructor = (Constructor) Class.forName("org.kxml2.io.KXmlParser").getConstructor();
6997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        expatConstructor = (Constructor) Class.forName("org.apache.harmony.xml.ExpatPullParser")
7097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes                .getConstructor();
7197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    }
7297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes
7397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    private byte[] getXmlBytes() throws IOException {
7497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        FileInputStream fileIn = new FileInputStream(xmlFile);
7597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
7697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        int count;
7797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        byte[] buffer = new byte[1024];
7897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        while ((count = fileIn.read(buffer)) != -1) {
7997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes            bytesOut.write(buffer, 0, count);
8097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        }
8197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        fileIn.close();
8297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        return bytesOut.toByteArray();
8397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    }
8497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes
8597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    public int timeSax(int reps) throws IOException, SAXException {
8697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        int elementCount = 0;
8797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        for (int i = 0; i < reps; i++) {
8897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes            inputStream.reset();
8997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes            ElementCounterSaxHandler elementCounterSaxHandler = new ElementCounterSaxHandler();
9097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes            saxParser.parse(inputStream, elementCounterSaxHandler);
9197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes            elementCount += elementCounterSaxHandler.elementCount;
9297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        }
9397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        return elementCount;
9497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    }
9597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes
9697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    private static class ElementCounterSaxHandler extends DefaultHandler {
9797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        int elementCount = 0;
9897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        @Override public void startElement(String uri, String localName,
9997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes                String qName, Attributes attributes) {
10097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes            elementCount++;
10197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        }
10297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    }
10397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes
10497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    public int timeDom(int reps) throws IOException, SAXException {
10597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        int elementCount = 0;
10697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        for (int i = 0; i < reps; i++) {
10797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes            inputStream.reset();
10897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes            Document document = documentBuilder.parse(inputStream);
10997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes            elementCount += countDomElements(document.getDocumentElement());
11097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        }
11197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        return elementCount;
11297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    }
11397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes
11497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    private int countDomElements(Node node) {
11597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        int result = 0;
11697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        for (; node != null; node = node.getNextSibling()) {
11797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes            if (node.getNodeType() == Node.ELEMENT_NODE) {
11897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes                result++;
11997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes            }
12097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes            result += countDomElements(node.getFirstChild());
12197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        }
12297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        return result;
12397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    }
12497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes
12597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    public int timeExpat(int reps) throws Exception {
12697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        return testXmlPull(expatConstructor, reps);
12797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    }
12897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes
12997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    public int timeKxml(int reps) throws Exception {
13097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        return testXmlPull(kxmlConstructor, reps);
13197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    }
13297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes
13397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    private int testXmlPull(Constructor<? extends XmlPullParser> constructor, int reps)
13497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes            throws Exception {
13597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        int elementCount = 0;
13697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        for (int i = 0; i < reps; i++) {
13797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes            inputStream.reset();
13897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes            XmlPullParser xmlPullParser = constructor.newInstance();
13997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes            xmlPullParser.setInput(inputStream, "UTF-8");
14097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes            int type;
14197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes            while ((type = xmlPullParser.next()) != XmlPullParser.END_DOCUMENT) {
14297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes                if (type == XmlPullParser.START_TAG) {
14397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes                    elementCount++;
14497aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes                }
14597aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes            }
14697aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        }
14797aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        return elementCount;
14897aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    }
14997aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes
15097aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    public static void main(String[] args) {
15197aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes        Runner.main(XmlParseBenchmark.class, args);
15297aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes    }
15397aba27f961a5a6f37dcaf7f455df371e250ede3Elliott Hughes}
154