Erlang 21 - 8. Processes

8 प्रक्रियाएँ




erlang

8 प्रक्रियाएँ

8.1 एर्लैंग प्रोसेस बनाना

ऑपरेटिंग सिस्टम में थ्रेड्स और प्रक्रियाओं की तुलना में एरलैंग प्रक्रिया हल्की होती है।

एक नवप्रवर्तित एर्लैंग प्रक्रिया HiPE समर्थन के बिना गैर-एसएमपी एमुलेटर में स्मृति के 309 शब्दों का उपयोग करती है। (SMP समर्थन और HiPE समर्थन दोनों इस आकार को जोड़ते हैं।) आकार निम्नानुसार पाया जा सकता है:

Erlang (BEAM) emulator version 5.6 [async-threads:0] [kernel-poll:false]

Eshell V5.6  (abort with ^G)
1> Fun = fun() -> receive after infinity -> ok end end.
#Fun<...>
2> {_,Bytes} = process_info(spawn(Fun), memory).
{memory,1232}
3> Bytes div erlang:system_info(wordsize).
309

आकार में ढेर क्षेत्र के लिए 233 शब्द शामिल हैं (जिसमें स्टैक शामिल है)। कचरा संग्रहकर्ता आवश्यकतानुसार ढेर बढ़ा देता है।

एक प्रक्रिया के लिए मुख्य (बाहरी) लूप पूंछ-पुनरावर्ती होना चाहिए। अन्यथा, प्रक्रिया समाप्त होने तक स्टैक बढ़ता है।

ऐसा न करें

loop() -> 
  receive
     {sys, Msg} ->
         handle_sys_msg(Msg),
         loop();
     {From, Msg} ->
          Reply = handle_msg(Msg),
          From ! Reply,
          loop()
  end,
  io:format("Message is processed~n", []).

io:format/2 कॉल कभी भी निष्पादित नहीं की जाएगी, लेकिन एक वापसी पते को अभी भी स्टैक पर धकेल दिया जाएगा प्रत्येक बार loop/0 को पुनरावर्ती कहा जाता है। फ़ंक्शन का सही पूंछ-पुनरावर्ती संस्करण निम्नानुसार दिखता है:

करना

loop() -> 
   receive
      {sys, Msg} ->
         handle_sys_msg(Msg),
         loop();
      {From, Msg} ->
         Reply = handle_msg(Msg),
         From ! Reply,
         loop()
 end.

प्रारंभिक ढेर का आकार

233 शब्दों का डिफ़ॉल्ट प्रारंभिक ढेर का आकार सैकड़ों या हजारों प्रक्रियाओं के साथ एर्लांग सिस्टम का समर्थन करने के लिए काफी रूढ़िवादी है। कचरा संग्रहकर्ता बढ़ता है और आवश्यकतानुसार ढेर को सिकोड़ता है।

ऐसी प्रणाली में जो तुलनात्मक रूप से कुछ प्रक्रियाओं का उपयोग करती है, erl या spawn_opt/4 लिए spawn_opt/4 विकल्प का उपयोग करके erl या प्रक्रिया-प्रति-प्रक्रिया के आधार पर या तो +h विकल्प का उपयोग करके न्यूनतम हीप आकार बढ़ाकर प्रदर्शन में सुधार किया जा सकता है।

लाभ दुगुना है:

  • हालांकि कचरा संग्रहकर्ता ढेर को बढ़ाता है, यह इसे चरण-दर-चरण बढ़ता है, जो कि प्रक्रिया को पैदा करने पर सीधे एक बड़ा ढेर स्थापित करने की तुलना में अधिक महंगा है।
  • यदि यह उस पर संग्रहीत डेटा की मात्रा से बहुत बड़ा है, तो कचरा कलेक्टर भी ढेर को सिकोड़ सकता है; न्यूनतम हीप आकार सेट करने से रोकता है।
चेतावनी

एमुलेटर संभवतः अधिक मेमोरी का उपयोग करता है, और क्योंकि कचरा संग्रह कम बार होता है, विशाल बायनेरिज़ को अधिक लंबे समय तक रखा जा सकता है।

कई प्रक्रियाओं वाली प्रणालियों में, कम समय के लिए चलने वाले कम्प्यूटेशन कार्यों को उच्च न्यूनतम आकार के साथ एक नई प्रक्रिया में बंद किया जा सकता है। जब प्रक्रिया की जाती है, तो यह दूसरी प्रक्रिया के लिए अभिकलन का परिणाम भेजता है और समाप्त हो जाता है। यदि न्यूनतम हीप आकार की गणना ठीक से की जाती है, तो प्रक्रिया को किसी भी तरह का कचरा संग्रहण नहीं करना पड़ सकता है। उचित माप के बिना इस अनुकूलन का प्रयास नहीं किया जाना है।

8.2 प्रक्रिया संदेश

Erlang प्रक्रियाओं के बीच संदेशों में सभी डेटा की प्रतिलिपि बनाई जाती है, केवल उसी Erlang नोड पर refc binaries को छोड़कर।

जब कोई संदेश किसी अन्य Erlang नोड पर एक प्रक्रिया को भेजा जाता है, तो इसे पहली बार TCP / IP सॉकेट के माध्यम से भेजे जाने से पहले Erlang बाहरी प्रारूप में एन्कोड किया जाता है। Erlang नोड प्राप्त करना संदेश को डिकोड करता है और इसे सही प्रक्रिया में वितरित करता है।

लगातार पूल

