Skip to content

Commit 136dc46

Browse files
authored
Enable fixes for memory leaks in bindings (#945)
This PR fixes a long-standing issue in the backend's binding code, which is that the call to `initStaticObjects()` when the Python module is _bound_ does not affect the process that actually runs the backend interpreter. A consequence of this is that GMP is never told to use our GC'ed memory allocators, and so any code using integer operations ends up leaking lots of memory when it runs for a long time. To fix Python code that uses the bindings: * Call `init_static_objects` on application startup * If an application _only_ does function evaluation or simplification, you may also want to call `free_all_gc_memory` occasionally as the backend will not do so autonomously unless a rewrite step is taken. Relevant: * #770 * #922 (has reproduction instructions)
1 parent 4ca71da commit 136dc46

File tree

2 files changed

+14
-3
lines changed

2 files changed

+14
-3
lines changed

bindings/python/runtime.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ PYBIND11_DECLARE_HOLDER_TYPE(T, raw_ptr<T>, true);
4040
*/
4141

4242
extern "C" {
43-
void initStaticObjects();
43+
void initStaticObjects(void);
44+
void freeAllKoreMem(void);
4445
block *take_steps(int64_t, block *);
4546
void *constructInitialConfiguration(const KOREPattern *initial);
4647
}
@@ -58,6 +59,9 @@ void bind_runtime(py::module_ &m) {
5859

5960
m.def("evaluate_function", bindings::evaluate_function);
6061

62+
m.def("init_static_objects", initStaticObjects);
63+
m.def("free_all_gc_memory", freeAllKoreMem);
64+
6165
// This class can't be used directly from Python; the mutability semantics
6266
// that we get from the Pybind wrappers make it really easy to break things.
6367
// We therefore have to wrap it up in some external Python code; see
@@ -97,7 +101,5 @@ void bind_runtime(py::module_ &m) {
97101
}
98102

99103
PYBIND11_MODULE(_kllvm_runtime, m) {
100-
initStaticObjects();
101-
102104
bind_runtime(m);
103105
}

test/python/test_steps.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ def test_steps_1(self):
4343
t.step(200)
4444
self.assertEqual(str(t), bar_output())
4545

46+
kllvm.runtime.free_all_gc_memory()
47+
4648
def test_steps_2(self):
4749
t = kllvm.runtime.Term(start_pattern())
4850

@@ -52,17 +54,24 @@ def test_steps_2(self):
5254
t.step(-1)
5355
self.assertEqual(str(t), bar_output())
5456

57+
kllvm.runtime.free_all_gc_memory()
58+
5559
def test_steps_3(self):
5660
t = kllvm.runtime.Term(start_pattern())
5761
t.run()
5862
self.assertEqual(str(t), bar_output())
5963

64+
kllvm.runtime.free_all_gc_memory()
65+
6066
def test_steps_to_pattern(self):
6167
t = kllvm.runtime.Term(start_pattern())
6268
t.run()
6369
pat = t.to_pattern()
6470
self.assertEqual(str(pat), bar_output())
6571

72+
kllvm.runtime.free_all_gc_memory()
73+
6674

6775
if __name__ == "__main__":
76+
kllvm.runtime.init_static_objects()
6877
unittest.main()

0 commit comments

Comments
 (0)