Unitech / pm2

Node.js Production Process Manager with a built-in Load Balancer.
https://pm2.keymetrics.io/docs/usage/quick-start/
Other
41.59k stars 2.62k forks source link

Python threading causes memory leak in pm2 #4852

Open BarryThrill opened 4 years ago

BarryThrill commented 4 years ago

What's going wrong?

I have done some test and realized that when using threading with pm2 it causes memory leaks where it stacks up the threading instead of dumping them. I have tested both with pm2 vs normal terminal. When using threading I could see that using normal terminal would take around 60mb~ usage. While using PM2 could stack up to be over 160MB~ with the same exact code.

What I do is that when the threading is done with its task, it should be killed with a return/or sys.exit()

How could we reproduce this issue?

This is a example I have done, I'm not sure if this could replicate it but same code should give two different RAM usage even thought its the same exact code.

EDIT:

After testing on Windows. The issue still remains. I can see that it takes around 11MB~ with PM2 while with terminal/cmd it takes around 4.5MB.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import random
import threading
import time

class Monitoring(object):

    def parseNew(self):

        ListsNumber = []

        while True:

            newtLists = random.sample(range(1, 1000), 999)

            for numbers in newtLists:
                if numbers not in ListsNumber:
                    ListsNumber.append(numbers)

                    threading.Thread(
                        target=self.threadingTest,
                        args=(numbers,)
                    ).start()
            else:
                print("sleeping")
                time.sleep(random.randint(2, 4))

    def threadingTest(self, numbers):
        print(numbers)
        return

if __name__ == '__main__':
    Monitoring().parseNew()

Supporting information

Python 3.8.2, Ubuntu 20.04.1 LTS

--- PM2 report ----------------------------------------------------------------
Date                 : Fri Sep 11 2020 15:45:24 GMT+0200 (Central European Summe                                                                                                                                                             r Time)
===============================================================================
--- Daemon -------------------------------------------------
pm2d version         : 4.4.0
node version         : 14.6.0
node path            : /usr/bin/pm2
argv                 : /usr/bin/node,/usr/lib/node_modules/pm2/lib/Daemon.js
argv0                : node
user                 : autosnkr
uid                  : 1000
gid                  : 1000
uptime               : 50586min
===============================================================================
--- CLI ----------------------------------------------------
local pm2            : 4.4.0
node version         : 14.6.0
node path            : /usr/bin/pm2
argv                 : /usr/bin/node,/usr/bin/pm2,report
argv0                : node
user                 : autosnkr
uid                  : 1000
gid                  : 1000
===============================================================================
--- System info --------------------------------------------
arch                 : x64
platform             : linux
type                 : Linux
cpus                 : Intel(R) Core(TM) i7-8700T CPU @ 2.40GHz
cpus nb              : 12
freemem              : 1734098944
totalmem             : 16617046016
home                 : /home/autosnkr
===============================================================================
BarryThrill commented 4 years ago

I have posted a thread about it on Stackoverflow. It got 6 upvotes and still waiting. https://stackoverflow.com/questions/63848510/python-threading-causes-memory-leak-using-pm2

Unitech commented 4 years ago

There is 0 code orchestration for Python application, basically it's just a spawn: https://github.com/Unitech/pm2/blob/master/lib/God/ForkMode.js#L118 with stdIO configured like stdio : ['pipe', 'pipe', 'pipe', 'ipc']

So I don't see how PM2 could create a leak in your app

BarryThrill commented 4 years ago

There is 0 code orchestration for Python application, basically it's just a spawn: https://github.com/Unitech/pm2/blob/master/lib/God/ForkMode.js#L118 with stdIO configured like stdio : ['pipe', 'pipe', 'pipe', 'ipc']

So I don't see how PM2 could create a leak in your app

Hello @Unitech - I am not sure why the reason aswell but when running the script - Everytime I create a thread it adds additional RAM and after "killing/exiting" the thread. I believe that the thread somehow gets stuck instead of cleaning/garbage collection?

In the test I have provided before. When using PM2 it collects around 11MB Memory usage while without PM2 it stays at 4 MB. Meaning if we add more numbers in the test script then the PM2 memory will get increased by much more compare to without the PM2.

Also please, if there is anything more I can help you out with information you need. Let me know and I will try my best to give you all information I can get off. :)

BarryThrill commented 4 years ago

@Unitech I have created a small script for you aswell. Here you should see over time that pm2 gets decreased RAM usage compare to without PM2:

import gc
import sys
import threading
import time

import requests
from bs4 import BeautifulSoup

class pageThread(threading.Thread):
    def run(self):
        res = requests.get(
            "https://www.google.com/search?q=among+us&sxsrf=ALeKk03FrFRxu_Wr0bGr-w-w3UflnN30HQ:1601298873486&source=lnms&tbm=isch&sa=X&ved=2ahUKEwiSx6GU94vsAhXhkosKHXbGAK0Q_AUoAXoECBgQAw&biw=958&bih=927")
        if res.status_code == 200:
            print("Successful request")
            page = BeautifulSoup(res.text, "lxml")
            time.sleep(2)
        res.close()
        sys.exit()

def load():
    threading.Thread(
        target=pageThread().run,
    ).start()

while True:
    load()
    time.sleep(.1)

Left is without pm2 and right is pm2 :) image

and as I mentioned, the pm2 keep decreasing with RAM usage while the left one is stable at 55-57MB

wolph commented 2 years ago

I can verify the issue... pm2 is unusable like this: telegram-cloud-photo-size-4-5962858429280270386-y

BarryThrill commented 2 years ago

@Unitech I have created a small script for you aswell. Here you should see over time that pm2 gets decreased RAM usage compare to without PM2:

import gc
import sys
import threading
import time

import requests
from bs4 import BeautifulSoup

class pageThread(threading.Thread):
    def run(self):
        res = requests.get(
            "https://www.google.com/search?q=among+us&sxsrf=ALeKk03FrFRxu_Wr0bGr-w-w3UflnN30HQ:1601298873486&source=lnms&tbm=isch&sa=X&ved=2ahUKEwiSx6GU94vsAhXhkosKHXbGAK0Q_AUoAXoECBgQAw&biw=958&bih=927")
        if res.status_code == 200:
            print("Successful request")
            page = BeautifulSoup(res.text, "lxml")
            time.sleep(2)
        res.close()
        sys.exit()

def load():
    threading.Thread(
        target=pageThread().run,
    ).start()

while True:
    load()
    time.sleep(.1)

Left is without pm2 and right is pm2 :) image

and as I mentioned, the pm2 keep decreasing with RAM usage while the left one is stable at 55-57MB

@Unitech

MarcusWidle commented 2 years ago

Any update? @Unitech The thread is over 2 years old

cryptoIRAfinance commented 10 months ago

How about now? it's been over 3 years. Any update?