लगातार एरलंग शब्द (जिन्हें शाब्दिक भी कहा जाता है ) निरंतर ताल में रखे जाते हैं; प्रत्येक लोड किए गए मॉड्यूल का अपना पूल है। निम्न फ़ंक्शन हर बार ट्यूपल का निर्माण नहीं करता है जिसे यह कहा जाता है (केवल यह है कि अगली बार कचरा कलेक्टर को चलाने के लिए छोड़ दिया गया था), लेकिन ट्यूपल मॉड्यूल के स्थिर पूल में स्थित है:

करना

days_in_month(M) ->
    element(M, {31,28,31,30,31,30,31,31,30,31,30,31}).

लेकिन अगर एक स्थिरांक को दूसरी प्रक्रिया में भेजा जाता है (या एक Ets तालिका में संग्रहीत), तो इसे कॉपी किया जाता है । कारण यह है कि रनटाइम सिस्टम को स्थिरांक के साथ कोड को ठीक से अनलोड करने के लिए स्थिरांक के सभी संदर्भों का ट्रैक रखने में सक्षम होना चाहिए। (जब कोड अनलोड किया जाता है, तो कॉन्स्टेंट को उन प्रक्रियाओं के ढेर पर कॉपी किया जाता है जो उन्हें संदर्भित करते हैं।) भविष्य की एर्लैंग / ओटीपी रिलीज़ में कॉन्स्टेंट की नकल को समाप्त किया जा सकता है।

शेयरिंग का नुकसान

साझा सबटर्म्स निम्नलिखित मामलों में संरक्षित नहीं हैं:

  • जब एक शब्द को दूसरी प्रक्रिया में भेजा जाता है
  • जब किसी शब्द को spawn कॉल में प्रारंभिक प्रक्रिया के तर्क के रूप में पारित किया जाता है
  • जब एक शब्द Ets तालिका में संग्रहीत किया जाता है

वह एक अनुकूलन है। अधिकांश एप्लिकेशन साझा किए गए सबटम्स के साथ संदेश नहीं भेजते हैं।

निम्न उदाहरण से पता चलता है कि कैसे एक साझा सबटर्म बनाया जा सकता है:

kilo_byte() ->
    kilo_byte(10, [42]).

kilo_byte(0, Acc) ->
    Acc;
kilo_byte(N, Acc) ->
    kilo_byte(N-1, [Acc|Acc]).

kilo_byte/1 एक गहरी सूची बनाता है। यदि list_to_binary/1 को कहा जाता है, तो गहरी सूची को 1024 बाइट्स के बाइनरी में परिवर्तित किया जा सकता है:

1> byte_size(list_to_binary(efficiency_guide:kilo_byte())).
1024

erts_debug:size/1 BIF का उपयोग करके, यह देखा जा सकता है कि गहरी सूची में केवल ढेर शब्दों के 22 शब्दों की आवश्यकता है:

2> erts_debug:size(efficiency_guide:kilo_byte()).
22

erts_debug:flat_size/1 का उपयोग करना erts_debug:flat_size/1 BIF, साझा करने पर ध्यान न दिए जाने पर गहरी सूची के आकार की गणना की जा सकती है। यह सूची का आकार बन जाता है जब इसे किसी अन्य प्रक्रिया में भेजा जाता है या Ets तालिका में संग्रहीत किया जाता है:

3> erts_debug:flat_size(efficiency_guide:kilo_byte()).
4094

यह सत्यापित किया जा सकता है कि यदि डेटा को Ets तालिका में डाला गया है तो साझाकरण खो जाएगा:

4> T = ets:new(tab, []).
#Ref<0.1662103692.2407923716.214181>
5> ets:insert(T, {key,efficiency_guide:kilo_byte()}).
true
6> erts_debug:size(element(2, hd(ets:lookup(T, key)))).
4094
7> erts_debug:flat_size(element(2, hd(ets:lookup(T, key)))).
4094

जब डेटा एक Ets तालिका से erts_debug:size/1 , तो erts_debug:size/1 और erts_debug:flat_size/1 समान मान लौटाते हैं। शेयरिंग खो गया है।

भविष्य में एर्लैंग / ओटीपी जारी होने पर, इसे साझाकरण को संरक्षित करने (वैकल्पिक रूप से) के लिए लागू किया जा सकता है।

8.3 एसएमपी एमुलेटर

एसएमपी एमुलेटर (आर 11 बी में पेश किया गया) कई एर्लांग शेड्यूलर थ्रेड्स (आमतौर पर कोर की संख्या के समान) चलाकर मल्टी-कोर या मल्टी-सीपीयू कंप्यूटर का लाभ उठाता है। प्रत्येक शेड्यूलर थ्रेड शेड्यूल एरलैंग उसी तरह से प्रक्रिया करता है जैसे एर्लांग शेड्यूलर गैर-एसएमपी एमुलेटर में।

एसएमपी एमुलेटर का उपयोग करके प्रदर्शन प्राप्त करने के लिए, आपके आवेदन में अधिकांश समय एक से अधिक रन करने योग्य एर्लैंग प्रक्रिया होनी चाहिए । अन्यथा, एर्लैंग एमुलेटर उस समय केवल एक एर्लैंग प्रक्रिया चला सकता है, लेकिन आपको लॉकिंग के लिए ओवरहेड का भुगतान करना होगा। हालांकि एर्लैंग / ओटीपी लॉकिंग ओवरहेड को जितना संभव हो उतना कम करने की कोशिश करता है, लेकिन यह कभी भी शून्य नहीं होगा।

समवर्ती प्रतीत होने वाले बेंचमार्क अक्सर अनुक्रमिक होते हैं। उदाहरण के लिए, एस्टोन बेंचमार्क पूरी तरह से अनुक्रमिक है। तो "रिंग बेंचमार्क" का सबसे आम कार्यान्वयन है; आमतौर पर एक प्रक्रिया सक्रिय है, जबकि अन्य एक receive बयान में प्रतीक्षा receive