2011-05-07 65 views
0

不知道從哪裏可以得知這個信息,因爲他們拿下他們的論壇的亞音速乘員組,並說使用stackoverflow,所以我們走了。SubSonic&LinqTemplate:爲什麼在這裏讀得這麼慢?

我一直在努力實現ORM的最大性能。我喜歡亞音速,在這種情況下,它的批量插入,更新和刪除消除了實體框架,但是對於直接簡單的讀取,EF以超出水面5倍的速度吹出亞音速。

我已經剝離了下來,刪除了變更跟蹤,國外屬性,導航屬性,一切都下到了poco。

EF執行一個簡單的選擇1M行約4.8,亞音速的LINQ正在5X是...

看SQL事件探查器調用略有不同: 實體框架:SELECT TOP (1000000) [c].[Id] AS [Id], [c].[ProjectIDL] AS [ProjectIDL], [c].[DescriptorIDL] AS [DescriptorIDL], [c].[FieldIDL] AS [FieldIDL], [c].[Data] AS [Data], [c].[OptionId] AS [OptionId] FROM [dbo].[DescriptorFieldValues] AS [c]

亞音速: SELECT TOP (1000000) [t0].[Data], [t0].[DescriptorIDL], [t0].[FieldIDL], [t0].[Id], [t0].[OptionId], [t0].[ProjectIDL] FROM [dbo].[DescriptorFieldValues] AS t0

SQL事件探查器正在運行一個跟蹤並顯示一個巨大的持續時間差異。
我檢查審覈登錄這兩個查詢之前,他們是相同的......

如果我運行在SQL Management Studio中相同的查詢需要11秒兩個詢問

展望亞音速3.04來源,我無法弄清楚我會在哪裏進行調整以使它與EF匹配,但是這裏的查詢語法是否真的使這種差異變大,還是有一些我不知道的魔法?

感謝您的幫助!

+0

「EF執行約4.8中1M行的簡單選擇,SubSonic Linq取5倍...」至少,我們應該看到這個斷言來自的代碼,以及它觀察到的條件下。我記得閱讀(但無法找到源代碼)SubSonic使用一些動態代碼生成,因此編譯最初可能需要很高的時間成本。另外,問題是,如果在管理工作室中運行11秒鐘,EF如何返回「4.8」中的查詢(4.8,btw?)? – 2011-05-09 20:21:33

+0

我指的是從SQL監視器的時間 - 從SQL Server收到它並處理它到返回結果的時間,至少這是我相信的時間... – JTtheGeek 2011-05-09 21:20:43

+0

您還沒有建立任何實際的作爲比較的基礎,我仍然很困惑你從哪裏得到你的號碼。您是否在說4.8和SQL Server報告的「5x」?如果你問的是性能,它有助於做到非常明確和詳細。沒有更多細節我就再也忍不住了。 – 2011-05-09 21:36:20

回答

1

Rob Robney因爲想要了解爲什麼SubSonic與EF相比很慢,並且被告知我們很想知道爲什麼SubSonic壞了,我們相信我們的團隊已經找到了一些解決這些性能問題的地方:

  1. 在擴展/ Database.cs負載每行使用,每屬性反射到數據行序列化到一個具體的對象。
  2. 在Extensions/Database.cs中ToEnumerable所有的DataReader轉換都是在1個while循環中完成的。
  3. ExecutionBuilder - 這個查詢編譯器是一個alpha的直接複製粘貼,僅用於教育目的而僅用於查詢編譯器,並使用DynamicInvoke過時地過時。

我們的團隊計劃進行以下修改,按以下順序:

  1. 在擴展/ Database.cs ToEnumerable拉物業的相關信息,一旦並將它們傳遞到負載,這被認爲有影響最小的性能,但可能會帶來體面的內存利用率影響。

  2. 修改ToEnumerable以多線程化大數據集的實現。

  3. 在對象工廠中添加一個方法,以允許在不使用反射的情況下從數據行構建對象,而是提前使用t4模板代碼生成。
  4. 內部負載,請檢查此接口方法的對象激活器,如果是這樣的話,如果沒有,則默認返回基於反射的序列化。
  5. 更新ExceutionBuilder以避免使用DynamicInvoke。

希望這應該會使我們的表現需要成果。

感謝Jeff V,Ken I和QES的幫助。看到SubSonic Rob Corney的創造者對SubSonic的表現感到難以置信,因爲它似乎相當容易解決。 〜JT

+0

很高興我能幫到你。如果您最終變得更快,請發佈補丁或GitHub拉取請求。 -JeffV(rally25rs) – CodingWithSpike 2011-05-23 11:39:57

+0

傑夫,再次感謝。爲了做一些測試,我們自動生成了一個工廠,可以從一個數據採集器構建任何一種主要類型。我們正在檢查實現情況,看看它是否爲基本類型,如果是,則將其發送到工廠並繞過所有反射。我們看到,性能超過了我們所看到的其他任何東西,並且內存利用率也至少在最低水平。我們能夠在一秒鐘內輕鬆讀取1M。在我們的空閒時間,我們將嘗試將這一代帶到下一個層次並使用reflection.emit。我很樂意儘快發佈我們的更改。 – JTtheGeek 2011-05-23 18:53:23

+0

我們有什麼好東西? – 2012-10-25 05:04:44

1

除了您的SubSonic查詢似乎沒有選擇ID字段這兩個事實之外,這兩個SQL語句的用途完全相同。發現這兩個查詢需要花費相同的時間在SQL Management Studio中執行似乎支持這一點。

這似乎表明SubSonic確實需要更長的時間來查詢比EF。 SubSonic is known to have some issues with performance這絕對可以解釋這種差異。

但是,真的,我們需要更詳細的確切用法來真正地確定爲什麼這個查詢對您來說較慢的答案。

此外,如果您正在尋找當前的活動並使用SubSonic,請嘗試their Google Group。 SubSonic的創造者Rob Conery在一段時間前停止了工作,而「SubSonic人員」還沒有發佈任何實質性更新(如果有的話,我不認爲他們有,但我'米不完全確定)。這是一個項目,你可能會認爲「完成」了項目已停止的工作(所有實際目的),但在某種程度上,並不需要完全確定更多的工作(它的工作原理)。

順便說一下,那個說SubSonic論壇的頁面被關閉並且來到StackOverflow - 那麼這些頁面在一年內還沒有被更新,可能是2年。

+0

雖然我很欣賞你的答案,但它沒有解決我在這種情況下如何查詢其中一個查詢比其他查詢更快的實際問題,也不能解釋我如何能夠在亞音速中進行這種增強,聲波團隊。然而,這是朝着一個方向邁出的一步,但希望能夠獲得有關查詢性能問題的更多信息。 – JTtheGeek 2011-05-09 19:21:19

+0

好吧,你並沒有真正給出足夠的具體信息來確定你爲什麼看到性能差異,所以任何人都可以做的最好的是提供一般信息。這就是說,我意識到我有一個鏈接錯誤,並更新了。 – 2011-05-09 20:19:25

1

subsonic 3是如此之慢,因爲它需要compile again and again and again the same thinks纔去sql server並詢問結果。

而這個編譯發生在linq部分。

例如,一個簡單的靜態命令,如"Select * FROM Products WHERE ProductID > 100",在亞音速3中輸入爲Products.Find(x => (x.ProductID > 100)首先需要很多時間才能轉換爲字符串命令,我的意思是很長一段時間。

這是亞音速太慢的主要原因,也就是爲什麼亞音速3毫無價值。

在linq中,訣竅是CompiledQuery.Compile函數將其編譯一次並在內存中記住它。對我而言,我的標準如何也很慢。

現在回到亞音速2,這是一個非常好的想法,但仍然需要很多優化。顯然他們沒有想太多的速度。無論如何,一些優化亞音速2可以超快,靠近簡單的ado命令。

我的測試在一年前: Benchmark Linq2SQL, Subsonic2, Subsonic3 - Any other ideas to make them faster?

我的想法是要回去亞音速2,使之更好地和迅速,並刪除亞音速3.我感謝他們既亞音速2和3,但在他們失敗的版本3,它的好,我已經做了太多年的程序,並沒有全部使用。沒什麼大不了的。

+0

絕對是有關亞音速和動態查詢編譯的有效點。在我的特殊用例中,雖然我所有的讀取都非常龐大,然後大多數情況下我會進行小插入/更新/刪除調用。我發現迄今爲止最大的性能提升是擴展了高級模板,爲每個需要DataReader的類生成構造函數。然後在subsonic中的反序列化中,如果對象很簡單,我會調用該datareader構造函數而不是使用反射來填充對象。這讓我輕鬆地獲得了20倍的讀取速度,幾乎沒有使用內存。 – JTtheGeek 2011-06-28 22:38:56