2009-08-30 53 views
5

執行延遲幾乎總是一個福音。但是有些情況下,這是一個問題,你可以通過「獲取」(在Nhibernate中)來獲取它。什麼時候懶惰評估沒有用?

你是否知道懶惰的評估能咬你回去的實際情況......?

回答

0

延遲加載資源涉及在請求者和源之間來回訪問每個負載。在NHibernate的情況下,這意味着從應用程序到數據庫(通常在不同的服務器上)。

每次旅行都有相關的開銷(當然有NHibernate或任何其他數據庫查詢)。

如果您知道您將需要全部或大部分數據,則最好一次性將其拉出,並且只會產生一次開銷。

一個典型的例子是當你需要拉回一個對象列表來填充組合框(通常這些將是配置對象)。每次將列表成員添加到組合框時,延遲加載都會返回到數據庫。由於您將整個列表放到組合框中,因此您將需要額外的額外開銷來懶惰地獲取每個對象。

0

它也可能是您的程序的用戶體驗問題。當應用程序加載過程中屏幕上顯示橫幅時,人們會高興地等待5秒鐘,但當他們在文本框中鍵入內容時,他們不得不等待0.25秒。如果加載所有數據所需的時間並不長,您可能會考慮在工作流程中的某個時間點接受延遲(例如應用程序加載,窗口彈出,按下按鈕)。

3

在性能至關重要且必須評估值總是的情況下,懶惰評估無效。在這些情況下,您最好只評估價值並完成它,因爲懶惰評估的開銷將被浪費。

+0

懶惰評估是一種獲得績效的方式。 – Zorf 2010-05-19 18:27:06

+5

不正確。如果您必須評估答案,那麼懶惰評估的額外開銷就會產生一個沒有收益的成本。 – vy32 2010-05-20 04:59:01

+0

vy32是正確的。例如,如果您有移動設備上的列表中顯示的對象列表,則視圖將在列表項出現在屏幕上時創建。如果列表中顯示的某些值必須被延遲加載,則列表會結結並滯後,因爲新列表項不能足夠快地填充。 – Janusz 2010-06-09 13:31:01

0

如果您不想存儲價值,只使用它,懶惰評估就沒有用。但這取決於懶惰評估者的實現。有些系統(如Haskell)可以判斷一個值是否會再次被使用。其他一些人不能也可能導致泄漏。

2

當評估可能有副作用時,懶惰評估沒有用處。這是唯一的原因,這就是爲什麼只有純粹的功能語言。如果表達式可能具有必須以某種順序發生的副作用,則不能擁有它。

除此之外,懶惰評估只會獲得性能,這是它的主要目標。這就是爲什麼有些語言禁止使用副作用,爲了達到這種妥協的懶惰評估,另一個好的效果是控制結構可以是常規功能。對於lazyness引起奇怪的問題,(今天發生在我身上,在Haskell)

2

一個例子:

foo.txt: openFile: resource busy (file is locked) 

我以爲它會:

import System.IO 

main = do 
    content <- readFile "foo.txt" 
    writeFile "foo.txt" content 

當編譯&執行這引發以下錯誤做: 打開文件foo.txt,閱讀內容,再關閉它。然後打開它進行寫入,寫入內容並再次關閉。

什麼它實際上做的: 。「啊,有些內容我可能會讀它之後,我們真的需要它」然後打開「foo.txt」進行書寫。開始寫內容...好吧,現在我們需要內容。打開foo.txt閱讀 - 巴姆!

我知道這是微不足道的修復,但很難找到,如果你不知道去哪裏找。

+1

這是一個由懶惰I/O引起的問題,而不是一般的懶惰評估。懶惰I/O實際上是相當危險的,並且違背函數式編程的精神,因爲它會給應該是純粹的函數帶來副作用(即,評估字符串會導致數據從磁盤讀取 - 這是一種副作用!),從而導致問題就像這個,也是這一個:http://stackoverflow.com/questions/2981582/haskell-lazy-io-and-closing-files但是你可以肯定懶惰的評估沒有懶惰的I/O,事實上,這似乎是Haskell目前的方向。 – Jesse 2010-06-10 11:28:16

+0

這是一個很好的例子! – vy32 2010-06-11 04:05:35

4

你不能做在與惰性求恆定空間輸入的數據的減少(例如,摺疊),如線性的空間複雜度的每個還原步驟結果的延遲評價。您必須改爲強制評估每個縮減步驟的結果以保持空間使用量不變。

例如,散列在Haskell一個文件。你可能會善意和讀取輸入文件懶洋洋塊逐塊,將每個塊的摘要,而是你背後的Haskell實際上是讓你加入到消化每塊一個thunk,使整個文件在內存中直到得到的摘要被實際評估爲止。哎喲!

查看此最後的評論:Haskell lazy I/O and closing files