请教 Python 多线程内存不释放怎么排查

2020-10-06 23:51:58 +08:00
 r150r

新手写了一个多线程的爬虫,所有线程都执行完了,但是一直占着 1.5GB 的内存(任务数越多不释放的内存越多) 不知道怎么排查哪里出问题,pympler 看不太懂问题到底出在哪里,请教该如何正确的排查问题

执行多线程函数的代码:

    def mainfunc(tasknum, thread):
        tr = tracker.SummaryTracker()
        tr.print_diff()
        list = []
        for i in range(tasknum):
            list.append(str(i))
        pool = threadpool.ThreadPool(thread)
        requests = threadpool.makeRequests(childfunc, list)
        for req in requests:
            pool.putRequest(req)
        pool.wait()
        tr.print_diff()

tr.print_diff()打印的内容

初始化:

                     types |   # objects |   total size
========================== | =========== | ============
                      list |        3741 |    350.84 KB
                       str |        3739 |    260.01 KB
                       int |         673 |     18.40 KB
                      dict |           2 |    352     B
                     tuple |           4 |    256     B
                      code |           1 |    144     B
     function (store_info) |           1 |    136     B
                      cell |           2 |     96     B
  functools._lru_list_elem |           1 |     80     B
                    method |          -1 |    -64     B

所有线程结束后:

                                types |   # objects |   total size
===================================== | =========== | ============
                                 dict |      202860 |     43.69 MB
                                 list |      100169 |      8.47 MB
                                  str |      102446 |      5.62 MB
               threadpool.WorkRequest |      100000 |      5.34 MB
                                  int |      100836 |      3.08 MB
                   _io.BufferedReader |         294 |      2.35 MB
                                tuple |        1480 |     93.30 KB
                                 type |          76 |     85.98 KB
                                 code |         572 |     80.57 KB
                                bytes |        1219 |     51.49 KB
                                  set |          32 |     43.50 KB
                        socket.socket |         294 |     27.56 KB
       pymysql.connections.Connection |         294 |     16.08 KB
                      socket.SocketIO |         294 |     16.08 KB
  DBUtils.SteadyDB.SteadyDBConnection |         294 |     16.08 KB
6665 次点击
所在节点    Python
25 条回复
r150r
2020-10-07 15:06:12 +08:00
python 标记变量为垃圾而不释放有什么条件吗?
如果把代码里的 session.get 替换成 str = ' ' * (500 * 1024 * 1024),使用的内存会马上就归还给系统,是 requests 的问题吗
mywaiting
2020-10-07 17:06:07 +08:00
之前遇到过类似的问题,把 requests 的 timeout 调小一点吧 timeout=(5, 10) 试试
changePro
2020-10-08 22:18:26 +08:00
这个问题我今晚研究了下,Py 自己管理内存

```
str = ' ' * (500 * 1024 * 1024)
```

这段代码有可能是在栈上面的,用完了 frame 就没了,内存自然释放

但是

```
res = s.get(url, timeout=(5, 60))
```

有可能是在堆上面的,GC 回收的话,应该有内在策略,找时间可以分析分析内存布局
HappyTrail
2020-10-10 14:01:23 +08:00
https 改成 http 试试看 - -
nisonGe
2020-10-12 00:08:39 +08:00
个人猜测是因为有大量的异常导致,异常递归。task 越多,异常越多,内存占用也越多。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/712846

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX