- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我是一名中级 Haskell 程序员,在严格的 FP 和非 FP 语言方面拥有丰富的经验。我的大多数 Haskell 代码都分析中等大的数据集(10^6..10^9 的东西),所以懒惰总是潜伏着。我对 thunk、WHNF、模式匹配和共享有相当好的理解,并且我已经能够使用 bang 模式和 seq 修复泄漏,但这种分析和祈祷方法感觉肮脏和错误。
我想知道经验丰富的 Haskell 程序员如何在设计时处理懒惰问题。我不是在询问像 Data.ByteString.Lazy 或 Foldl' 这样的简单项目;相反,我想知道您如何看待导致运行时内存问题和棘手调试的低级惰性机制。
您如何看待设计时的 thunk、模式匹配和共享?
您使用哪些设计模式和习惯用法来避免泄漏?
您是如何学习这些模式和习语的,您有一些好的引用资料吗?
如何避免过早优化非泄漏非问题?
(时间预算于 2014 年 5 月 15 日修订):
您是否预算了大量的项目时间来查找和修复内存问题?
或者,您的设计技能通常会规避内存问题,并且您会在开发周期的早期就得到预期的内存消耗吗?
最佳答案
我认为大多数“严格性泄漏”问题的发生是因为人们没有一个好的概念模型。没有良好概念模型的 Haskeller 倾向于持有并传播“越严格越好”的迷信。也许这种直觉来自于他们玩弄小例子和紧密循环的结果。但这是不正确的。在正确的时间偷懒和在正确的时间严格同样重要。
数据类型有两个阵营,通常称为“data”和“codata”。尊重每个人的模式至关重要。
X
被求值”的形式,而是“当 Y
被求值时,也被求值” X
“)。filter
)。 codata 的另一个重要部分是尽可能线性地使用它——即仅使用列表的尾部一次;树的每个分支只使用一次。这确保了 GC 可以在消耗碎片时收集它们。当您拥有包含数据的 codata 时,需要特别小心。例如。 iterate (+1) 0 !! 1000
在评估之前最终会生成一个大小为 1000 的 thunk。您需要再次考虑条件严格性——防止这种情况的方法是确保列表中的 cons 被消耗时,会添加其元素。 iterate
违反了这一点,所以我们需要一个更好的版本。
iterate' :: (a -> a) -> a -> [a]
iterate' f x = x : (x `seq` iterate' f (f x))
当你开始编写东西时,当然很难判断什么时候会发生坏情况。一般来说,很难创建在 data 和 codata 上同样工作的高效数据结构/函数,重要的是要记住哪个是哪个(即使在不能保证的多态设置中,您也应该记住一个并尝试尊重它)。
分享是很棘手的,我想我主要是根据具体情况来处理它。因为它很棘手,所以我尝试保持其本地化,选择不向一般模块用户公开大型数据结构。这通常可以通过暴露组合器来生成有问题的东西,然后一次性生成和消耗它来完成(单子(monad)上的代码密度转换就是一个例子)。
我的设计目标是让每个函数都尊重我类型的数据/协同数据模式。我通常可以击中它(尽管有时需要深思熟虑——多年来这已经变得很自然),而且当我这样做时,我很少遇到泄漏问题。但我并不是说这很容易——它需要规范库和语言模式的经验。这些决定并不是孤立做出的,一切都必须同时正确才能顺利进行。一件调音不当的乐器可能会毁掉整个音乐会(这就是为什么“随机扰动优化”几乎无法解决此类问题)。
Apfelmus 的 Space Invariants文章有助于进一步发展您的空间/thunk 直觉。另请参阅下面 Edward Kmett 的评论。
关于haskell - 经验丰富的 Haskell 开发人员如何在*设计*时应对懒惰问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23280936/
我想用个人详细信息来丰富订单集合。 假设我已经(示例在 json 中): [ { "orderId": 123, "quantity": 5, "buyerI
def classify(numb): i=1 j=1 sum=0 for i in range(numb): for j in range(numb)
我正在尝试使用 Spark 处理来自 HBase 表的数据。 This blog post给出了如何使用 NewHadoopAPI 从任何 Hadoop InputFormat 读取数据的示例。 我做
我使用 rich:menuitem 在 Richfaces 上构建了菜单。我需要确定用户单击了哪个菜单项。我尝试使用: 但是,我在请求参数中没有看到参数
注意:我遗漏了不相关的代码 所以我目前正在研究 CCC 1996 P1,这个问题的全部目的是能够计算一个整数输入是完美数、不足数还是充数。我上面列出的代码可以工作,但是我认为它太慢了。该代码会迭代每个
我们正在考虑将 ACS 作为我们的联合 STS。我们可以将自己的自定义 STS 配置为 IP-STS,以及“内置”身份提供商,例如 Facebook、Live 和 Google。然而,我们收到的 cl
我使用以下命令成功创建了一个绘图: # suppose I have a p <- ggplot(data=df, ...) then the following works # I get thos
我正在使用 spring-data-rest 存储库从 REST API 公开常见的 CRUD 操作。 但是我需要为这些操作添加额外的功能。 例如我想向第三方 API 发送关于删除的 HTTP 请求。
我有一个java支持bean,它有一个方法(称之为getDataList()),它返回ArrayList . 在 MyType.java我有很多 setter 和 getter,它们都分配 Strin
我正在使用以下代码:
我正在尝试在facelet组合中使用rich:faces组件rich:jQuery。但我无法产生任何 jquery 调用。 另一个问题...我将如何重写它以落入第一模式
是否可以将 Firebase 上游消息作为可操作通知进行传递?这就是我想要实现的目标:我希望能够将可操作的上游 Firebase 消息从我的 iPad 发送到我的 iPhone。 这可能吗? 这是我的
我有richfaces应用程序。在页面中,定义了 jQuery 函数: 然后我有一些 a4j:commandLink,它应该在完成 ajax 请求时调用该函数。 不幸的是,它不起作用。我知道 on
我有一个 rich:tree 组件,如下使用:
对于客户,我们需要为集成测试生成详细的测试报告,这些报告不仅表明一切都是绿色的,而且还表明测试做了什么。我和我的同事都很懒惰,我们不想破解电子表格或文本文档。 为此,我想了一种方法来记录更复杂的集成测
我在构建 Clojure 时遇到了一些困难基于 Web 应用程序。这是一个简单的 CRUD 应用程序,我开始探索 Clojure 网络生态系统。我正在尝试不同的库,例如 Hiccup , Enlive
我正在编写一个 Flink 流程序,其中我需要使用一些静态数据集(信息库,IB)来丰富用户事件的 DataStream。 对于例如假设我们有一个买家的静态数据集,并且有一个传入的事件点击流,对于每个事
在我的应用程序中,我有一个记录列表。用户可以选择任何记录,更新选项菜单。表格显示了这些记录,它有分页。 所以问题是,当我选择一条记录并对列表进行排序(使我之前选择的记录转到另一个页面)时,我看不到所选
我有一棵树(父级可以有任意数量的子级)和一个用于按名称搜索节点的 inputText 。假设有以下树: A --A1 ----AA1 --A2 其中 A 有两个子级 A1 和 A2,A1 有一个子级
我有一个 rich:dataTable 和一个 rich:dataScroller。当我单击 datascroller 时,我的 dataTable 不会自动刷新以显示正确的页面。但是,如果我按下刷新
我是一名优秀的程序员,十分优秀!