1lcnt(3) Erlang Module Definition lcnt(3)
2
3
4
6 lcnt - A runtime system Lock Profiling tool.
7
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
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
264 The following functions are used for convenience.
265
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
333 The following functions control the behavior of the internal counters.
334
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
445 LCNT User's Guide
446
447
448
449Ericsson AB tools 3.4.4 lcnt(3)