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([Option]) -> ok
93
94              Types:
95
96                 Option  =  {sort,  Sort}  |  {reverse, bool()} | {thresholds,
97                 [Thresholds]} |  {print,  [Print  |  {Print,  integer()}]}  |
98                 {max_locks, MaxLocks} | {combine, bool()}
99                 Sort  =  name  |  id  | type | tries | colls | ratio | time |
100                 entry
101                 Thresholds = {tries, integer()} | {colls, integer()} | {time,
102                 integer()}
103                 Print  =  name  | id | type | entry | tries | colls | ratio |
104                 time | duration
105                 MaxLocks = integer() | none
106
107              Prints a list of internal locks and its statistics.
108
109              For option description, see lcnt:inspect/2.
110
111       locations() -> ok
112
113              Same as locations([]).
114
115       locations([Option]) -> ok
116
117              Types:
118
119                 Option = {sort, Sort} | {thresholds, [Thresholds]} |  {print,
120                 [Print | {Print, integer()}]} | {max_locks, MaxLocks} | {com‐
121                 bine, bool()}
122                 Sort = name | id | type | tries | colls  |  ratio  |  time  |
123                 entry
124                 Thresholds = {tries, integer()} | {colls, integer()} | {time,
125                 integer()}
126                 Print = name | id | type | entry | tries | colls  |  ratio  |
127                 time | duration
128                 MaxLocks = integer() | none
129
130              Prints  a  list  of  internal lock counters by source code loca‐
131              tions.
132
133              For option description, see lcnt:inspect/2.
134
135       inspect(Lock) -> ok
136
137              Same as inspect(Lock, []).
138
139       inspect(Lock, [Option]) -> ok
140
141              Types:
142
143                 Lock = Name | {Name, Id | [Id]}
144                 Name = atom() | pid() | port()
145                 Id = atom() | integer() | pid() | port()
146                 Option = {sort, Sort} | {thresholds, [Thresholds]} |  {print,
147                 [Print | {Print, integer()}]} | {max_locks, MaxLocks} | {com‐
148                 bine, bool()} | {locations, bool()}
149                 Sort = name | id | type | tries | colls | ratio | time
150                 Thresholds = {tries, integer()} | {colls, integer()} | {time,
151                 integer()}
152                 Print  =  name  | id | type | entry | tries | colls | ratio |
153                 time | duration
154                 MaxLocks = integer() | none
155
156              Prints a list of internal lock counters for a specific lock.
157
158              Lock Name and Id for ports  and  processes  are  interchangeable
159              with the use of lcnt:swap_pid_keys/0 and is the reason why pid()
160              and port() options can be used in both Name and Id  space.  Both
161              pids  and  ports  are special identifiers with stripped creation
162              and can be recreated with lcnt:pid/2,3 and lcnt:port/1,2.
163
164              Option description:
165
166                {combine, bool()}:
167                  Combine the statistics from different instances  of  a  lock
168                  class.
169                  Default: true
170
171                {locations, bool()}:
172                  Print the statistics by source file and line numbers.
173                  Default: false
174
175                {max_locks, MaxLocks}:
176                  Maximum number of locks printed or no limit with none.
177                  Default: 20
178
179                {print, PrintOptions}:
180                  Printing options:
181
182                  name:
183                    Named  lock or named set of locks (classes). The same name
184                    used for initializing the lock in the VM.
185
186                  id:
187                    Internal id for set of  locks,  not  always  unique.  This
188                    could  be  table name for ets tables (db_tab), port id for
189                    ports, integer identifiers for allocators, etc.
190
191                  type:
192                    Type of lock: rw_mutex, mutex,  spinlock,  rw_spinlock  or
193                    proclock.
194
195                  entry:
196                    In  combination  with {locations, true} this option prints
197                    the lock operations source file  and  line  number  entry-
198                    points along with statistics for each entry.
199
200                  tries:
201                    Number of acquisitions of this lock.
202
203                  colls:
204                    Number  of  collisions when a thread tried to acquire this
205                    lock. This is when a trylock is EBUSY, a write try on read
206                    held  rw_lock,  a try read on write held rw_lock, a thread
207                    tries to lock an already  locked  lock.  (Internal  states
208                    supervises this).
209
210                  ratio:
211                    The  ratio between the number of collisions and the number
212                    of tries (acquisitions) in percentage.
213
214                  time:
215                    Accumulated waiting time for  this  lock.  This  could  be
216                    greater than actual wall clock time, it is accumulated for
217                    all threads. Trylock conflicts does not accumulate time.
218
219                  duration:
220                    Percentage of accumulated waiting time of wall clock time.
221                    This  percentage can be higher than 100% since accumulated
222                    time is from all threads.
223                Default: [name,id,tries,colls,ratio,time,duration]
224
225                {reverse, bool()}:
226                  Reverses the order of sorting.
227                  Default: false
228
229                {sort, Sort}:
230                  Column sorting orders.
231                  Default: time
232
233                {thresholds, Thresholds}:
234                  Filtering thresholds. Anything values  above  the  threshold
235                  value are passed through.
236                  Default: [{tries, 0}, {colls, 0}, {time, 0}]
237
238       information() -> ok
239
240              Prints lcnt server state and generic information about collected
241              lock statistics.
242
243       swap_pid_keys() -> ok
244
245              Swaps places on Name and Id space for ports and processes.
246
247       load(Filename) -> ok
248
249              Types:
250
251                 Filename = filename()
252
253              Restores previously saved data to the server.
254
255       save(Filename) -> ok
256
257              Types:
258
259                 Filename = filename()
260
261              Saves the collected data to file.
262

