1lcnt(3)                    Erlang Module Definition                    lcnt(3)
2
3
4

NAME

6       lcnt - A runtime system Lock Profiling tool.
7

DESCRIPTION

9       The  lcnt  module  is used to profile the internal ethread locks in the
10       Erlang Runtime System. With lcnt enabled, internal counters in the run‐
11       time  system are updated each time a lock is taken. The counters stores
12       information about the number of acquisition tries  and  the  number  of
13       collisions that has occurred during the acquisition tries. The counters
14       also record the waiting time a lock has caused  for  a  blocked  thread
15       when a collision has occurred.
16
17       The  data  produced  by  the lock counters will give an estimate on how
18       well the runtime system will behave from a  parallelizable  view  point
19       for the scenarios tested. This tool was mainly developed to help Erlang
20       runtime developers iron out potential and generic bottlenecks.
21
22       Locks in the emulator are named after what type of resource  they  pro‐
23       tect  and  where  in  the emulator they are initialized, those are lock
24       'classes'. Most of those locks are also instantiated several times, and
25       given unique identifiers, to increase locking granularity. Typically an
26       instantiated lock protects a disjunct set of the resource, for  example
27       ets  tables,  processes or ports. In other cases it protects a specific
28       range of a resource, for  example  pix_lock  which  protects  index  to
29       process  mappings,  and  is  given  a unique number within the class. A
30       unique lock in lcnt is referenced by a name (class) and an  identifier:
31       {Name, Id}.
32
33       Some  locks in the system are static and protects global resources, for
34       example bif_timers and the run_queue locks. Other locks are dynamic and
35       not  necessarily  long  lived,  for example process locks and ets-table
36       locks. The statistics data from short lived locks can be  stored  sepa‐
37       rately  when  the locks are deleted. This behavior is by default turned
38       off to save memory but can be  turned  on  via  lcnt:rt_opt({copy_save,
39       true}).  The  lcnt:apply/1,2,3  functions  enables this behavior during
40       profiling.
41

EXPORTS

