2016-12-27 9 views
5

मैंने प्रश्न Why does Process.fork make stuff slower in Ruby on OS X? देखा और यह निर्धारित करने में सक्षम था कि Process.fork वास्तव में धीमी गति से कार्य करता है।ओएस एक्स (और पायथन में नहीं) पर रुबी में एक फोर्क प्रक्रिया में 'टाइम.यूटीसी' धीमा क्यों है?

हालांकि, ऐसा लगता है कि यह Time.utc विशेष रूप से बहुत धीमी है।

main: 0.100000 0.000000 0.100000 ( 0.103762) 
fork: 0.530000 3.210000 3.740000 ( 3.765203) 

main: 0.100000 0.000000 0.100000 ( 0.104218) 
fork: 0.540000 3.280000 3.820000 ( 3.858817) 

main: 0.100000 0.000000 0.100000 ( 0.102956) 
fork: 0.520000 3.280000 3.800000 ( 3.831084) 

एक संकेत हो सकता है कि इसके बाद के संस्करण ओएस एक्स पर जगह लेता है, जबकि Ubuntu पर, वहाँ एक अंतर हो प्रतीत नहीं होता:

main: 0.100000 0.070000 0.170000 ( 0.166505) 
fork: 0.090000 0.070000 0.160000 ( 0.169578) 

main: 0.090000 0.080000 0.170000 ( 0.167889) 
fork: 0.100000 0.060000 0.160000 ( 0.169160) 

main: 0.100000 0.070000 0.170000 ( 0.170839) 
fork: 0.100000 0.070000 0.170000 ( 0.176146) 

require 'benchmark' 

def do_stuff 
    50000.times { Time.utc(2016) } 
end 

puts "main: #{Benchmark.measure { do_stuff }}" 

Process.fork do 
    puts "fork: #{Benchmark.measure { do_stuff }}" 
end 

यहाँ कुछ परिणाम हैं

क्या कोई इस विषमता को समझा सकता है?

आगे की जांच:

@tadman सुझाव दिया कि यह MacOS/ओएस एक्स बार कोड में एक बग हो सकता है, तो मैं अजगर में एक समान परीक्षण लिखा है:

from timeit import timeit 
from os import fork 

print timeit("datetime.datetime.utcnow()", setup="import datetime") 

if fork() == 0: 
    print timeit("datetime.datetime.utcnow()", setup="import datetime") 
else: 
    pass 

फिर, Ubuntu पर , बेंचमार्क फोर्क/मुख्य प्रक्रियाओं के लिए समान हैं। ओएस एक्स पर, हालांकि, मुख्य प्रक्रिया की तुलना में फोर्क की गई प्रक्रिया अब तेज है, जो रूबी में व्यवहार के विपरीत है।

इससे मुझे विश्वास होता है कि "कांटा जुर्माना" का स्रोत रुबी कार्यान्वयन में है और ओएस एक्स समय कार्यान्वयन में नहीं है।

+1

क्या यह प्रति कांटा परत प्रति दंड है, जैसे कि यह एक और उप-कांटा में डबल होगा? क्या माता-पिता की प्रक्रिया समाप्त होने पर वह जुर्माना दूर हो जाता है? क्या यह धागे के अंदर लागू होता है? – tadman

+0

@tadman कूल सवाल। यह प्रति कांटा परत प्रति दंड नहीं है; अगली-स्तरीय कांटा में पहली कांटा के समान सटीक निष्पादन समय होता है। यदि मैं कर सकता हूं तो मैं बाकी परिदृश्यों की जांच करूंगा। –

+1

मै मैकोज़ 10.12 पर रूबी 2.3.3 के साथ वही व्यवहार देख रहा हूं, लेकिन इसे फेडोरा पर पुन: उत्पन्न नहीं कर सकता। यह संभवतः मैकोज़ पर समय कोड के साथ एक मुद्दा है, इसलिए यह एक बग रिपोर्ट दर्ज करने लायक हो सकता है। मेरा मानना ​​है कि यह किसी कारण से समय से संबंधित कार्यों के लिए अलग है। – tadman

उत्तर

4

जैसा कि यह पता चला है, मंदी gmtime_with_leapsecond में time.c में दो फ़ंक्शन कॉल के बराबर माप में है। दो कार्य tzset और localtime_r हैं।

उस खोज ने मुझे Why is tzset() a lot slower after forking on Mac OS X? पर सवाल उठाया, जिसमें से वर्तमान प्रश्न को उचित रूप से डुप्लिकेट कहा जा सकता है।

वहाँ या तो

  • "async-संकेत सुरक्षित" tzset की -नेस और localtime/localtime_r, या
  • की एप्पल के उपयोग से जुड़े वहाँ दो जवाब, न तो स्वीकार कर लिया है, जो बिंदु मूल कारणों के लिए कर रहे एक निष्क्रिय अधिसूचना रजिस्ट्री जो fork 'डी जब अमान्य होती है।

तथ्य यह है कि मंदी केवल कोई ज्ञात छलांग सेकंड (के रूप में उपयोगकर्ता that other guy द्वारा की खोज) के साथ साल में होता है तथ्य यह है कि रूबी gmtime_with_leapsecond फोन नहीं करता है जब यह जानता है कि साल कोई छलांग सेकंड के कारण स्पष्ट रूप से है ।

मुझे यकीन नहीं है कि पाइथन में ऐसी कोई मंदी क्यों नहीं है। एक संभावित स्पष्टीकरण यह है कि fork और utcnow का उपयोग करके मेरी टेस्ट स्क्रिप्ट एक बाल प्रक्रिया नहीं बना रही है जो tzset या localtime/localtime_r पर कॉल करती है।

संबंधित मुद्दे