CONVENIENCE FUNCTIONS

264       The following functions are used for convenience.
265

EXPORTS

267       apply(Fun) -> term()
268
269              Types:
270
271                 Fun = fun()
272
273              Same as apply(Fun, []).
274
275       apply(Fun, Args) -> term()
276
277              Types:
278
279                 Fun = fun()
280                 Args = [term()]
281
282              Same as apply(Module, Function, Args).
283
284       apply(Module, Function, Args) -> term()
285
286              Types:
287
288                 Module = atom()
289                 Function = atom()
290                 Args = [term()]
291
292              Clears the lock counters and then setups the instrumentation  to
293              save  all  destroyed  locks. After setup the function is called,
294              passing the elements in Args as  arguments.  When  the  function
295              returns  the statistics are immediately collected to the server.
296              After the collection the instrumentation is returned to its pre‐
297              vious behavior. The result of the applied function is returned.
298
299          Warning:
300              This  function should only be used for micro-benchmarks; it sets
301              copy_save to true for  the  duration  of  the  call,  which  can
302              quickly lead to running out of memory.
303
304
305       pid(Id, Serial) -> pid()
306
307              Same as pid(node(), Id, Serial).
308
309       pid(Node, Id, Serial) -> pid()
310
311              Types:
312
313                 Node = node()
314                 Id = integer()
315                 Serial = integer()
316
317              Creates a process id with creation 0.
318
319       port(Id) -> port()
320
321              Same as port(node(), Id).
322
323       port(Node, Id) -> port()
324
325              Types:
326
327                 Node = node()
328                 Id = integer()
329
330              Creates a port id with creation 0.
331

INTERNAL RUNTIME LOCK COUNTER CONTROLLERS

333       The following functions control the behavior of the internal counters.
334

EXPORTS

336       rt_collect() -> [lock_counter_data()]
337
338              Same as rt_collect(node()).
339
340       rt_collect(Node) -> [lock_counter_data()]
341
342              Types:
343
344                 Node = node()
345
346              Returns a list of raw lock counter data.
347
348       rt_clear() -> ok
349
350              Same as rt_clear(node()).
351
352       rt_clear(Node) -> ok
353
354              Types:
355
356                 Node = node()
357
358              Clear the internal counters. Same as lcnt:clear(Node).
359
360       rt_mask() -> [category_atom()]
361
362              Same as rt_mask(node()).
363
364       rt_mask(Node) -> [category_atom()]
365
366              Types:
367
368                 Node = node()
369
370              Refer  to  rt_mask/2  for  a list of valid categories. All cate‐
371              gories are enabled by default.
372
373       rt_mask(Categories) -> ok | {error, copy_save_enabled}
374
375              Types:
376
377                 Categories = [atom()]
378
379              Same as rt_mask(node(), Categories).
380
381       rt_mask(Node, Categories) -> ok | {error, copy_save_enabled}
382
383              Types:
384
385                 Node = node()
386                 Categories = [atom()]
387
388              Sets the lock category mask to the given categories.
389
390              This  will  fail  if  the  copy_save  option  is  enabled;   see
391              lcnt:rt_opt/2.
392
393              Valid categories are:
394
395                * allocator
396
397                * db (ETS tables)
398
399                * debug
400
401                * distribution
402
403                * generic
404
405                * io
406
407                * process
408
409                * scheduler
410
411              This  list  is subject to change at any time, as is the category
412              any given lock may belong to.
413
414       rt_opt({Type, bool()}) -> bool()
415
416              Same as rt_opt(node(), {Type, Opt}).
417
418       rt_opt(Node, {Type, bool()}) -> bool()
419
420              Types:
421
422                 Node = node()
423                 Type = copy_save | process_locks
424
425              Option description:
426
427                {copy_save, bool()}:
428                  Retains the statistics of destroyed locks.
429                  Default: false
430
431            Warning:
432                This option will use a lot of memory when enabled, which  must
433                be  reclaimed  with  lcnt:rt_clear. Note that it makes no dis‐
434                tinction between locks that were destroyed and locks for which
435                counting  was  disabled,  so enabling this option will disable
436                changes to the lock category mask.
437
438
439                {process_locks, bool()}:
440                  Profile process locks, equal to adding process to  the  lock
441                  category mask; see lcnt:rt_mask/2
442                  Default: true
443

SEE ALSO

445       LCNT User's Guide
446
447
448
449Ericsson AB                      tools 3.1.0.1                         lcnt(3)
Impressum