Excel読み込み処理のパフォーマンス比較。
チョーざっくりと、POI、JExcelAPI、XPath、StAXで
Excelを読み込んだらどうなるかを計測してみた。
全くチューニングしてないし、
いい加減な測定なので、結果は参考程度に。
- 方法
結果
ツール | 1回(ms) | 3回(ms) | 10回(ms) | 100回(ms) |
---|---|---|---|---|
POI | 250 | 281 | 297 | 484 |
JExcelAPI | 172 | 297 | 688 | 6125 |
JExcelAPI (GCなし) | 0 or 16 | 78 | 312 | 3438 |
XPath | 109 | 172 | 391 | 2203 |
StAX | 0 or 16 | 15 | 31 | 141 |
(2008/2/29 JExcelAPIにsetGCDisabled(true)の場合の結果を追加)
POIは内部キャッシュでも効いているのか、
繰り返し読み込みした時に、性能が落ちないのが良い。
JExcelAPIは逆にキャッシュが効いてなさそうで、
1回読み込みならPOIより早いけど、あとはシーケンシャルに増えていく。
特にGCなしの場合のパフォーマンスは秀逸だけど、
シーケンシャルに増えていく所はあまり変わらない。
XPathはごめん、僕の書き方が悪い可能性が高い。
でも、いくら頑張ってもStAXより早くなることはなさそう。
ということで、StAXはXMLStreamReaderで全部読み取ってるんだけど、早い。
XMLSpreadSheetの仕様さえ把握できるなら、これが一番有利。
ソースコードを読みたい人は、続きを読んでください。
import java.io.InputStream; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamConstants; import javax.xml.stream.XMLStreamReader; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathFactory; import jxl.Cell; import jxl.Sheet; import jxl.Workbook; import jxl.WorkbookSettings; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.w3c.dom.Document; public class ExcelRead { private static final int trial = 100; private static WorkbookSettings settings = new WorkbookSettings(); private static XPathFactory xpathFactory = XPathFactory.newInstance(); private static XPath xpath = xpathFactory.newXPath(); private static DocumentBuilderFactory df = DocumentBuilderFactory .newInstance(); private static XMLInputFactory factory = XMLInputFactory.newInstance(); public static void main(String[] args) throws Exception { settings.setGCDisabled(true); long start = System.currentTimeMillis(); for (int i = 0; i < trial; i++) { readByPoi(); } System.out.println(System.currentTimeMillis() - start); start = System.currentTimeMillis(); for (int i = 0; i < trial; i++) { readByJExcelAPI(); } System.out.println(System.currentTimeMillis() - start); start = System.currentTimeMillis(); for (int i = 0; i < trial; i++) { readByJExcelAPINoGC(); } System.out.println(System.currentTimeMillis() - start); start = System.currentTimeMillis(); for (int i = 0; i < trial; i++) { readByXPath(); } System.out.println(System.currentTimeMillis() - start); start = System.currentTimeMillis(); for (int i = 0; i < trial; i++) { readByStAX(); } System.out.println(System.currentTimeMillis() - start); } private static void readByPoi() throws Exception { StringBuilder builder = new StringBuilder(45); InputStream in = ExcelRead.class.getResourceAsStream("/test.xls"); try { HSSFWorkbook book = new HSSFWorkbook(in); HSSFSheet sheet = book.getSheetAt(0); int rowNum = sheet.getLastRowNum(); for (int i = 0; i <= rowNum; i++) { HSSFRow row = sheet.getRow(i); int colNum = row.getLastCellNum(); for (short j = 0; j < colNum; j++) { builder.append(row.getCell(j).getRichStringCellValue() .getString()); } } } finally { if (in != null) { in.close(); } } } private static void readByJExcelAPI() throws Exception { StringBuilder builder = new StringBuilder(45); InputStream in = ExcelRead.class.getResourceAsStream("/test.xls"); try { Workbook book = Workbook.getWorkbook(in); Sheet sheet = book.getSheet(0); int rowNum = sheet.getRows(); int colNum = sheet.getColumns(); for (int i = 0; i < rowNum; i++) { Cell[] row = sheet.getRow(i); for (short j = 0; j < colNum; j++) { builder.append(row[j].getContents()); } } } finally { if (in != null) { in.close(); } } } private static void readByJExcelAPINoGC() throws Exception { StringBuilder builder = new StringBuilder(45); InputStream in = ExcelRead.class.getResourceAsStream("/test.xls"); try { Workbook book = Workbook.getWorkbook(in, settings); Sheet sheet = book.getSheet(0); int rowNum = sheet.getRows(); int colNum = sheet.getColumns(); for (int i = 0; i < rowNum; i++) { Cell[] row = sheet.getRow(i); for (short j = 0; j < colNum; j++) { builder.append(row[j].getContents()); } } } finally { if (in != null) { in.close(); } } } private static void readByXPath() throws Exception { StringBuilder builder = new StringBuilder(45); InputStream in = ExcelRead.class.getResourceAsStream("/test.xml"); try { Document document = df.newDocumentBuilder().parse(in); for (int i = 1; i <= 5; i++) { for (int j = 1; j <= 3; j++) { String str = xpath.evaluate( "//Workbook/Worksheet[1]/Table/Row[" + i + "]/Cell[" + j + "]/Data", document); builder.append(str); } } } finally { if (in != null) { in.close(); } } } private static void readByStAX() throws Exception { StringBuilder builder = new StringBuilder(45); InputStream in = ExcelRead.class.getResourceAsStream("/test.xml"); XMLStreamReader reader = null; try { reader = factory.createXMLStreamReader(in); for (; reader.hasNext(); reader.next()) { int eventType = reader.getEventType(); if (eventType == XMLStreamConstants.START_ELEMENT) { if ("Cell".equals(reader.getLocalName())) { reader.next(); builder.append(reader.getElementText()); } } } } finally { if (in != null) { in.close(); } if (reader != null) { reader.close(); } } } }