ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Process 생성하기
    카테고리 없음 2022. 7. 19. 18:13

    앞글에도 적었지만, Elixir 의 Process는 주요 특성이 있습니다.

     

    • Process는 독립적으로 동시에 실행된다. 한 Process의 종료가 다른 Process에 영향을 미치지 않는다. (Link 라는 개념으로 영향을 줄수도 있는데, 이는 다음에 적겠습니다.)
    • Process 간에 공유되는 것은 없으며,  Process간의 협업은 Message 전달로 이루어진다. (함수 호출이 아닌, 메세지 전달)

     

    이들에 대해서 하나씩,  상세히 적어보겠습니다. 

     

    우선, 가장 쉽게 Process를 느껴보도록 하죠..

    iex 를 실행시킨 후, 아래와 같이 self() 명령을 치면,   

    #PID<0.106.0> 과 같은 Process ID 가 나옵니다.  

    이 PID 는 iex 자체의 Process 입니다.   즉 , iex 도 Elixir Process 로 실행이되는 것입니다. 

    PID 는 실행시키는 PC 마다 환경에 따라 다른 값이 나올 수 있습니다. 

     

    그 다음에는 Process에게 Message를 보내보죠. 

    아래와 같이 send 함수를 이용해서 메세지를 보낼수 있으며, 보내는 값은 어떤 값이라도 괜찮습니다. 

     

    send( self(), {:hello, "Process", %{a: 1, b: 2}} )

    화면에 나타난 값 "{:hello, "Process", %{a: 1, b: 2}}" 은 send 함수의 return 값이 출력된것이지, 

    수신된 message 자체를 출력한것은 아닙니다.  iex 에서 어떤 함수를 호출하면, 그 함수의 return 값이 출력되는 것 처럼. send 함수의 return 값이 화면에 출력된 것 입니다.  send 함수는 어떤 process에게 전송된 메세지를 반환하게 되며, 그 메세지가 화면에

    출력 된것 입니다. 

     

    위의 명령은 메세지를 받는 대상이 self() 이므로, 자기 자신에게 메세지를 보낸 것입니다. 

    수신된 메세지는 Process의 Message Mailbox 에 저장되게 됩니다. 

     

    프로그램을 개발할때 각 Process에 수신된 메세지는 receive 함수로 읽게 됩니다.  이의 사용은 잠시후 보겠습니다. 

     

     

    iex 에서는 flush() 명령으로, 수신된 메세지가 있으면 이를 읽어와서 화면에 표시하게 됩니다. 

     

    첫번째, flush() 명령에서는 수신된 메세지인 "{:hello, "Process", %{a: 1, b: 2}}" 를 출력합니다. 

    두번째 flush() 에서는 이미 메세지를 읽어왔기 때문에 아무런 값이 출력되지 않습니다. 

     

    Process간의 통신(협업)은 모두 메세지를 보내는 send 함수와 메세지를 수신하는 receive 함수(iex 에서는 flush) 로 이루어집니다. 

     

     

    이제, Process 생성에 대해 알아보겠습니다. 

    Process의 생성은 spawn 과 spawn_link 함수로 합니다.  

    우선은 spawn 함수보터 알아 보겠습니다. 

     

     

    우선 아주 간단히, 자신의 pid 를 출력하는 Process를 만들어 보겠습니다. 

     

    IO.inspect(self())

    이 코드를 실행하면, 위와 같이 iex 창에서 self() 를 실행한것 같이 iex 자체의 pid 를 출력합니다. 

     

    spawn(fn -> IO.inspect(self()) end)

    동일한 code 를 spawn 을 통해서 실행을 시켰더니, 다른 PID 값이 출력되었습니다. 

    즉, 이는 spawn 을 통해서 새로운 Process를 생성하고, 이 Process가 self() 를 실행하니, 새로 생성된 Process의 ID 가 출력 된것 입니다. 

     

    이와 같이, Elixir 는 spawn 함수를 이용하여 Process 를 만들수 있습니다. 

    위의 코드에서, IO.inspect(self()) 를 출력한 Process는 더이상 실행할 code 가 없으므로, 종료가 된 상태 입니다. 

     

     

    spawn에 대해서 좀더 알아보기 위해 , 계산에 오래 걸리는 함수를 하나 만들어 보겠습니다. 

     

    다음은, 원주율 Pi 를 계산하는 코드 입니다. (참조 : https://ko.wikihow.com/Pi-%EA%B3%84%EC%82%B0%ED%95%98%EB%8A%94-%EB%B2%95 )

     

    1..10_000_000//2 |> Enum.reduce({0,1},fn i,{pi,mul} -> {pi + (4/i) *mul , mul * -1}  end)

    (1..10_000_000//2 에서 //2는 최신 Elixir version에서 지원하는 step 입니다. - elixir v1.12.0 부터 step 이 지원됩니다.   이 값은 1, 3, 5, 7 ,.. 의 수열을 만듭니다.)

     

    컴퓨터의 성능에 따라 다르지만, 이 코드를 실행시키면 대략 10초 정도의 시간이 소요됩니다.  코드 입력후, Enter 키를 치면. 

    대략 10초 동안 iex 가 반응이 없게됩니다.   즉, iex process가 계산을 하고 , 계산이 완료된 후 결과를 출력하는 것 입니다. 

     

    동일 코드를 process를 생성해서 실행해보겠습니다. 

     

    spawn(fn -> 1..10_000_000//2 |> Enum.reduce({0,1},fn i,{pi,mul} -> {pi + (4/i) *mul , mul * -1}  end) |> IO.inspect()  end)

    코드를 입력하고 Enter를 치면, 아까와는 다르게, iex 는 바로 반응을 하고

    대략 10초 전후에 계산 결과가 화면에 출력 됩니다. 

     

    코드를 실행시킨 후, 바로 출력된 PID 값은 위의 코드에서와 같이 새로 생성한 Process의 ID 입니다. 

     

    즉 시간이 걸리는 연산처리는 새로 생성된 프로세스에서 실행을 했으니, iex 는 바로 응답을 할 수 있는것이고

    생성된 프로세스가 연산을 마친 후, 계산 결과를 화면에 출력한 것 입니다. 

     

    이와 같이 Elixir 에서는 Process를 생성하여, 어떤 일을 시킬 수 있습니다. 

     

    이번 장에서는 우선 Process의 생성만 다루고, 다음장에서는 Process간의 통신을 다루겠습니다. 

     

     

     

Designed by Tistory.