- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
当你只有一把锤子时,一切看起来都像钉子。因此,在发现 Array#map
和 Array#select< 的实用性、优雅性和语法乐趣之前,可以说是 Ruby 中的
和其他可迭代方法。我很好奇的是:Array#each
方法
为什么在使用更精确的可迭代方法时性能会实际提高?一般来说,这是真的吗?
例如,在
require 'benchmark'
array = (1..100000).to_a
puts Benchmark.measure {
100.times do
array.map { |el| el.even? }
end
}
puts Benchmark.measure {
100.times do
new_array = []
array.each do |el|
new_array << el.even?
end
end
}
# ruby bench.rb
# 0.450598 0.015524 0.466122 ( 0.466802)
# 0.496796 0.018525 0.515321 ( 0.516196)
Benchmark
始终显示有利于 Array#map
的时间性能差异。在以下代码中:
puts Benchmark.measure {
100.times do
array.select { |el| el.even? }
end
}
puts Benchmark.measure {
100.times do
new_array = []
array.each do |el|
if el.even?
new_array << el
end
end
end
}
# ruby bench.rb
# 0.405254 0.007965 0.413219 ( 0.413733)
# 0.471416 0.008875 0.480291 ( 0.481079)
Array#select
每次都击败了一个偷工减料的 Array#each
。
那么为什么这些更精确的方法会产生明显更好的性能呢?这是 Ruby 和/或所有语言中的通用公理吗?
最佳答案
在您的两个示例中,第二段代码分配的内存是第一段代码的 100 倍。它还对数组执行大约 log_1.5(100) 次调整大小(假设动态数组的标准教科书实现具有 1.5 的增长因子)。调整数组的大小是昂贵的(分配一个新的内存块,然后将所有元素的 O(n) 副本复制到新的内存块中)。更一般地说,垃圾收集器讨厌突变,它们收集大量生命周期短的小对象比保持一些生命周期长的大对象更有效。
换句话说,在第一个示例中,您正在测量 Array#map
和 Array#select
,分别,而在第二个例子中,你不仅测量 Array#each
, 还有 Array#<<
以及数组大小调整和内存分配。从基准测试结果中无法判断哪些贡献了多少。正如 Zed Shaw 曾经说过的那样:"If you want to measure something, then don't measure other shit" .
但即使您在基准测试中修复了该错误,一般来说,更专业的操作比通用操作具有更多可用信息,因此更通用的操作通常不会比专业操作更快。
在您的特定示例中,它可能只是一些非常简单的事情,例如,您使用的 Ruby 实现不太擅长优化 Ruby 代码(例如 YARV,与 TruffleRuby 不同),同时具有优化的Array#map
的 native 实现和 Array#select
(再次以 YARV 为例,它对这两者都有 C 实现,并且通常不能很好地优化 Ruby 代码)。
最后,编写正确的微基准测试很困难。真的,真的,真的很难。我鼓励阅读并理解 mechanical-sympathy 上的整个讨论主题。邮寄名单:JMH vs Caliper: reference thread .虽然它专门针对 Java 基准测试(实际上是关于 JVM 基准测试),但许多论点适用于任何现代高性能 OO 执行引擎,例如 Rubinius、TruffleRuby 等。在较小程度上也适用于 YARV。请注意,大部分讨论都是关于编写微基准测试工具,而不是编写微基准测试本身,即它是关于编写允许开发人员编写正确的微基准测试的框架,不必了解那些东西,但不幸的是,即使有最好的微基准测试工具(Ruby 的 Benchmark
实际上不是一个很好的工具),您仍然需要对现代编译器、垃圾收集器、执行引擎、CPU、硬件架构有非常深刻的理解, 还有统计数据。
这是一个失败的基准测试的好例子,对于未受过训练的基准测试编写者来说可能并不明显:Why is printing “B” dramatically slower than printing “#”? .
关于ruby - 为什么#map 比#each 更有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60011859/
我正在尝试从一个 map 的 map 的 map 的 map 的 map 的 map 的 map 的 map 的 map 的 map 的 map 的 map 的 map 的 map 的 map 的 m
我是 Haskell 的新手,我认为函数 map map和 map.map在 Haskell 中是一样的。 我的终端给了我两种不同的类型, (map.map) :: (a -> b) -> [[a]
我的目标是创建一个 map 的 map ,这样我就可以通过它的键检索外部 map 的信息,然后通过它们的键访问它的“内部” map 。 但是,当我得到每个内部映射时,我最初创建的映射变成了一个对象,我
如何使用 Java8 编写以下代码? for (Entry> entry : data.entrySet()) { Map value = entry.getValue(); if (valu
我有覆盖整个南非的图片。它们为Tiff格式,并已将坐标嵌入其中。我正在尝试拍摄这些图像(大约20张图像),并将它们用作我的iPhone应用程序中的地图叠加层。我的问题在于(准确地)将地图切成图块。 我
所以我有 2 std::map s >一个是“旧的”,一个是“新的”,我想知道哪些文件被删除了,这样就能够遍历差异并对 shared_ptr 做一些事情。这样的事情可能吗?如何做到? 最佳答案 虽然
是否可以将当前查看的 google.maps.Map 转换为静态图像链接,以便我可以获取图像并将其嵌入到 PDF 中? 我在 map 上添加了一些带有自定义图标的标记,所以我不确定这是否真的可行。 如
你能帮我吗 Java Streams ? 从标题可以看出我需要合并List>>进入Map> . 列表表示为List>>看起来像: [ { "USER_1":{
对于 idAndTags 的第二个条目,内部映射被打乱,但第一个条目则不然 第一次接近! for (Map.Entry> entryOne : idAndTags.entrySet()) {
我将从我的代码开始,因为它应该更容易理解我想要做什么: @function get-color($color, $lightness) { @return map-get(map-get($col
我过去曾在许多网站上使用过 Google map ,但遇到了以前从未遇到过的问题。 map 窗口正在显示,但它只显示左上角的 map 片段,以及之后的任何内容(即使我在周围导航时),右侧也不会加载任何
众所周知,这些 map ,无论是常规街道 map 还是卫星 map ,在中国的特定地区都无法正确排列。那么哪个 map 排列正确,是卫星 map 还是默认街道 map ?一些网站表明卫星 map 是正
在拖尾事件之后,我面临着获取此处 map 中的 map 边界的问题。我需要新的经纬度来在新更改的视口(viewport)中获取一些项目/点。我只是想在拖动结束时获得谷歌地图map.getBounds(
我想做的是通过 ajax API 显示以英国邮政编码为中心的小型 bing 生成 map 。我相信这是可能的;我在 Bing map 文档中找不到如何将英国邮政编码转换为可以插入 map Ajax 控
我有一个 List我想转换成的 e Map>其中外部字符串应为“Name”,内部字符串应为“Domain”。 Name Id Domain e(0) - Emp1, 1, Insuran
我的第 2 部分:https://stackoverflow.com/questions/21780627/c-map-of-maps-typedef-doubts-queries 然后我继续创建 I
是否可以在 1 行中使用 Java8 编写以下所有 null 和空字符串检查? Map> data = new HashMap<>(holdings.rowMap()); Set>> entrySet
我正在审查一个项目的旧代码,并使用 Map 的 Map 的 Map 获得了如下数据结构(3 层 map ): // data structure Map>>> tagTree
这可能是一种不好的做法,但我还没有找到更好的解决方案来解决我的问题。所以我有这张 map // Map>> private Map>> properties; 我想初始化它,这样我就不会得到 Null
我们在 JDK 1.7 中使用 HashMap,我在使用 SonarQube 进行代码审查时遇到了一些问题。 请考虑以下示例: public class SerializationTest imple
我是一名优秀的程序员,十分优秀!