|
16 | 16 |
|
17 | 17 |
|
18 | 18 | /* Special free list |
19 | | -
|
20 | | - Since some Python programs can spend much of their time allocating |
21 | | - and deallocating floats, these operations should be very fast. |
22 | | - Therefore we use a dedicated allocation scheme with a much lower |
23 | | - overhead (in space and time) than straight malloc(): a simple |
24 | | - dedicated free list, filled when necessary with memory from malloc(). |
25 | | -
|
26 | | - block_list is a singly-linked list of all PyFloatBlocks ever allocated, |
27 | | - linked via their next members. PyFloatBlocks are never returned to the |
28 | | - system before shutdown (PyFloat_Fini). |
29 | | -
|
30 | 19 | free_list is a singly-linked list of available PyFloatObjects, linked |
31 | 20 | via abuse of their ob_type members. |
32 | 21 | */ |
33 | 22 |
|
34 | | -#define BLOCK_SIZE 1000 /* 1K less typical malloc overhead */ |
35 | | -#define BHEAD_SIZE 8 /* Enough for a 64-bit pointer */ |
36 | | -#define N_FLOATOBJECTS ((BLOCK_SIZE - BHEAD_SIZE) / sizeof(PyFloatObject)) |
37 | | - |
38 | | -struct _floatblock { |
39 | | - struct _floatblock *next; |
40 | | - PyFloatObject objects[N_FLOATOBJECTS]; |
41 | | -}; |
42 | | - |
43 | | -typedef struct _floatblock PyFloatBlock; |
44 | | - |
45 | | -static PyFloatBlock *block_list = NULL; |
| 23 | +#ifndef PyFloat_MAXFREELIST |
| 24 | +#define PyFloat_MAXFREELIST 100 |
| 25 | +#endif |
| 26 | +static int numfree = 0; |
46 | 27 | static PyFloatObject *free_list = NULL; |
47 | 28 |
|
48 | | -static PyFloatObject * |
49 | | -fill_free_list(void) |
50 | | -{ |
51 | | - PyFloatObject *p, *q; |
52 | | - /* XXX Float blocks escape the object heap. Use PyObject_MALLOC ??? */ |
53 | | - p = (PyFloatObject *) PyMem_MALLOC(sizeof(PyFloatBlock)); |
54 | | - if (p == NULL) |
55 | | - return (PyFloatObject *) PyErr_NoMemory(); |
56 | | - ((PyFloatBlock *)p)->next = block_list; |
57 | | - block_list = (PyFloatBlock *)p; |
58 | | - p = &((PyFloatBlock *)p)->objects[0]; |
59 | | - q = p + N_FLOATOBJECTS; |
60 | | - while (--q > p) |
61 | | - Py_TYPE(q) = (struct _typeobject *)(q-1); |
62 | | - Py_TYPE(q) = NULL; |
63 | | - return p + N_FLOATOBJECTS - 1; |
64 | | -} |
65 | | - |
66 | 29 | double |
67 | 30 | PyFloat_GetMax(void) |
68 | 31 | { |
@@ -151,14 +114,16 @@ PyFloat_GetInfo(void) |
151 | 114 | PyObject * |
152 | 115 | PyFloat_FromDouble(double fval) |
153 | 116 | { |
154 | | - register PyFloatObject *op; |
155 | | - if (free_list == NULL) { |
156 | | - if ((free_list = fill_free_list()) == NULL) |
157 | | - return NULL; |
| 117 | + register PyFloatObject *op = free_list; |
| 118 | + if (op != NULL) { |
| 119 | + free_list = (PyFloatObject *) Py_TYPE(op); |
| 120 | + numfree--; |
| 121 | + } else { |
| 122 | + op = (PyFloatObject*) PyObject_MALLOC(sizeof(PyFloatObject)); |
| 123 | + if (!op) |
| 124 | + return PyErr_NoMemory(); |
158 | 125 | } |
159 | 126 | /* Inline PyObject_New */ |
160 | | - op = free_list; |
161 | | - free_list = (PyFloatObject *)Py_TYPE(op); |
162 | 127 | PyObject_INIT(op, &PyFloat_Type); |
163 | 128 | op->ob_fval = fval; |
164 | 129 | return (PyObject *) op; |
@@ -217,6 +182,11 @@ static void |
217 | 182 | float_dealloc(PyFloatObject *op) |
218 | 183 | { |
219 | 184 | if (PyFloat_CheckExact(op)) { |
| 185 | + if (numfree >= PyFloat_MAXFREELIST) { |
| 186 | + PyObject_FREE(op); |
| 187 | + return; |
| 188 | + } |
| 189 | + numfree++; |
220 | 190 | Py_TYPE(op) = (struct _typeobject *)free_list; |
221 | 191 | free_list = op; |
222 | 192 | } |
@@ -1932,96 +1902,22 @@ _PyFloat_Init(void) |
1932 | 1902 | int |
1933 | 1903 | PyFloat_ClearFreeList(void) |
1934 | 1904 | { |
1935 | | - PyFloatObject *p; |
1936 | | - PyFloatBlock *list, *next; |
1937 | | - int i; |
1938 | | - int u; /* remaining unfreed floats per block */ |
1939 | | - int freelist_size = 0; |
1940 | | - |
1941 | | - list = block_list; |
1942 | | - block_list = NULL; |
1943 | | - free_list = NULL; |
1944 | | - while (list != NULL) { |
1945 | | - u = 0; |
1946 | | - for (i = 0, p = &list->objects[0]; |
1947 | | - i < N_FLOATOBJECTS; |
1948 | | - i++, p++) { |
1949 | | - if (PyFloat_CheckExact(p) && Py_REFCNT(p) != 0) |
1950 | | - u++; |
1951 | | - } |
1952 | | - next = list->next; |
1953 | | - if (u) { |
1954 | | - list->next = block_list; |
1955 | | - block_list = list; |
1956 | | - for (i = 0, p = &list->objects[0]; |
1957 | | - i < N_FLOATOBJECTS; |
1958 | | - i++, p++) { |
1959 | | - if (!PyFloat_CheckExact(p) || |
1960 | | - Py_REFCNT(p) == 0) { |
1961 | | - Py_TYPE(p) = (struct _typeobject *) |
1962 | | - free_list; |
1963 | | - free_list = p; |
1964 | | - } |
1965 | | - } |
1966 | | - } |
1967 | | - else { |
1968 | | - PyMem_FREE(list); |
1969 | | - } |
1970 | | - freelist_size += u; |
1971 | | - list = next; |
| 1905 | + PyFloatObject *f = free_list, *next; |
| 1906 | + int i = numfree; |
| 1907 | + while (f) { |
| 1908 | + next = (PyFloatObject*) Py_TYPE(f); |
| 1909 | + PyObject_FREE(f); |
| 1910 | + f = next; |
1972 | 1911 | } |
1973 | | - return freelist_size; |
| 1912 | + free_list = NULL; |
| 1913 | + numfree = 0; |
| 1914 | + return i; |
1974 | 1915 | } |
1975 | 1916 |
|
1976 | 1917 | void |
1977 | 1918 | PyFloat_Fini(void) |
1978 | 1919 | { |
1979 | | - PyFloatObject *p; |
1980 | | - PyFloatBlock *list; |
1981 | | - int i; |
1982 | | - int u; /* total unfreed floats per block */ |
1983 | | - |
1984 | | - u = PyFloat_ClearFreeList(); |
1985 | | - |
1986 | | - if (!Py_VerboseFlag) |
1987 | | - return; |
1988 | | - fprintf(stderr, "# cleanup floats"); |
1989 | | - if (!u) { |
1990 | | - fprintf(stderr, "\n"); |
1991 | | - } |
1992 | | - else { |
1993 | | - fprintf(stderr, |
1994 | | - ": %d unfreed float%s\n", |
1995 | | - u, u == 1 ? "" : "s"); |
1996 | | - } |
1997 | | - if (Py_VerboseFlag > 1) { |
1998 | | - list = block_list; |
1999 | | - while (list != NULL) { |
2000 | | - for (i = 0, p = &list->objects[0]; |
2001 | | - i < N_FLOATOBJECTS; |
2002 | | - i++, p++) { |
2003 | | - if (PyFloat_CheckExact(p) && |
2004 | | - Py_REFCNT(p) != 0) { |
2005 | | - char *buf = PyOS_double_to_string( |
2006 | | - PyFloat_AS_DOUBLE(p), 'r', |
2007 | | - 0, 0, NULL); |
2008 | | - if (buf) { |
2009 | | - /* XXX(twouters) cast |
2010 | | - refcount to long |
2011 | | - until %zd is |
2012 | | - universally |
2013 | | - available |
2014 | | - */ |
2015 | | - fprintf(stderr, |
2016 | | - "# <float at %p, refcnt=%ld, val=%s>\n", |
2017 | | - p, (long)Py_REFCNT(p), buf); |
2018 | | - PyMem_Free(buf); |
2019 | | - } |
2020 | | - } |
2021 | | - } |
2022 | | - list = list->next; |
2023 | | - } |
2024 | | - } |
| 1920 | + (void)PyFloat_ClearFreeList(); |
2025 | 1921 | } |
2026 | 1922 |
|
2027 | 1923 | /*---------------------------------------------------------------------------- |
|
0 commit comments