2011-03-29 75 views
0

使用Java对100MB XML文件进行排序需要多长时间?用Java对100MB XML文件排序?

文件有下列结构项目,我需要通过事件

<doc> 
    <id>84141123</id> 
    <title>kk+ at Hippie Camp</title> 
    <description>photo by SFP</description> 
    <time>18945840</time> 
    <tags>elphinstone tribalharmonix vancouver intention intention7 newyears hippiecamp bc sunshinecoast woowoo kk kriskrug sunglasses smoking unibomber møtleykrüg </tags> 
    <geo></geo> 
    <event>47409</event> 
</doc> 

我在英特尔双双核心和4GB RAM对它们进行排序。

分钟?小时 ?

感谢

+10

建立它。衡量它。分享你学到的东西。我们无法推测您的代码是如何显示的,您的计算机运行速度有多慢,SAN的速度有多慢以及您的操作系统速度有多慢。但是,您可以通过生成假数据并写入它来测量实际时间。你会发现解析输入比创建输出要慢。 – 2011-03-29 09:56:52

回答

2

我想说分钟 - 你shud能够做到完全在内存中,所以用SAX解析器,这将是阅读排序写作,不应该是你的硬件

问题
+2

*如果您在内存中执行此操作,则DOM解析器可能更合适,因为您无需以此方式单独构建内存中的数据表示形式。 – 2011-03-29 09:57:24

+0

但是,自定义内存中结构可能比DOM更紧凑。 – Thilo 2011-03-29 09:59:53

+1

我实际上正在考虑一个带有事件id和xml项的项的树图 - 简单的愚蠢的实现w/o任何xml魔术。 =) – atamur 2011-03-29 10:01:36

0

我觉得像这样的问题会更好地使用序列化进行排序。

  1. 将XML文件反序列化为'doc'的ArrayList。

  2. 使用直接的Java代码,对事件属性应用排序并将排序后的arraylist存储在另一个变量中。

  3. 连载了排序“文档”的ArrayList到文件

+0

要小心'ArrayList' - 当它扩展时,它分配的内存是它的两倍。Imho,最好先扫描文件并计算''条目('grep | wc -l'这样做很好),然后分配一个确切大小的数组。 – 9000 2011-03-29 10:15:50

+0

@ 9000,它是4 GB机器中的唯一一个100 MB文件。 2x扩展应该不成问题。 ;) – 2011-03-29 10:36:30

0

如果您在内存中做到这一点,你应该能够做到这一点在10秒。你会在2秒钟之内做这件事,因为它会花费那么多次读/写磁盘。

该程序应该使用不超过原始文件大小的4-5倍。你的情况下约500 MB。

String[] records = FileUtils.readFileToString(new File("my-file.xml")).split("</?doc>"); 
Map<Long, String> recordMap = new TreeMap<Long, String>(); 
for(int i=1;i<records.length;i+=2) { 
    String record = records[i]; 
    int pos1 = record.indexOf("<id>"); 
    int pos2 = record.indexOf("</id>", pos1+4); 
    long num = Long.parseLong(record.substring(pos1+3, pos2)); 
    recordMap.put(num, record); 
} 

StringBuilder sb = new StringBuilder(records[0]); 
for (String s : recordMap.values()) { 
    sb.append("<doc>").append(s).append("</doc>"); 
} 
sb.append(records[records.length-1]); 
FileUtils.writeStringToFile(new File("my-output-file.xml"), sb.toString()); 
7

下面是用于在100Mb的输入文件中使用的XQuery撒克逊执行类似的任务的定时。

Saxon-EE 9.3.0.4J from Saxonica 
Java version 1.6.0_20 
Analyzing query from {for $i in //item order by location return $i} 
Analysis time: 195 milliseconds 
Processing file:/e:/javalib/xmark/xmark100.xml 
Using parser com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser 
Building tree for file:/e:/javalib/xmark/xmark100.xml using class net.sf.saxon.tree.tiny.TinyBuilder 
Tree built in 6158 milliseconds 
Tree size: 4787932 nodes, 79425460 characters, 381878 attributes 
Execution time: 3.466s (3466ms) 
Memory used: 471679816 

因此:解析输入文件和构建树大约需要6秒,对它进行排序需要3.5秒。这是从命令行调用的,但是从Java调用它将获得非常类似的性能。不要试图自己对代码进行编码 - 它只是一个单行查询,而且你不太可能匹配优化的XQuery引擎的性能。

+1

+1。很好的答案。只要使用这个现有的工具,就不用费心去编写已经存在于一个很好的,可访问的打包解决方案中的代码。 – Thilo 2011-03-30 01:19:06