obj.nil? 대 obj == nil
사용하는 것이 더 낫 습니까? obj.nil?
또는 obj == nil
둘 다의 이점은 무엇입니까?
obj.nil을 사용하는 것이 더 낫습니까? 또는 obj == nil
똑같습니다.
그것은 외부에서 똑같은 관찰 가능한 효과를 가지고 있습니다 (pfff) *
그리고 둘 다의 이점은 무엇입니까?
마이크로 최적화가 마음 에 들면 객체 자체를 제외한 모든 객체가 메시지로 반환 false
되는 반면 메시지를 사용하는 객체는 다른 객체와 미세한 비교를 수행하여 동일한 객체인지 확인합니다..nil?
nil
==
* 의견을 참조하십시오.
개인적으로 나는 object.nil?
긴 줄에서 덜 혼란 스러울 수 있기 때문에 선호 합니다. 그러나 object.blank?
변수가 비어 있는지 확인하기 때문에 Rails에서 작업 하는 경우 에도 일반적으로 사용 합니다.
구문과 스타일은 제쳐두고, nil 테스트에 대한 "동일한"다양한 접근 방식을보고 싶었습니다. 그래서 저는 몇 가지 벤치 마크를 작성하여 다양한 형태의 nil 테스트를 던졌습니다.
TL; DR-결과 우선
실제 결과는 obj
nil 검사로 사용 하는 것이 모든 경우에 가장 빠른 것으로 나타났습니다 . obj
확인하는 것보다 지속적으로 30 % 이상 빠릅니다 obj.nil?
.
놀랍게도에서 obj
변형보다 약 3 ~ 4 배 빠른 속도로 obj == nil
성능이 저하되는 것으로 보입니다.
성능 집약적 인 알고리즘의 속도를 200 % -300 %까지 높이고 싶으십니까? 모든 obj == null
수표를 obj
. 코드 성능을 샌드백하고 싶으십니까? 가능한 obj == null
모든 곳에서 사용하십시오 . (농담입니다 : 코드를 샌드백하지 마세요!).
최종 분석에서는 항상 obj
. 와 그 jives 루비 스타일 가이드의 규칙 : 할 일이되지 부울 값으로 당신이하지 않는있는 거 거래 명시 적 nil이 아닌 확인을한다.
벤치 마크 조건
좋습니다.이게 결과입니다.이 벤치 마크는 어떻게 구성되고 어떤 테스트가 수행되었으며 결과의 세부 사항은 무엇입니까?
내가 생각해 낸 nil 검사는 다음과 같습니다.
- obj
- obj.nil?
- ! obj
- !! obj
- obj == nil
- obj! = nil
유형에 따라 결과가 변경되는 경우를 대비하여 다양한 Ruby 유형을 선택하여 테스트했습니다. 이러한 유형은 Fixnum, Float, FalseClass, TrueClass, String 및 Regex입니다.
각 유형에 대해 이러한 nil 검사 조건을 사용하여 성능 측면에서 차이가 있는지 확인했습니다. 각 유형에 대해, I는 모두 닐 목적 및 비 닐 값 객체 (예를 들어 시험 1_000_000
, 100_000.0
, false
, true
, "string"
, 및 /\w/
무 아니다 개체에 비해 전무 인 오브젝트에 닐 검사에 차이가 있는지) 확인합니다.
벤치 마크
이 모든 과정에서 벤치 마크 코드는 다음과 같습니다.
require 'benchmark'
nil_obj = nil
N = 10_000_000
puts RUBY_DESCRIPTION
[1_000_000, 100_000.0, false, true, "string", /\w/].each do |obj|
title = "#{obj} (#{obj.class.name})"
puts "============================================================"
puts "Running tests for obj = #{title}"
Benchmark.bm(15, title) do |x|
implicit_obj_report = x.report("obj:") { N.times { obj } }
implicit_nil_report = x.report("nil_obj:") { N.times { nil_obj } }
explicit_obj_report = x.report("obj.nil?:") { N.times { obj.nil? } }
explicit_nil_report = x.report("nil_obj.nil?:") { N.times { nil_obj.nil? } }
not_obj_report = x.report("!obj:") { N.times { !obj } }
not_nil_report = x.report("!nil_obj:") { N.times { !nil_obj } }
not_not_obj_report = x.report("!!obj:") { N.times { !!obj } }
not_not_nil_report = x.report("!!nil_obj:") { N.times { !!nil_obj } }
equals_obj_report = x.report("obj == nil:") { N.times { obj == nil } }
equals_nil_report = x.report("nil_obj == nil:") { N.times { nil_obj == nil } }
not_equals_obj_report = x.report("obj != nil:") { N.times { obj != nil } }
not_equals_nil_report = x.report("nil_obj != nil:") { N.times { nil_obj != nil } }
end
end
결과
결과는 흥미로 웠습니다. Fixnum, Float 및 String 유형의 성능은 거의 동일했고 Regex는 거의 비슷했으며 FalseClass와 TrueClass는 훨씬 더 빠르게 수행되었습니다. 테스트는 MRI 버전 1.9.3, 2.0.0, 2.1.5 및 2.2.5에서 수행되었으며 버전간에 비교 결과가 매우 유사했습니다. MRI 2.2.5 버전의 결과가 여기에 표시됩니다 ( 요점 에서 사용 가능 :
ruby 2.2.5p319 (2016-04-26 revision 54774) [x86_64-darwin14]
============================================================
Running tests for obj = 1000000 (Fixnum)
user system total real
obj: 0.970000 0.000000 0.970000 ( 0.987204)
nil_obj: 0.980000 0.010000 0.990000 ( 0.980796)
obj.nil?: 1.250000 0.000000 1.250000 ( 1.268564)
nil_obj.nil?: 1.280000 0.000000 1.280000 ( 1.287800)
!obj: 1.050000 0.000000 1.050000 ( 1.064061)
!nil_obj: 1.070000 0.000000 1.070000 ( 1.170393)
!!obj: 1.110000 0.000000 1.110000 ( 1.122204)
!!nil_obj: 1.120000 0.000000 1.120000 ( 1.147679)
obj == nil: 2.110000 0.000000 2.110000 ( 2.137807)
nil_obj == nil: 1.150000 0.000000 1.150000 ( 1.158301)
obj != nil: 2.980000 0.010000 2.990000 ( 3.041131)
nil_obj != nil: 1.170000 0.000000 1.170000 ( 1.203015)
============================================================
Running tests for obj = 100000.0 (Float)
user system total real
obj: 0.940000 0.000000 0.940000 ( 0.947136)
nil_obj: 0.950000 0.000000 0.950000 ( 0.986488)
obj.nil?: 1.260000 0.000000 1.260000 ( 1.264953)
nil_obj.nil?: 1.280000 0.000000 1.280000 ( 1.306817)
!obj: 1.050000 0.000000 1.050000 ( 1.058924)
!nil_obj: 1.070000 0.000000 1.070000 ( 1.096747)
!!obj: 1.100000 0.000000 1.100000 ( 1.105708)
!!nil_obj: 1.120000 0.010000 1.130000 ( 1.132248)
obj == nil: 2.140000 0.000000 2.140000 ( 2.159595)
nil_obj == nil: 1.130000 0.000000 1.130000 ( 1.151257)
obj != nil: 3.010000 0.000000 3.010000 ( 3.042263)
nil_obj != nil: 1.170000 0.000000 1.170000 ( 1.189145)
============================================================
Running tests for obj = false (FalseClass)
user system total real
obj: 0.930000 0.000000 0.930000 ( 0.933712)
nil_obj: 0.950000 0.000000 0.950000 ( 0.973776)
obj.nil?: 1.250000 0.000000 1.250000 ( 1.340943)
nil_obj.nil?: 1.270000 0.010000 1.280000 ( 1.282267)
!obj: 1.030000 0.000000 1.030000 ( 1.039532)
!nil_obj: 1.060000 0.000000 1.060000 ( 1.068765)
!!obj: 1.100000 0.000000 1.100000 ( 1.111930)
!!nil_obj: 1.110000 0.000000 1.110000 ( 1.115355)
obj == nil: 1.110000 0.000000 1.110000 ( 1.121403)
nil_obj == nil: 1.100000 0.000000 1.100000 ( 1.114550)
obj != nil: 1.190000 0.000000 1.190000 ( 1.207389)
nil_obj != nil: 1.140000 0.000000 1.140000 ( 1.181232)
============================================================
Running tests for obj = true (TrueClass)
user system total real
obj: 0.960000 0.000000 0.960000 ( 0.964583)
nil_obj: 0.970000 0.000000 0.970000 ( 0.977366)
obj.nil?: 1.260000 0.000000 1.260000 ( 1.265229)
nil_obj.nil?: 1.270000 0.010000 1.280000 ( 1.283342)
!obj: 1.040000 0.000000 1.040000 ( 1.059689)
!nil_obj: 1.070000 0.000000 1.070000 ( 1.068290)
!!obj: 1.120000 0.000000 1.120000 ( 1.154803)
!!nil_obj: 1.130000 0.000000 1.130000 ( 1.155932)
obj == nil: 1.100000 0.000000 1.100000 ( 1.102394)
nil_obj == nil: 1.130000 0.000000 1.130000 ( 1.160324)
obj != nil: 1.190000 0.000000 1.190000 ( 1.202544)
nil_obj != nil: 1.200000 0.000000 1.200000 ( 1.200812)
============================================================
Running tests for obj = string (String)
user system total real
obj: 0.940000 0.000000 0.940000 ( 0.953357)
nil_obj: 0.960000 0.000000 0.960000 ( 0.962029)
obj.nil?: 1.290000 0.010000 1.300000 ( 1.306233)
nil_obj.nil?: 1.240000 0.000000 1.240000 ( 1.243312)
!obj: 1.030000 0.000000 1.030000 ( 1.046630)
!nil_obj: 1.060000 0.000000 1.060000 ( 1.123925)
!!obj: 1.130000 0.000000 1.130000 ( 1.144168)
!!nil_obj: 1.130000 0.000000 1.130000 ( 1.147330)
obj == nil: 2.320000 0.000000 2.320000 ( 2.341705)
nil_obj == nil: 1.100000 0.000000 1.100000 ( 1.118905)
obj != nil: 3.040000 0.010000 3.050000 ( 3.057040)
nil_obj != nil: 1.150000 0.000000 1.150000 ( 1.162085)
============================================================
Running tests for obj = (?-mix:\w) (Regexp)
user system total real
obj: 0.930000 0.000000 0.930000 ( 0.939815)
nil_obj: 0.960000 0.000000 0.960000 ( 0.961852)
obj.nil?: 1.270000 0.000000 1.270000 ( 1.284321)
nil_obj.nil?: 1.260000 0.000000 1.260000 ( 1.275042)
!obj: 1.040000 0.000000 1.040000 ( 1.042543)
!nil_obj: 1.040000 0.000000 1.040000 ( 1.047280)
!!obj: 1.120000 0.000000 1.120000 ( 1.128137)
!!nil_obj: 1.130000 0.000000 1.130000 ( 1.138988)
obj == nil: 1.520000 0.010000 1.530000 ( 1.529547)
nil_obj == nil: 1.110000 0.000000 1.110000 ( 1.125693)
obj != nil: 2.210000 0.000000 2.210000 ( 2.226783)
nil_obj != nil: 1.170000 0.000000 1.170000 ( 1.169347)
대부분의 경우 둘 다 부울 진리 값만 테스트합니다.
Although the two operations are very different I'm pretty sure they will always produce the same result, at least until someone out on the edge of something decides to override Object's #nil?
method. (One calls the #nil?
method inherited from Object or overridden in NilClass
and one compares against the nil
singleton.)
I would suggest that when in doubt you go a third way, actually, and just test the truth value of an expression.
So, if x
and not if x == nil
or if x.nil?
, in order to have this test DTRT when the expression value is false. Working this way may also help to avoiding tempting someone to define FalseClass#nil?
as true.
You can use Symbol#to_proc on nil?
, whereas it wouldn't be practical on x == nil
.
arr = [1, 2, 3]
arr.any?(&:nil?) # Can be done
arr.any?{|x| x == nil} # More verbose, and I suspect is slower on Ruby 1.9.2
! arr.all? # Check if any values are nil or false
I find myself not using .nil?
at all when you can do:
unless obj
// do work
end
It's actually slower using .nil?
but not noticeably. .nil?
is just a method to check if that object is equal to nil, other than the visual appeal and very little performance it takes there is no difference.
Some might suggest that using .nil? is slower than the simple comparison, which makes sense when you think about it.
But if scale and speed are not your concern, then .nil? is perhaps more readable.
참고URL : https://stackoverflow.com/questions/1972266/obj-nil-vs-obj-nil
'code' 카테고리의 다른 글
Windows의 git-svn. (0) | 2020.11.12 |
---|---|
사용자 지정 예외 메시지 : 모범 사례 (0) | 2020.11.12 |
SQL Server에서 IDENTITY_INSERT가 ON 또는 OFF로 설정되어 있는지 어떻게 확인합니까? (0) | 2020.11.12 |
Reified Generic은 무엇입니까? (0) | 2020.11.12 |
Facebook은 캔버스 페이지의 iFrame에 대한 교차 도메인 쿠키를 어떻게 설정합니까? (0) | 2020.11.12 |