You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/basics/syscmds.md
+76-30Lines changed: 76 additions & 30 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -315,41 +315,41 @@ q){x where x like"ht??"}system"f .h"
315
315
## `\g` (garbage collection mode)
316
316
317
317
```syntax
318
-
\g mode
318
+
\g / current garbage-collection mode
319
+
\g mode / set garbage-collection mode
319
320
```
320
321
321
-
Show or set garbage-collection mode.
322
-
The default mode is 0.
322
+
Show or set garbage-collection mode. The default mode is 0 (deferred). Setting the garbage-collection mode will automatically call [`.Q.gc[]`](../ref/dotq.md#gc-garbage-collect) after setting the provided value.
323
+
324
+
Q manages its own thread-local heap. Objects in q use reference counting. As soon as there are no references to an object, its memory is eligable to be returned to the heap.
323
325
324
326
0 (deferred)
325
327
326
-
: returns memory to the OS when either `.Q.gc[]` is called or an allocation fails, hence has a performance advantage, but can be more difficult to dimension or manage memory requirements.
328
+
: Returns memory to the thread-local heap. Will subsequently return memory to the OS when either `.Q.gc[]` is called or an allocation fails, hence has a performance advantage, but can be more difficult to dimension or manage memory requirements.
327
329
328
330
1 (immediate)
329
331
330
-
: returns (certain types of) memory to the OS as soon as no longer referenced; has an associated performance overhead.
331
-
332
-
Q manages its own thread-local heap.
333
-
334
-
Vectors always have a capacity and a used size (the count).
335
-
336
-
There is no garbage since q uses reference counting. As soon as there are no references to an object, its memory is returned to the heap.
337
-
338
-
During that return of memory, q checks if the capacity of the object is ≥64MB. If it is and `\g` is 1, the memory is returned immediately to the OS; otherwise, the memory is returned to the thread-local heap for reuse.
339
-
340
-
Executing [`.Q.gc[]`](../ref/dotq.md#qgc-garbage-collect) additionally attempts to coalesce pieces of the heap into their original allocation units and returns any units ≥64MB to the OS.
341
-
342
-
Since V3.3 2015.08.23 (Linux only) unused pages in the heap are dropped from RSS during `.Q.gc[]`.
332
+
: As memory is returned to the thread-local heap, if the object is ≥64MB then the memory is returned to the OS instead. This has an associated performance overhead. As per `defered mode`, memory used by the heap may be subsequently returned to the OS when either `.Q.gc[]` is called or an allocation fails.
343
333
344
334
When q is denied additional address space from the OS, it invokes `.Q.gc[]` and retries the request to the OS.
345
335
If the subsequent attempt fail, the request exits with [`'wsfull`](../basics/errors.md#wsfull).
346
336
347
-
When secondary threads are configured and `.Q.gc[]` is invoked in the main thread, `.Q.gc[]` is automatically invoked in each secondary thread.
348
-
If the call is instigated in a secondary thread, it affects that thread’s local heap only.
349
-
350
337
!!! detail "Notes on the allocator"
351
338
352
339
Q’s allocator bins objects in power-of-two size categories, from 16b (e.g. an atom) to 64MB.
340
+
341
+
In this example, various vectors of longs (8 bytes per long) are created of different sizes using [`til`](../ref/til.md).
342
+
The memory used for the operation is shown via [`\ts`](#ts-time-and-space). Note that more bytes are reported
343
+
that only the pure vector size due to other house keeping, for example the type information.
344
+
```q
345
+
q)\ts til 800 / 800*8=6400, needs a 2^13=8192 byte slab (too big for a 2^12=4096 byte slab)
346
+
0 8368
347
+
q)\ts til 1000 / 1000*8=8000, needs a 2^13=8192 byte slab (memory same as smaller vector above)
348
+
0 8368
349
+
q)\ts til 1200 / 1200*8=9600, cant fit in a 2^13=8192 bytes slab, needs 2^14=16384 byte slab
350
+
0 16560
351
+
```
352
+
353
353
If there is already a slab in the object category’s freelist, it is reused.
354
354
If there are no available slabs, a larger slab is recursively split in two until the needed category size is reached.
355
355
If there are no free slabs available, a new 64MB slab is requested from the system.
@@ -365,15 +365,61 @@ If the call is instigated in a secondary thread, it affects that thread’s loca
365
365
366
366
split slab
367
367
368
-
: Suppose that at some point q needed a 32MB allocation. It requested a new 64MB slab from the OS, split it in half, used and freed the object, and returned the two 32MB slabs to the freelist. Now if q needs to allocate 64MB, it will have to make another request to the OS. running `.Q.gc` would attempt to coalesce these two 32MB slabs together back into one 64MB, which would allow it to be returned to the OS (or reused for larger allocations, if the resulting slab is <64MB).
368
+
: Suppose that at some point q needed a 32MB allocation. It requested a new 64MB slab from the OS, split it in half, used and freed the object, and returned the two 32MB slabs to the freelist. Now if q needs to allocate 64MB, it will have to make another request to the OS. When `.Q.gc` is called (or an allocation fails), it would attempt to coalesce these two 32MB slabs together back into one 64MB, which would allow it to be returned to the OS (or reused for larger allocations, if the resulting slab is <64MB).
369
369
370
370
leftover objects
371
371
372
-
: If most of the objects allocated from a 64MB slab are freed but one remains, the slab still cannot be returned to the OS (or coalesced). In this case, `.Q.gc` notifies the OS that the physical memory backing the unused pages in the block can be reclaimed.
372
+
: If most of the objects allocated from a 64MB slab are freed but one remains, the slab still cannot be returned to the OS (or coalesced).
373
373
374
+
The following example shows freeing an object ≥64MB in `deferred` mode, while inspecting memory usage via [`.Q.w[]`](../ref/dotq.md##w-memory-stats):
375
+
```q
376
+
q).Q.w[]`used`heap / original memory used and memory reserved by kdb+ at time of test
377
+
371552 67108864
378
+
q)a:til 10000000 / need memory ≥64MB to store value
379
+
q).Q.w[]`used`heap / heap (memory reserved by kdb+) has grown, and used memory grown from the heap has grown
380
+
134589328 201326592
381
+
q)a:1 / variable assigned different value, old value no longer used
382
+
q).Q.w[]`used`heap / heap (memory reserved by kdb+) hasn't reduced as it is kept for future use, used memory has reduced
383
+
371616 201326592
384
+
q)a:til 10000000 / need memory ≥64MB to store value again
385
+
q).Q.w[]`used`heap / heap memory (no increase) as memory used has been taken from the available heap
386
+
134589328 201326592
387
+
```
388
+
The same example will differ when using `immediate` mode, by returning memory to the OS (as the object free'd is greater than 64MB):
389
+
```q
390
+
q).Q.w[]`used`heap / original memory used and memory reserved by kdb+ at time of test
391
+
371648 67108864
392
+
q)a:til 10000000 / need memory ≥64MB to store value
393
+
q).Q.w[]`used`heap / heap (memory reserved by kdb+) has grown, and used memory from the heap has grown
394
+
134589424 201326592
395
+
q)a:1 / variable assigned different value, old value no longer used
396
+
q).Q.w[]`used`heap / heap (memory reserved by kdb+) has reduced, it has been returned to OS
397
+
371712 67108864
398
+
q)a:til 10000000 / need memory ≥64MB to store value again
399
+
q).Q.w[]`used`heap / heap memory has increased (requested from OS) as memory used is more than whats available to use in heap
400
+
134589328 201326592
401
+
```
402
+
`Immediate mode` will not return the memory to the OS when several objects less than 64MB each are freed, even though their sum may be more than 64MB.
403
+
In this situation, `immediate` and `deferred` mode operate identically by adding the freed memory to the heap for future use.
404
+
405
+
The following examples shows this effect when running in `immediate mode`.
406
+
No memory is returned to the OS on freeing the objects, and only when [`.Q.gc[]`](../ref/dotq.md#gc-garbage-collect) is run is the memory coalesced and freed.
407
+
```q
408
+
q).Q.w[]`used`heap / original memory used and memory reserved by kdb+ at time of test
409
+
371648 67108864
410
+
q)v:`a`b`c`d`e`f`g`h`i`j / create a list of 10 variable names to use
411
+
q){set[x;til 1000000]} each v / create a global variable using each of the names in v, each containing 1000000 longs
412
+
q).Q.w[]`used`heap / heap (memory reserved by kdb+) has grown, and used memory from the heap has grown
413
+
84258096 134217728
414
+
q)![`.;();0b;v] / delete all the variables and their contents
415
+
q).Q.w[]`used`heap / used memory has been reduced, but none of the heap memory has returned to the OS
416
+
371824 134217728
417
+
q).Q.gc[] / running garbage collection freed over 64MB
q).Q.gc[] / garbage collection has found no contiguous unused memory of ≥64MB to free
1007
+
0
1008
+
q)v:-8!v / convert v into its serialised form, return vector used by v to heap
1009
+
q).Q.gc[] / garbage collection now found unused contiguous memory slab ≥64MB to return to OS
1010
+
16374562816
1011
+
q)v:-9!v / convert serialised form of v back to its original state
1012
+
q).Q.w[] / used memory remains the same as before, but heap has reduced
1013
+
used| 40760016
1014
+
heap| 134217728
1015
+
peak| 16508780544
1000
1016
wmax| 0
1001
1017
mmap| 0
1002
-
mphy| 270538350592
1003
-
syms| 570
1004
-
symw| 24964
1018
+
mphy| 17179869184
1019
+
syms| 690
1020
+
symw| 37436
1005
1021
```
1006
1022
1007
-
So if you have many nested data, e.g. columns of char vectors, or much grouping, you may be fragmenting memory quite heavily.
1023
+
If you have nested data, e.g. columns of char vectors, or much grouping, you may be fragmenting memory.
1024
+
1025
+
Since V3.3 2015.08.23 (Linux only) unused pages in the heap are dropped from RSS during `.Q.gc[]`.
1008
1026
1009
1027
Since 4.1t 2022.07.01, `.Q.gc[0]` can be used to perform a subset of operations performed by `.Q.gc[]` (i.e. only return unused blocks >= 64MB to os).
1010
1028
This has the advantage of running return faster than `.Q.gc[]`, but with the disadvantage of not defragmenting unused memory blocks of a smaller size (therefore may not free as much unused memory).
@@ -2118,7 +2138,7 @@ q)@[get;"select from tt";-2@]; / no error
2118
2138
.Q.w[]
2119
2139
```
2120
2140
2121
-
Returns the memory stats from [`\w`](../basics/syscmds.md#w-workspace) into a more readable dictionary.
2141
+
Returns the memory stats from [`\w`](../basics/syscmds.md#w-workspace) into a more readable dictionary. Refer to [`\w`](../basics/syscmds.md#w-workspace) for an explaination of each statistic.
0 commit comments