User Tools

Site Tools


cs326:labp

CSci 326 - Lab P

Purpose: to become familiar with process concepts.

Record the results of the steps below, and turn in a writeup to the instructor. Copy the program file processes.ex found below into an editor and have a look at it. Note the use of spawn, send, and receive. This program is adapted from the Erlang program given on page 189 of Programming Erlang, 2nd Ed. by Joe Armstrong.

Part 1. First, make a table with four columns: #processes | CPU time | Wall-clock time | Max processes. You'll only need to record the maximum number of processes the first time, and when we change it.

  1. Start processes.ex in iex.
  2. Determine the maximum number of processes available and record the creation time (CPU and wall-clock) for 20,000 processes:
    iex> Processes.max(20000)
  3. Record what happens when trying to run 40,000 processes.
  4. Record what happens when trying to run 100,000 processes.
  5. Record what happens when trying to run 300,000 processes. Note: this will cause a major train wreck, which you can get out of typing Ctrl-C twice or Ctrl-C and (a)bort.

Part 2. We can tell BEAM how many processes to use at startup with the appropriate command line flags. Restart iex like this:

iex --erl "+P 3000000" processes.ex
  1. Determine the maximum number of processes available and record the results of running 300,000 processes
  2. Record the results of running 1,000,000 processes
  3. Record the results of running 2,000,000 processes
  4. Record the results of running 4,000,000 processes. Running too many more than 4,000,000 causes a major train wreck, don't even try.
  5. Start the BEAM observer by entering :observer.start. From the observer, record the number of logical CPUs and Online schedulers. Switch to the Load Charts tab
  6. In iex, run 1,000,000 processes again. Watch how the CPU load changes in the observer. After the call to Processes.max completes, record (approximately) the greatest scheduler utilization and largest memory usage shown.

Here's what we did when we restarted iex with the –erl option (from the Erlang Runtime Systems manual):

+P Number

Sets the maximum number of simultaneously existing processes for this system if a Number is passed as value. Valid range for Number is [1024-134217727]

NOTE: The actual maximum chosen may be much larger than the Number passed. Currently the runtime system often, but not always, chooses a value that is a power of 2. This might, however, be changed in the future. The actual value chosen can be checked by calling erlang:system_info(process_limit).

The default value is 262144

Question: was the maximum number of processes you recorded for Part 1, question 5 a power of 2? How might you use Elixir to find out? Hint: recall a certain program you wrote for Homework 1…

Part 3. And now…try to understand what we did.

The function max uses several Erlang library functions, and it would be nice to know a little bit about what they do. Summarize the behavior of:

erlang:system_info (wow this has many many options…do a search for process_limit, the only option we used) statistics (same…search for runtime and wall_clock)

Finally, what is the purpose of the :die message sent to each spawned process?

Write up your results and turn in or email to the instructor.

processes.ex

defmodule Processes do
  @moduledoc """
   Gather statistics about the maximum number of 
   processes in an iex session, and the average amount
   of time process creation takes
  """

  @doc """
   max(N) - Time the task of creating N processes, then destroy them
   """
  @spec max(integer)::atom
  def max(nprocs) when nprocs > 0 do
    limit = :erlang.system_info(:process_limit)
    :io.format("Maximum allowed processes:~p~n",[limit])
    :erlang.statistics(:runtime)
    :erlang.statistics(:wall_clock)
    procs = for _x <- 1..nprocs, do: spawn(fn -> wait() end)
    {_, time1} = :erlang.statistics(:runtime)
    {_, time2} = :erlang.statistics(:wall_clock)
    Enum.each(procs, fn(pid) -> send(pid, :die) end)
    ms1 = time1 * 1000 / nprocs
    ms2 = time2 * 1000 / nprocs
    :io.format("Process spawn time=~p (~p wall-clock) microseconds~n",
	      [ms1, ms2])
  end

  defp wait() do
    receive do
	:die -> :void
	_    -> IO.puts "unknown message, ignoring"
    end
  end

end
cs326/labp.txt · Last modified: 2021/10/19 22:49 by scarl