43       start() -> {ok, Pid} | {error, {already_started, Pid}}
44
45              Types:
46
47                 Pid = pid()
48
49              Starts the lock profiler server. The server only act as a medium
50              for  the  user  and performs filtering and printing of data col‐
51              lected by lcnt:collect/1.
52
53       stop() -> ok
54
55              Stops the lock profiler server.
56
57       collect() -> ok
58
59              Same as collect(node()).
60
61       collect(Node) -> ok
62
63              Types:
64
65                 Node = node()
66
67              Collects lock statistics from the runtime system.  The  function
68              starts  a server if it is not already started. It then populates
69              the server with lock statistics. If the  server  held  any  lock
70              statistics data before the collect then that data is lost.
71
72       clear() -> ok
73
74              Same as clear(node()).
75
76       clear(Node) -> ok
77
78              Types:
79
80                 Node = node()
81
82              Clears  the  internal  lock  statistics from the runtime system.
83              This does not clear the data on the server only on runtime  sys‐
84              tem. All counters for static locks are zeroed, all dynamic locks
85              currently alive are zeroed and all saved locks now destroyed are
86              removed. It also resets the duration timer.
87
88       conflicts() -> ok
89
90              Same as conflicts([]).
91
92       conflicts(Options) -> ok
93
94              Types:
95
96                 Options = [option()]
97                 option() =
98                     {sort, Sort :: sort()} |
99                     {reverse, boolean()} |
100                     {locations, boolean()} |
101                     {thresholds, Thresholds :: [threshold()]} |
102                     {print,
103                      PrintOptions :: [print() | {print(), integer() >= 0}]} |
104                     {max_locks, MaxLocks :: integer() >= 0 | none} |
105                     {combine, boolean()}
106                 print() =
107                     colls | duration | entry | id | name | ratio | time | tries |
108                     type
109                 sort() =
110                     colls | entry | id | name | ratio | time | tries | type
111                 threshold() =
112                     {colls, integer() >= 0} |
113                     {time, integer() >= 0} |
114                     {tries, integer() >= 0}
115
116              Prints a list of internal locks and its statistics.
117
118              For option description, see lcnt:inspect/2.
119
120       locations() -> ok
121
122              Same as locations([]).
123
124       locations(Options) -> ok
125
126              Types:
127
128                 Options = [option()]
129                 option() =
130                     {sort, Sort :: sort()} |
131                     {reverse, boolean()} |
132                     {locations, boolean()} |
133                     {thresholds, Thresholds :: [threshold()]} |
134                     {print,
135                      PrintOptions :: [print() | {print(), integer() >= 0}]} |
136                     {max_locks, MaxLocks :: integer() >= 0 | none} |
137                     {combine, boolean()}
138                 print() =
139                     colls | duration | entry | id | name | ratio | time | tries |
140                     type
141                 sort() =
142                     colls | entry | id | name | ratio | time | tries | type
143                 threshold() =
144                     {colls, integer() >= 0} |
145                     {time, integer() >= 0} |
146                     {tries, integer() >= 0}
147
148              Prints  a  list  of  internal lock counters by source code loca‐
149              tions.
150
151              For option description, see lcnt:inspect/2.
152
153       inspect(Lock) -> ok
154
155              Types:
156
157                 Lock = Name | {Name, Id | [Id]}
158                 Name = atom() | pid() | port()
159                 Id = atom() | integer() | pid() | port()
160
161              Same as inspect(Lock, []).
162
163       inspect(Lock, Options) -> ok
164
165              Types:
166
167                 Lock = Name | {Name, Id | [Id]}
168                 Name = atom() | pid() | port()
169                 Id = atom() | integer() | pid() | port()
170                 Options = [option()]
171                 option() =
172                     {sort, Sort :: sort()} |
173                     {reverse, boolean()} |
174                     {locations, boolean()} |
175                     {thresholds, Thresholds :: [threshold()]} |
176                     {print,
177                      PrintOptions :: [print() | {print(), integer() >= 0}]} |
178                     {max_locks, MaxLocks :: integer() >= 0 | none} |
179                     {combine, boolean()}
180                 print() =
181                     colls | duration | entry | id | name | ratio | time | tries |
182                     type
183                 sort() =
184                     colls | entry | id | name | ratio | time | tries | type
185                 threshold() =
186                     {colls, integer() >= 0} |
187                     {time, integer() >= 0} |
188                     {tries, integer() >= 0}
189
190              Prints a list of internal lock counters for a specific lock.
191
192              Lock Name and Id for ports  and  processes  are  interchangeable
193              with the use of lcnt:swap_pid_keys/0 and is the reason why pid()
194              and port() options can be used in both Name and Id  space.  Both
195              pids  and  ports  are special identifiers with stripped creation
196              and can be recreated with lcnt:pid/2,3 and lcnt:port/1,2.
197
198              Option description:
199
200                {combine, boolean()}:
201                  Combine the statistics from different instances  of  a  lock
202                  class.
203                  Default: true
204
205                {locations, boolean()}:
206                  Print the statistics by source file and line numbers.
207                  Default: false
208
209                {max_locks, MaxLocks}:
210                  Maximum number of locks printed or no limit with none.
211                  Default: 20
212
213                {print, PrintOptions}:
214                  Printing options:
215
216                  name:
217                    Named  lock or named set of locks (classes). The same name
218                    used for initializing the lock in the VM.
219
220                  id:
221                    Internal id for set of  locks,  not  always  unique.  This
222                    could  be  table name for ets tables (db_tab), port id for
223                    ports, integer identifiers for allocators, etc.
224
225                  type:
226                    Type of lock: rw_mutex, mutex,  spinlock,  rw_spinlock  or
227                    proclock.
228
229                  entry:
230                    In  combination  with {locations, true} this option prints
231                    the lock operations source file  and  line  number  entry-
232                    points along with statistics for each entry.
233
234                  tries:
235                    Number of acquisitions of this lock.
236
237                  colls:
238                    Number  of  collisions when a thread tried to acquire this
239                    lock. This is when a trylock is EBUSY, a write try on read
240                    held  rw_lock,  a try read on write held rw_lock, a thread
241                    tries to lock an already locked lock. (Internal states su‐
242                    pervises this).
243
244                  ratio:
245                    The  ratio between the number of collisions and the number
246                    of tries (acquisitions) in percentage.
247
248                  time:
249                    Accumulated waiting time for  this  lock.  This  could  be
250                    greater than actual wall clock time, it is accumulated for
251                    all threads. Trylock conflicts does not accumulate time.
252
253                  duration:
254                    Percentage of accumulated waiting time of wall clock time.
255                    This  percentage can be higher than 100% since accumulated
256                    time is from all threads.
257                Default: [name,id,tries,colls,ratio,time,duration]
258
259                {reverse, boolean()}:
260                  Reverses the order of sorting.
261                  Default: false
262
263                {sort, Sort}:
264                  Column sorting orders.
265                  Default: time
266
267                {thresholds, Thresholds}:
268                  Filtering thresholds. Anything values  above  the  threshold
269                  value are passed through.
270                  Default: [{tries, 0}, {colls, 0}, {time, 0}]
271
272       information() -> ok
273
274              Prints lcnt server state and generic information about collected
275              lock statistics.
276
277       swap_pid_keys() -> ok
278
279              Swaps places on Name and Id space for ports and processes.
280
281       load(Filename) -> ok
282
283              Types:
284
285                 Filename = file:filename()
286
287              Restores previously saved data to the server.
288
289       save(Filename) -> ok
290
291              Types:
292
293                 Filename = file:filename()
294
295              Saves the collected data to file.
296

CONVENIENCE FUNCTIONS

298       The following functions are used for convenience.
299

EXPORTS

