DAL object leaks memory
See original GitHub issueI have an application that runs on CherryPy (v8.1.2) on Ubuntu (14.04.5 LTS) and python 2.7.6. I use standalone pyDAL (v16.09) to connect to my MySQL DB on AWS RDS. I’m seeing a constant memory leak on my servers which causes the process to use up 100% of RAM in a few hours and eventual die a painful death (no SWAP enabled; enabling SWAP pushes back certain death a little).
I have managed to reproduce the leak with a very small loop that repeatedly opens and closes the DAL object. I confirmed that memory continues to grow using htop and will eventually end up using 100% of RAM. I thought it was an MySQL adapter specific problem but I was able to repro it with the default sqlite adapter as well.
from pydal import DAL
def open_close_dal():
sql = DAL()
sql.close()
if __name__ == '__main__':
while True:
open_close_dal()
I read some really old threads on this issue that suggested calling sql._adapter.close()
or sql._adapter.close_all_instances()
or del sql
but it doesn’t seem to make a difference. I’ve tried tracking down the memory leak and managed to confirm that it is the guts of the DAL that are leaking. One iteration of the loop, with pympler.tracker enabled reports these objects created:
types | # objects | total size
============================================ | =========== | ============
dict | 672 | 423.38 KB
list | 3525 | 354.35 KB
str | 2851 | 162.49 KB
<class 'collections.OrderedDict | 129 | 135.02 KB
code | 585 | 73.12 KB
<class 'pydal.dialects.MetaDialect | 32 | 28.25 KB
<class 'pydal.parsers.MetaParser | 17 | 15.01 KB
type | 16 | 14.12 KB
<class 'pydal.representers.MetaRepresenter | 16 | 14.12 KB
tuple | 168 | 12.85 KB
<class 'pydal.dialects.sqltype_for | 178 | 11.12 KB
weakref | 89 | 7.65 KB
int | 258 | 6.05 KB
<class 'pydal.representers.for_type | 49 | 3.06 KB
function (wrap) | 25 | 2.93 KB
Issue Analytics
- State:
- Created 7 years ago
- Comments:12 (7 by maintainers)
Top GitHub Comments
@toorsukhmeet ok found the leak.
@mdipierro this is because every
DAL
instance create data intoTHREAD_LOCAL
variable and never remove the contents.I’ve tested this:
with some profiling on the memory usage:
and is quite obvious the
THREAD_LOCAL
is increasing due to connections:So this is happening on web2py because it creates a DAL instance per-request. On weppy the DAL instance is the same across the processes and is initialized when the server start, this is why I missed the leak.
The proposal is to edit the
DAL.close
method to add some cleaning of the connection data on theTHREAD_LOCAL
object:@mdipierro what do you think?
@toorsukhmeet Will inspect this during the weekend