blob: 471cdf45df276681e517433f0f3412b44ebabd59 [file] [log] [blame]
Eric Snow2ebc5ce2017-09-07 23:51:28 -06001#ifndef Py_INTERNAL_MEM_H
2#define Py_INTERNAL_MEM_H
3#ifdef __cplusplus
4extern "C" {
5#endif
6
7#include "objimpl.h"
8#include "pymem.h"
9
10#ifdef WITH_PYMALLOC
11#include "internal/pymalloc.h"
12#endif
13
14/* Low-level memory runtime state */
15
16struct _pymem_runtime_state {
17 struct _allocator_runtime_state {
18 PyMemAllocatorEx mem;
19 PyMemAllocatorEx obj;
20 PyMemAllocatorEx raw;
21 } allocators;
22#ifdef WITH_PYMALLOC
23 /* Array of objects used to track chunks of memory (arenas). */
24 struct arena_object* arenas;
25 /* The head of the singly-linked, NULL-terminated list of available
26 arena_objects. */
27 struct arena_object* unused_arena_objects;
28 /* The head of the doubly-linked, NULL-terminated at each end,
29 list of arena_objects associated with arenas that have pools
30 available. */
31 struct arena_object* usable_arenas;
32 /* Number of slots currently allocated in the `arenas` vector. */
33 unsigned int maxarenas;
34 /* Number of arenas allocated that haven't been free()'d. */
35 size_t narenas_currently_allocated;
36 /* High water mark (max value ever seen) for
37 * narenas_currently_allocated. */
38 size_t narenas_highwater;
39 /* Total number of times malloc() called to allocate an arena. */
40 size_t ntimes_arena_allocated;
41 poolp usedpools[MAX_POOLS];
42 Py_ssize_t num_allocated_blocks;
Eric Snow2ebc5ce2017-09-07 23:51:28 -060043#endif /* WITH_PYMALLOC */
Eric Snowba6d5d12017-09-11 17:02:24 -070044 size_t serialno; /* incremented on each debug {m,re}alloc */
Eric Snow2ebc5ce2017-09-07 23:51:28 -060045};
46
47PyAPI_FUNC(void) _PyMem_Initialize(struct _pymem_runtime_state *);
48
49
50/* High-level memory runtime state */
51
52struct _pyobj_runtime_state {
53 PyObjectArenaAllocator allocator_arenas;
54};
55
56PyAPI_FUNC(void) _PyObject_Initialize(struct _pyobj_runtime_state *);
57
58
59/* GC runtime state */
60
61/* If we change this, we need to change the default value in the
62 signature of gc.collect. */
63#define NUM_GENERATIONS 3
64
65/*
66 NOTE: about the counting of long-lived objects.
67
68 To limit the cost of garbage collection, there are two strategies;
69 - make each collection faster, e.g. by scanning fewer objects
70 - do less collections
71 This heuristic is about the latter strategy.
72
73 In addition to the various configurable thresholds, we only trigger a
74 full collection if the ratio
75 long_lived_pending / long_lived_total
76 is above a given value (hardwired to 25%).
77
78 The reason is that, while "non-full" collections (i.e., collections of
79 the young and middle generations) will always examine roughly the same
80 number of objects -- determined by the aforementioned thresholds --,
81 the cost of a full collection is proportional to the total number of
82 long-lived objects, which is virtually unbounded.
83
84 Indeed, it has been remarked that doing a full collection every
85 <constant number> of object creations entails a dramatic performance
86 degradation in workloads which consist in creating and storing lots of
87 long-lived objects (e.g. building a large list of GC-tracked objects would
88 show quadratic performance, instead of linear as expected: see issue #4074).
89
90 Using the above ratio, instead, yields amortized linear performance in
91 the total number of objects (the effect of which can be summarized
92 thusly: "each full garbage collection is more and more costly as the
93 number of objects grows, but we do fewer and fewer of them").
94
95 This heuristic was suggested by Martin von Löwis on python-dev in
96 June 2008. His original analysis and proposal can be found at:
97 http://mail.python.org/pipermail/python-dev/2008-June/080579.html
98*/
99
100/*
101 NOTE: about untracking of mutable objects.
102
103 Certain types of container cannot participate in a reference cycle, and
104 so do not need to be tracked by the garbage collector. Untracking these
105 objects reduces the cost of garbage collections. However, determining
106 which objects may be untracked is not free, and the costs must be
107 weighed against the benefits for garbage collection.
108
109 There are two possible strategies for when to untrack a container:
110
111 i) When the container is created.
112 ii) When the container is examined by the garbage collector.
113
114 Tuples containing only immutable objects (integers, strings etc, and
115 recursively, tuples of immutable objects) do not need to be tracked.
116 The interpreter creates a large number of tuples, many of which will
117 not survive until garbage collection. It is therefore not worthwhile
118 to untrack eligible tuples at creation time.
119
120 Instead, all tuples except the empty tuple are tracked when created.
121 During garbage collection it is determined whether any surviving tuples
122 can be untracked. A tuple can be untracked if all of its contents are
123 already not tracked. Tuples are examined for untracking in all garbage
124 collection cycles. It may take more than one cycle to untrack a tuple.
125
126 Dictionaries containing only immutable objects also do not need to be
127 tracked. Dictionaries are untracked when created. If a tracked item is
128 inserted into a dictionary (either as a key or value), the dictionary
129 becomes tracked. During a full garbage collection (all generations),
130 the collector will untrack any dictionaries whose contents are not
131 tracked.
132
133 The module provides the python function is_tracked(obj), which returns
134 the CURRENT tracking status of the object. Subsequent garbage
135 collections may change the tracking status of the object.
136
137 Untracking of certain containers was introduced in issue #4688, and
138 the algorithm was refined in response to issue #14775.
139*/
140
141struct gc_generation {
142 PyGC_Head head;
143 int threshold; /* collection threshold */
144 int count; /* count of allocations or collections of younger
145 generations */
146};
147
148/* Running stats per generation */
149struct gc_generation_stats {
150 /* total number of collections */
151 Py_ssize_t collections;
152 /* total number of collected objects */
153 Py_ssize_t collected;
154 /* total number of uncollectable objects (put into gc.garbage) */
155 Py_ssize_t uncollectable;
156};
157
158struct _gc_runtime_state {
159 /* List of objects that still need to be cleaned up, singly linked
160 * via their gc headers' gc_prev pointers. */
161 PyObject *trash_delete_later;
162 /* Current call-stack depth of tp_dealloc calls. */
163 int trash_delete_nesting;
164
165 int enabled;
166 int debug;
167 /* linked lists of container objects */
168 struct gc_generation generations[NUM_GENERATIONS];
169 PyGC_Head *generation0;
brainfvckc75edab2017-10-16 12:49:41 -0700170 /* a permanent generation which won't be collected */
171 struct gc_generation permanent_generation;
Eric Snow2ebc5ce2017-09-07 23:51:28 -0600172 struct gc_generation_stats generation_stats[NUM_GENERATIONS];
173 /* true if we are currently running the collector */
174 int collecting;
175 /* list of uncollectable objects */
176 PyObject *garbage;
177 /* a list of callbacks to be invoked when collection is performed */
178 PyObject *callbacks;
179 /* This is the number of objects that survived the last full
180 collection. It approximates the number of long lived objects
181 tracked by the GC.
182
183 (by "full collection", we mean a collection of the oldest
184 generation). */
185 Py_ssize_t long_lived_total;
186 /* This is the number of objects that survived all "non-full"
187 collections, and are awaiting to undergo a full collection for
188 the first time. */
189 Py_ssize_t long_lived_pending;
190};
191
192PyAPI_FUNC(void) _PyGC_Initialize(struct _gc_runtime_state *);
193
194#define _PyGC_generation0 _PyRuntime.gc.generation0
195
196#ifdef __cplusplus
197}
198#endif
199#endif /* !Py_INTERNAL_MEM_H */