Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages


home | help
lcnt(3)			   Erlang Module Definition		       lcnt(3)

       lcnt - A	runtime	system Lock Profiling tool.

       The  lcnt  module  is used to profile the internal ethread locks	in the
       Erlang Runtime System. With lcnt	enabled, internal counters in the run-
       time  system are	updated	each time a lock is taken. The counters	stores
       information about the number of acquisition tries  and  the  number  of
       collisions that has occurred during the acquisition tries. The counters
       also record the waiting time a lock has caused  for  a  blocked	thread
       when a collision	has occurred.

       The  data  produced  by	the lock counters will give an estimate	on how
       well the	runtime	system will behave from	a  parallelizable  view	 point
       for the scenarios tested. This tool was mainly developed	to help	Erlang
       runtime developers iron out potential and generic bottlenecks.

       Locks in	the emulator are named after what type of resource  they  pro-
       tect  and  where	 in  the emulator they are initialized,	those are lock
       'classes'. Most of those	locks are also instantiated several times, and
       given unique identifiers, to increase locking granularity. Typically an
       instantiated lock protects a disjunct set of the	resource, for  example
       ets  tables,  processes or ports. In other cases	it protects a specific
       range of	a resource, for	 example  pix_lock  which  protects  index  to
       process	mappings,  and	is  given  a unique number within the class. A
       unique lock in lcnt is referenced by a name (class) and an  identifier:
       {Name, Id}.

       Some  locks in the system are static and	protects global	resources, for
       example bif_timers and the run_queue locks. Other locks are dynamic and
       not  necessarily	 long  lived,  for example process locks and ets-table
       locks. The statistics data from short lived locks can be	 stored	 sepa-
       rately  when  the locks are deleted. This behavior is by	default	turned
       off to save memory but can be  turned  on  via  lcnt:rt_opt({copy_save,
       true}).	The  lcnt:apply/1,2,3  functions  enables this behavior	during

       start() -> {ok, Pid} | {error, {already_started,	Pid}}


		 Pid = pid()

	      Starts the lock profiler server. The server only act as a	medium
	      for  the	user  and performs filtering and printing of data col-
	      lected by	lcnt:collect/1.

       stop() -> ok

	      Stops the	lock profiler server.

       collect() -> ok

	      Same as collect(node()).

       collect(Node) ->	ok


		 Node =	node()

	      Collects lock statistics from the	runtime	system.	 The  function
	      starts  a	server if it is	not already started. It	then populates
	      the server with lock statistics. If the  server  held  any  lock
	      statistics data before the collect then that data	is lost.

       clear() -> ok

	      Same as clear(node()).

       clear(Node) -> ok


		 Node =	node()

	      Clears  the  internal  lock  statistics from the runtime system.
	      This does	not clear the data on the server only on runtime  sys-
	      tem. All counters	for static locks are zeroed, all dynamic locks
	      currently	alive are zeroed and all saved locks now destroyed are
	      removed. It also resets the duration timer.

       conflicts() -> ok

	      Same as conflicts([]).

       conflicts([Option]) -> ok


		 Option	 =  {sort,  Sort}  |  {reverse,	bool()}	| {thresholds,
		 [Thresholds]} |  {print,  [Print  |  {Print,  integer()}]}  |
		 {max_locks, MaxLocks} | {combine, bool()}
		 Sort  = name |	id | type | tries | colls | ratio | time | en-
		 Thresholds = {tries, integer()} | {colls, integer()} |	{time,
		 Print	=  name	 | id |	type | entry | tries | colls | ratio |
		 time |	duration
		 MaxLocks = integer() |	none

	      Prints a list of internal	locks and its statistics.

	      For option description, see lcnt:inspect/2.

       locations() -> ok

	      Same as locations([]).

       locations([Option]) -> ok


		 Option	= {sort, Sort} | {thresholds, [Thresholds]} |  {print,
		 [Print	| {Print, integer()}]} | {max_locks, MaxLocks} | {com-
		 bine, bool()}
		 Sort =	name | id | type | tries | colls | ratio | time	|  en-
		 Thresholds = {tries, integer()} | {colls, integer()} |	{time,
		 Print = name |	id | type | entry | tries | colls  |  ratio  |
		 time |	duration
		 MaxLocks = integer() |	none

	      Prints  a	 list  of  internal lock counters by source code loca-

	      For option description, see lcnt:inspect/2.

       inspect(Lock) ->	ok

	      Same as inspect(Lock, []).

       inspect(Lock, [Option]) -> ok


		 Lock =	Name | {Name, Id | [Id]}
		 Name =	atom() | pid() | port()
		 Id = atom() | integer() | pid() | port()
		 Option	= {sort, Sort} | {thresholds, [Thresholds]} |  {print,
		 [Print	| {Print, integer()}]} | {max_locks, MaxLocks} | {com-
		 bine, bool()} | {locations, bool()}
		 Sort =	name | id | type | tries | colls | ratio | time
		 Thresholds = {tries, integer()} | {colls, integer()} |	{time,
		 Print	=  name	 | id |	type | entry | tries | colls | ratio |
		 time |	duration
		 MaxLocks = integer() |	none

	      Prints a list of internal	lock counters for a specific lock.

	      Lock Name	and Id for ports  and  processes  are  interchangeable
	      with the use of lcnt:swap_pid_keys/0 and is the reason why pid()
	      and port() options can be	used in	both Name and Id  space.  Both
	      pids  and	 ports	are special identifiers	with stripped creation
	      and can be recreated with	lcnt:pid/2,3 and lcnt:port/1,2.

	      Option description:

		{combine, bool()}:
		  Combine the statistics from different	instances  of  a  lock
		  Default: true

		{locations, bool()}:
		  Print	the statistics by source file and line numbers.
		  Default: false

		{max_locks, MaxLocks}:
		  Maximum number of locks printed or no	limit with none.
		  Default: 20

		{print,	PrintOptions}:
		  Printing options:

		    Named  lock	or named set of	locks (classes). The same name
		    used for initializing the lock in the VM.

		    Internal id	for set	of  locks,  not	 always	 unique.  This
		    could  be  table name for ets tables (db_tab), port	id for
		    ports, integer identifiers for allocators, etc.

		    Type of lock: rw_mutex, mutex,  spinlock,  rw_spinlock  or

		    In	combination  with {locations, true} this option	prints
		    the	lock operations	source file  and  line	number	entry-
		    points along with statistics for each entry.

		    Number of acquisitions of this lock.

		    Number  of	collisions when	a thread tried to acquire this
		    lock. This is when a trylock is EBUSY, a write try on read
		    held  rw_lock,  a try read on write	held rw_lock, a	thread
		    tries to lock an already locked lock. (Internal states su-
		    pervises this).

		    The	 ratio between the number of collisions	and the	number
		    of tries (acquisitions) in percentage.

		    Accumulated	waiting	time for  this	lock.  This  could  be
		    greater than actual	wall clock time, it is accumulated for
		    all	threads. Trylock conflicts does	not accumulate time.

		    Percentage of accumulated waiting time of wall clock time.
		    This  percentage can be higher than	100% since accumulated
		    time is from all threads.
		Default: [name,id,tries,colls,ratio,time,duration]

		{reverse, bool()}:
		  Reverses the order of	sorting.
		  Default: false

		{sort, Sort}:
		  Column sorting orders.
		  Default: time

		{thresholds, Thresholds}:
		  Filtering thresholds.	Anything values	 above	the  threshold
		  value	are passed through.
		  Default: [{tries, 0},	{colls,	0}, {time, 0}]

       information() ->	ok

	      Prints lcnt server state and generic information about collected
	      lock statistics.

       swap_pid_keys() -> ok

	      Swaps places on Name and Id space	for ports and processes.

       load(Filename) -> ok


		 Filename = filename()

	      Restores previously saved	data to	the server.

       save(Filename) -> ok


		 Filename = filename()

	      Saves the	collected data to file.

       The following functions are used	for convenience.

       apply(Fun) -> term()


		 Fun = fun()

	      Same as apply(Fun, []).

       apply(Fun, Args)	-> term()


		 Fun = fun()
		 Args =	[term()]

	      Same as apply(Module, Function, Args).

       apply(Module, Function, Args) ->	term()


		 Module	= atom()
		 Function = atom()
		 Args =	[term()]

	      Clears the lock counters and then	setups the instrumentation  to
	      save  all	 destroyed  locks. After setup the function is called,
	      passing the elements in Args as arguments. When the function re-
	      turns  the  statistics  are immediately collected	to the server.
	      After the	collection the instrumentation is returned to its pre-
	      vious behavior. The result of the	applied	function is returned.

	      This  function should only be used for micro-benchmarks; it sets
	      copy_save	to true	for  the  duration  of	the  call,  which  can
	      quickly lead to running out of memory.

       pid(Id, Serial) -> pid()

	      Same as pid(node(), Id, Serial).

       pid(Node, Id, Serial) ->	pid()


		 Node =	node()
		 Id = integer()
		 Serial	= integer()

	      Creates a	process	id with	creation 0.

       port(Id)	-> port()

	      Same as port(node(), Id).

       port(Node, Id) -> port()


		 Node =	node()
		 Id = integer()

	      Creates a	port id	with creation 0.

       The following functions control the behavior of the internal counters.

       rt_collect() -> [lock_counter_data()]

	      Same as rt_collect(node()).

       rt_collect(Node)	-> [lock_counter_data()]


		 Node =	node()

	      Returns a	list of	raw lock counter data.

       rt_clear() -> ok

	      Same as rt_clear(node()).

       rt_clear(Node) -> ok


		 Node =	node()

	      Clear the	internal counters. Same	as lcnt:clear(Node).

       rt_mask() -> [category_atom()]

	      Same as rt_mask(node()).

       rt_mask(Node) ->	[category_atom()]


		 Node =	node()

	      Refer  to	 rt_mask/2  for	 a list	of valid categories. All cate-
	      gories are enabled by default.

       rt_mask(Categories) -> ok | {error, copy_save_enabled}


		 Categories = [atom()]

	      Same as rt_mask(node(), Categories).

       rt_mask(Node, Categories) -> ok | {error, copy_save_enabled}


		 Node =	node()
		 Categories = [atom()]

	      Sets the lock category mask to the given categories.

	      This  will  fail	if  the	 copy_save  option  is	enabled;   see

	      Valid categories are:

		* allocator

		* db (ETS tables)

		* debug

		* distribution

		* generic

		* io

		* process

		* scheduler

	      This  list  is subject to	change at any time, as is the category
	      any given	lock may belong	to.

       rt_opt({Type, bool()}) -> bool()

	      Same as rt_opt(node(), {Type, Opt}).

       rt_opt(Node, {Type, bool()}) -> bool()


		 Node =	node()
		 Type =	copy_save | process_locks

	      Option description:

		{copy_save, bool()}:
		  Retains the statistics of destroyed locks.
		  Default: false

		This option will use a lot of memory when enabled, which  must
		be  reclaimed  with  lcnt:rt_clear. Note that it makes no dis-
		tinction between locks that were destroyed and locks for which
		counting  was  disabled,  so enabling this option will disable
		changes	to the lock category mask.

		{process_locks,	bool()}:
		  Profile process locks, equal to adding process to  the  lock
		  category mask; see lcnt:rt_mask/2
		  Default: true

       LCNT User's Guide

Ericsson AB			   tools 3.1			       lcnt(3)


Want to link to this manual page? Use this URL:

home | help