4 ms·
When we first started playing with this we produced memory and reference leaks left and right, mostly through undisciplined access to reference counts or failur
by nickelpro 3y ago
When we first started playing with this we produced memory and reference leaks left and right, mostly through undisciplined access to reference counts or failures to reference count at all. The basic problems the GIL solves don't go away, you need to have a principled approach to managing reference counts for both the Balm'd objects and the underlying data.
A good rule of thumb we came up with is "reference counts are only allowed to be manipulated when holding the GIL." So if you create 500 string views that all reference some underlying data, the reference count for that underlying data should only be incremented by 500 once you acquire the GIL again to introduce the data to Python.
If you try to do granular per-refcount locking, you'll run into the problem in the multi-threading benchmark. You start to incur a lot of lock contention on certain workloads, or even in the best case you have a little overhead for zero gain. Making the reference counts atomic was a catastrophic performance hit.
Related: It's common to choose to free the underlying resources of the balm'd object even though the Python interpreter might have stashed a reference to it somewhere. For example in a webserver, after the request has been served free'ing/re-using the associated header buffers.
We call these "degenerate" applications, because it is not reasonable to hold onto such a reference. Sometimes the best thing is to document you don't support that use-case in the name of performance. Sometimes you might want to be nice and throw a description Python exception.