2009-08-30 52 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