2016-04-28 22 views
1

我目前在我們的.NET應用程序中使用Saxon來處理Xquery。我們正在處理非常大的XML文件(〜2GB)。當對直接使用Saxon二進制文件,這些文件中的一個運行中的XQuery,它需要完成評估時間約爲2分鐘,但是從我的C#應用​​程序在做評估時所經過的時間增加至10分鐘左右,而我的天堂還沒有能夠確定我做錯了什麼。如何提高C#中撒克遜評估的速度?

這是當我通過命令行運行使用Saxon二進制文件 XQuery的我在做什麼:

Query.exe -config:config.xml -q:XQueryTest.txt 

這些都是​​3210的內容:

<configuration xmlns="http://saxon.sf.net/ns/configuration" edition="HE"> 
    <xquery defaultElementNamespace="http://www.irs.gov/efile"/> 
</configuration> 

而且XQueryTest.txt包含我們要處理的Xquery。當從命令行運行Xquery時,我們使用doc()函數對其進行修改以指示我們將運行它的文件。下面是一個示例行:

for 
    $ReturnData at $currentReturnDataPos in if(exists(doc("2GB.XML")/Return/ReturnData)) then doc("2GB.XML")/Return/ReturnData else element{'ReturnData'} {''} 

如上所述,運行此命令需要大約2分鐘才能完成。

現在這是我在我的.NET應用程序,使這個同樣的評價正在做。

Processor processor = new Processor(); 
DocumentBuilder documentBuilder = processor.NewDocumentBuilder(); 
documentBuilder.IsLineNumbering = true; 
documentBuilder.WhitespacePolicy = WhitespacePolicy.PreserveAll; 
XQueryCompiler compiler = processor.NewXQueryCompiler(); 

string query = BuildXqueryString(); 

if (!String.IsNullOrEmpty(query)) 
{ 
    XQueryExecutable executable = compiler.Compile(query); 
    XQueryEvaluator evaluator = executable.Load(); 

    using (XmlReader myReader = XmlReader.Create(@"C:\Users\Administrator\Desktop\2GB.xml")) 
    { 
     evaluator.ContextItem = documentBuilder.Build(myReader); 
    } 

    var evaluations = evaluator.Evaluate(); 
} 

我們有的問題是在這一行:evaluator.ContextItem = documentBuilder.Build(myReader)。這甚至不是評估,而只是文件的加載。這條線需要太多的時間來執行,我需要知道這是否是預期的,或者是否有辦法提高速度。我已經使用了Build()方法的所有不同重載,並且它們都需要花費很多時間來完成,比從命令行執行時執行所花費的時間多2分鐘。

關於使用Saxon的流媒體容量按部分讀取文件,由於我們生成的Xqueries,這不是一個選項,因爲Xquery可以在XML的任何部分組合信息。

+0

http://stackoverflow.com/questions/2415434/the-limitation-on-the-size-of-net-array顯示.NET中任何分配對象的最大大小爲2GB。也許撒克遜正在遇到一個.NET內存問題,不得不採取額外的步驟,二進制可能不必採取?也許看看使用的資源會顯示二進制文件能夠使用額外的內存?對不起,我沒有別的東西或撒克遜的特殊經歷。乾杯! – chryosolo

回答

1

我們已經看到了Java平臺和薩克森在某些情況下,在.NET平臺上撒克遜之間類似的5:1的比例,我們沒有給它爲什麼會發生,儘管廣泛的調查底部。部分原因是它似乎不一致。當我們首次使用IKVMC交叉編譯器在.NET上發佈Saxon時,這個比例要好得多,.NET上的開銷只有25%左右,但從那以後似乎出現了許多技術變化:Java VM擁有得到更快的速度,IKVMC已經從使用GNU Classpath庫轉向OpenJDK,而.NET本身並沒有停滯不前。

這是新的我,雖然,同樣的代碼應該從.NET命令行運行得更快比它從.NET API運行。

這裏最大的區別在於,當您從命令行運行時,Saxon使用Apache Xerces解析器(使用IKVMC轉換爲.NET代碼)構建文檔,而在以所示方式使用DocumentBuilder.build()時,你正在使用微軟的XmlReader。

我希望,當您提供的(文件系統)的文件建設速度最快的運行URI,但我已經測得它,我不能說。這可能是值得做一些實驗(也許用較小的文件)並向我們展示結果。或者,您是否嘗試過使用應用程序中的doc()方法,而不是先構建文檔?

+0

我們也認爲使用URI會給我們帶來更好的結果,但事實並非如此,它仍然非常緩慢。我們嘗試使用您的最終建議(爲什麼我們沒有想到這一點?),而且速度實際上大大提高了。它仍然有點慢(有點超過3分鐘),但在前10分鐘附近,這太棒了!我認爲我們從來沒有想過這種方法,因爲我們認爲正確的實現應該首先加載XML,然後運行通用的Xquery,而不是在Xquery中對XML路徑進行硬編碼。 謝謝! – Ricardo

+0

感謝您的信息。這裏有一些奇怪的效果,我不明白:我們必須看看我們是否可以重現這一點。 –

+0

在此處記錄撒克遜問題:https://saxonica.plan.io/issues/2729 –

0

性能下降是由於使用.NET XmlReader進行解析造成的。使用.NET XML解析器和Saxon接收器的Push/Pull SAX事件處理比使用Saxon中提供的JAXP xerces解析器要慢得多。

要強制JAXP解析器,你可以做以下應該工作:

evaluator.ContextItem = documentBuilder.Build(新的URI(「文件:/// C:\用戶\管理員\桌面\ 2GB.xml「));