301       apply(Fun) -> term()
302
303              Types:
304
305                 Fun = function()
306
307              Same as apply(Fun, []).
308
309       apply(Fun, Args) -> term()
310
311              Types:
312
313                 Fun = function()
314                 Args = [term()]
315
316              Clears the lock counters and then setups the instrumentation  to
317              save  all  destroyed  locks. After setup the function is called,
318              passing the elements in Args as arguments. When the function re‐
319              turns  the  statistics  are immediately collected to the server.
320              After the collection the instrumentation is returned to its pre‐
321              vious behavior. The result of the applied function is returned.
322
323          Warning:
324              This  function should only be used for micro-benchmarks; it sets
325              copy_save to true for  the  duration  of  the  call,  which  can
326              quickly lead to running out of memory.
327
328
329       apply(Module, Function, Args) -> term()
330
331              Types:
332
333                 Module = module()
334                 Function = atom()
335                 Args = [term()]
336
337              Same  as  apply(fun()  ->  erlang:apply(Module,  Function, Args)
338              end).
339
340       pid(Id, Serial) -> pid()
341
342              Types:
343
344                 Id = Serial = integer()
345
346              Same as pid(node(), Id, Serial).
347
348       pid(Node, Id, Serial) -> pid()
349
350              Types:
351
352                 Node = node()
353                 Id = Serial = integer()
354
355              Creates a process id with creation 0.
356
357       port(Id) -> port()
358
359              Types:
360
361                 Id = integer()
362
363              Same as port(node(), Id).
364
365       port(Node, Id) -> port()
366
367              Types:
368
369                 Node = node()
370                 Id = integer()
371
372              Creates a port id with creation 0.
373

INTERNAL RUNTIME LOCK COUNTER CONTROLLERS

375       The following functions control the behavior of the internal counters.
376

EXPORTS

378       rt_collect() -> [lock_counter_data()]
379
380              Types:
381
382                 lock_counter_data() = term()
383
384              Same as rt_collect(node()).
385
386       rt_collect(Node) -> [lock_counter_data()]
387
388              Types:
389
390                 Node = node()
391                 lock_counter_data() = term()
392
393              Returns a list of raw lock counter data.
394
395       rt_clear() -> ok
396
397              Same as rt_clear(node()).
398
399       rt_clear(Node) -> ok
400
401              Types:
402
403                 Node = node()
404
405              Clear the internal counters. Same as lcnt:clear(Node).
406
407       rt_mask() -> [category_atom()]
408
409              Types:
410
411                 category_atom() = atom()
412
413              Same as rt_mask(node()).
414
415       rt_mask(Node) -> [category_atom()]
416
417              Types:
418
419                 Node = node()
420                 category_atom() = atom()
421
422              Refer to rt_mask/2. for a list of valid  categories.  All  cate‐
423              gories are enabled by default.
424
425       rt_mask(Categories) -> ok | {error, copy_save_enabled}
426
427              Types:
428
429                 Categories = [category_atom()]
430                 category_atom() = atom()
431
432              Same as rt_mask(node(), Categories).
433
434       rt_mask(Node, Categories) -> ok | {error, copy_save_enabled}
435
436              Types:
437
438                 Node = node()
439                 Categories = [category_atom()]
440                 category_atom() = atom()
441
442              Sets the lock category mask to the given categories.
443
444              This   will  fail  if  the  copy_save  option  is  enabled;  see
445              lcnt:rt_opt/2.
446
447              Valid categories are:
448
449                * allocator
450
451                * db (ETS tables)
452
453                * debug
454
455                * distribution
456
457                * generic
458
459                * io
460
461                * process
462
463                * scheduler
464
465              This list is subject to change at any time, as is  the  category
466              any given lock may belong to.
467
468       rt_opt(Option) -> boolean()
469
470              Types:
471
472                 Option = {Type, Value :: boolean()}
473                 Type = copy_save | process_locks
474
475              Same as rt_opt(node(), {Type, Value}).
476
477       rt_opt(Node, Option) -> boolean()
478
479              Types:
480
481                 Node = node()
482                 Option = {Type, Value :: boolean()}
483                 Type = copy_save | process_locks
484
485              Option description:
486
487                {copy_save, boolean()}:
488                  Retains the statistics of destroyed locks.
489                  Default: false
490
491            Warning:
492                This  option will use a lot of memory when enabled, which must
493                be reclaimed with lcnt:rt_clear. Note that it  makes  no  dis‐
494                tinction between locks that were destroyed and locks for which
495                counting was disabled, so enabling this  option  will  disable
496                changes to the lock category mask.
497
498
499                {process_locks, boolean()}:
500                  Profile  process  locks, equal to adding process to the lock
501                  category mask; see lcnt:rt_mask/2
502                  Default: true
503

SEE ALSO

505       LCNT User's Guide
506
507
508
509Ericsson AB                       tools 3.5.1                          lcnt(3)
Impressum