a 和 b 指向同一个对象,请问“拷贝”发生在哪里?
Ruby 不存在 值 这个概念,我不知道你说的值拷贝在 Ruby 上会是什么样子
我们再来看看是否如你所说产生了大量的小对象
n = 100_000
index = n / 2
GC.disable
puts "Checkpoint 1"
pp ObjectSpace.count_objects
arr = 1.upto(n).to_a
arr.index(index)
puts "Checkpoint 2"
pp ObjectSpace.count_objects
arr1 = arr[2..]
arr1.index(index)
puts "Checkpoint 3"
pp ObjectSpace.count_objects
注意为了避免 irb 的干扰(语句打印到控制台会产生大量对象)语句这段代码要么保存成文件执行,要么用 eval
来执行
另外注意,我们在代码里关闭了 GC,也就是说产生的任何对象,都不会被回收
Checkpoint 1
{:TOTAL=>48914,
:FREE=>3078,
:T_OBJECT=>2032,
:T_CLASS=>998,
:T_MODULE=>76,
:T_FLOAT=>4,
:T_STRING=>23003,
:T_REGEXP=>323,
:T_ARRAY=>4881,
:T_HASH=>274,
:T_STRUCT=>1000,
:T_BIGNUM=>2,
:T_FILE=>5,
:T_DATA=>567,
:T_MATCH=>248,
:T_COMPLEX=>1,
:T_SYMBOL=>58,
:T_IMEMO=>12265,
:T_ICLASS=>99}
Checkpoint 2
{:TOTAL=>49321,
:FREE=>303,
:T_OBJECT=>2161,
:T_CLASS=>1016,
:T_MODULE=>78,
:T_FLOAT=>4,
:T_STRING=>24893,
:T_REGEXP=>323,
:T_ARRAY=>5357,
:T_HASH=>284,
:T_STRUCT=>1002,
:T_BIGNUM=>2,
:T_FILE=>7,
:T_DATA=>615,
:T_MATCH=>248,
:T_COMPLEX=>1,
:T_SYMBOL=>58,
:T_IMEMO=>12867,
:T_ICLASS=>102}
Checkpoint 3
{:TOTAL=>49729,
:FREE=>167,
:T_OBJECT=>2290,
:T_CLASS=>1016,
:T_MODULE=>78,
:T_FLOAT=>4,
:T_STRING=>25066,
:T_REGEXP=>323,
:T_ARRAY=>5512,
:T_HASH=>286,
:T_STRUCT=>1003,
:T_BIGNUM=>2,
:T_FILE=>7,
:T_DATA=>656,
:T_MATCH=>248,
:T_COMPLEX=>1,
:T_SYMBOL=>58,
:T_IMEMO=>12910,
:T_ICLASS=>102}
观察结果,并没有产生大量的元素复制,假设证伪。
现在用 rubocop 或者 https://github.com/testdouble/standard 这些 linting 工具解决就是了
就 each_char
为例,文档已经关联了对应的源代码 https://ruby-doc.org/core-2.4.0/String.html#method-i-each_char 自己追就可以了
反驳的点是 他认为 b = a
是值拷贝,事实上 Ruby 不存在值语义,
换 Float 结果依旧成立
2.7.1 :027 > a = 1.1
2.7.1 :028 > a.object_id
=> -32425917317067566
2.7.1 :029 > b = a
2.7.1 :030 > b.object_id
=> -32425917317067566
此外
ruby 中有值和引用语义
这句话明显也是错的,Ruby 语言已经明确了只存在引用,就你以 Integer 的例子,证伪很容易
2.7.1 :021 > a = 1
2.7.1 :022 > a.object_id
=> 3
2.7.1 :023 > b = a
2.7.1 :024 > b.object_id
=> 3
a 和 b 都指向同一个 Integer 对象,并没有发生值拷贝
你对 b = a
的理解也有误区,他的意思是将 a
指向的对象 binding
(绑定)到 b
上。
就你的例子而言,我们做一个测试
require 'benchmark'
n = 100_000
arr = 1.upto(n).to_a
index = n / 2
puts index
Benchmark.bm do |x|
x.report { 100.times { arr.index(index) } }
x.report { 100.times { arr[2..].index(index) } }
end
在 ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-darwin19]
上的结果
user system total real
0.036552 0.000022 0.036574 ( 0.036579)
0.035222 0.000063 0.035285 ( 0.035303)
user system total real
0.034097 0.000060 0.034157 ( 0.034210)
0.030318 0.000049 0.030367 ( 0.030414)
user system total real
0.039931 0.000083 0.040014 ( 0.040158)
0.035147 0.000157 0.035304 ( 0.035333)
后者比前者性能略高(考虑误差性能大致一致)
换一种 benchmark 做法
require 'benchmark/ips'
n = 100_000
arr = 1.upto(n).to_a
index = n / 2
puts index
Benchmark.ips do |x|
x.config(time: 10, warmup: 2)
x.report("arr.index(index)") { arr.index(index) }
x.report("arr[2..].index(index)") { arr[2..].index(index) }
x.compare!
end
结果
Warming up --------------------------------------
arr.index(index) 329.000 i/100ms
arr[2..].index(index)
317.000 i/100ms
Calculating -------------------------------------
arr.index(index) 3.486k (± 3.5%) i/s - 34.874k in 10.018586s
arr[2..].index(index)
3.455k (± 1.6%) i/s - 34.553k in 10.002732s
Comparison:
arr.index(index): 3485.6 i/s
arr[2..].index(index): 3455.3 i/s - same-ish: difference falls within error
两种写法的性能表现几乎相同(考虑误差)
结果来看两种写法的性能并无差别,你的假设证伪。
更新:
换了 Float 一样成立
require 'benchmark'
n = 100_000.0
arr = 1.upto(n).to_a
index = n / 2
puts index
Benchmark.bm do |x|
x.report { 100.times { arr.index(index) } }
x.report { 100.times { arr[2..].index(index) } }
end
user system total real
0.196415 0.000087 0.196502 ( 0.196542)
0.188249 0.000104 0.188353 ( 0.188391)
更新了有奖互动相关的信息
更新了几件 T 恤图案的渲染图~
更新了自动加入参会群的二维码~
没 不过群里有发设计稿,我看看能不能把图案放到这里来。
因为这个周边制作有点特殊性,目前还没做样子
已改
这已经拖延症晚期,再不发就不用发了...
说来小扎的基金会网站也是 Rails 写的...
编译前端资源很消耗 CPU 的,我记得有 Cap 的 recipe 在本地编译传到服务器的
The parameters are passed on the stack. If there are too many parameters, you'll exhaust stack space and get the mentioned error.
据说 Hey 的技术成果过阵子要回馈社区,Turbolinks 6、Stimulus 2 还有 Rails 的一些组件
Redmine 的样式还是上个世纪的思路,就用浏览器调试器来做就好了...
好吧,我申请个 up 主去
蛋疼... 那有啥地方上传视频比较方便的...
发了个推展示一下 Dummy App 可以做到的效果
https://twitter.com/jasl9187/status/1270304483923259393
有空还可以搞一下表单字段的访问控制(FormCore 本来就有的功能)、会签、动态指派
加油!!!!!!!!!!!!!!!!!
如果没装烂七八糟常驻的程序的话,很可能是电池老化,这个很正常,可以自己搜一下怎么看电池健康度,如果过低花钱换(在保的话,低于 85% 是免费更换的)
不耗电啊
G 家肯定是 Angular 了,应该不开源,市面上收费免费的 MD UI 框架确实都有各自的小毛病不尽如人意
10.15 自带 Ruby 2.6,你用 RVM 或者 RBENV 装 2.6.6 吧
如果是单复数词汇的映射错误,可以添加例外列表到 config/initializers/inflections.rb
加 source 显式指明也不错
Ruby 这里比较灵活,因为决定puts 'hi'; 7 if (a<6)
这句话的返回值的是 7 if (a<6)
这部分,显然返回值是 7
,接着 7==7
成立,于是满足 puts 'good'
的条件,得到了你描述的结果
不过灵活归灵活,这种做法或许可以实现某些非常奇妙的效果,但是,可读性永远是第一位的,也就是,虽然你可以,但是尽量还是不要这样做。
Python 的设计哲学是希望一个事情只有一种做法,所以有时候会显得过于死板了。
这是人的问题,跟技术一点儿关系都没,富士康开工物美价廉的工人得给足