iicsys / pypmu

pyPMU - Python implementation of the IEEE C37.118 synchrophasor standard
BSD 3-Clause "New" or "Revised" License
60 stars 46 forks source link

Memory Leak #21

Open Marcello-debug opened 4 years ago

Marcello-debug commented 4 years ago

Hello! I tried randomPMU server connected with tinyPDC client. I experienced a memory leak (quite visible also from task manager) that brings to a MemoryError. O.S. is win7 SP1. Synchrophasor version 1.0.0a0. Thank you in advance for your help. Regards

Marcello

sstevan commented 4 years ago

Hello @Marcello-debug

Please refer to https://github.com/iicsys/pypmu/issues/20#issuecomment-645628107 Let us know if you are still encountering this issue on branch bugfix-v1.0.1.

Thanks!

Marcello-debug commented 4 years ago

Thank you @sstevan for your fast and precise response. Speaking about randomPMU I confirm that introducing a "sleep time" the problem is less evident but still present. I saw that implementing a sleep time of 20 ms the memory leak rate is 0.5MB/minute. With a sleep of 1 ms the rate becomes 20 MB/minute For my application is still not acceptable, have you got any other workaround or suggestion? Thanks again.

Marcello

sstevan commented 4 years ago

@Marcello-debug have tried bugfix branch without adding sleep time?

If you are putting measurements into sending queue faster than the actual reporting rate this "memory leak" is going to appear.

So, if you are having a delay of 20ms before putting measurement into sending queue you are actually creating 50 measurements per second and your reporting rate is 30 measurements per second. This means for each second you will put 20 measurements extra in a queue which will not be sent for that exact second.

That is why putting sleep delay the same as (near) reporting rate will give you better memory usage. Of course, it takes some time to pack frames for sending and frames are not sent exactly each 1/30s that is why we suggested lowering sending delay for small amount of time that is required to prepare frames for sending.

Marcello-debug commented 4 years ago

Thanks again. I will try to be more clear because I can't understand actually how to overcome the memory leak. I'm trying the example called randomPMU. I will paste the code at the end of this message. I tried different sleep time but the memory consuption increase for every value of sleep time. For values less then 1/30 s, the memory leak is huge. Over sleep time of 1/30 s the leak is less evident but still present. Furthermore if I stop a connected PDC, memory increases the rate of consuption and become huge again. Sorry if I bother you but I'm really interested in this program. Kind Regards

Marcello

Code:

import random

from synchrophasor.frame import ConfigFrame2
from synchrophasor.pmu import Pmu

import time

"""
randomPMU will listen on ip:port for incoming connections.
After request to start sending measurements - random
values for phasors will be sent.
"""

if __name__ == "__main__":

    pmu = Pmu(ip="127.0.0.1", port=1410)
    pmu.logger.setLevel("DEBUG")

    cfg = ConfigFrame2(1410,  # PMU_ID
                       1000000,  # TIME_BASE
                       1,  # Number of PMUs included in data frame
                       "Random Station",  # Station name
                       1410,  # Data-stream ID(s)
                       (True, True, True, True),  # Data format - POLAR; PH - REAL; AN - REAL; FREQ - REAL;
                       3,  # Number of phasors
                       1,  # Number of analog values
                       1,  # Number of digital status words
                       ["VA", "VB", "VC", "ANALOG1", "BREAKER 1 STATUS",
                        "BREAKER 2 STATUS", "BREAKER 3 STATUS", "BREAKER 4 STATUS", "BREAKER 5 STATUS",
                        "BREAKER 6 STATUS", "BREAKER 7 STATUS", "BREAKER 8 STATUS", "BREAKER 9 STATUS",
                        "BREAKER A STATUS", "BREAKER B STATUS", "BREAKER C STATUS", "BREAKER D STATUS",
                        "BREAKER E STATUS", "BREAKER F STATUS", "BREAKER G STATUS"],  # Channel Names
                       [(0, "v"), (0, "v"),(0, "v")],  # Conversion factor for phasor channels - (float representation, not important)
                       [(1, "pow")],  # Conversion factor for analog channels
                       [(0x0000, 0xffff)],  # Mask words for digital status words
                       50,  # Nominal frequency
                       1,  # Configuration change count
                       30)  # Rate of phasor data transmission)

    pmu.set_configuration(cfg)
    pmu.set_header("This is a PUM server (random data)!")

    pmu.run()

    while True:
        time.sleep(1/30) #riduce consumo cpu e memory leak. Con 0.02s il rate del memory leak è 0.5MB/min. Con 1ms il rate è 20MB/min. Per valori dell'ordine delle decine di ms è più o meno lineare.
        pmu.send_data(phasors=[(random.uniform(215.0, 216.0), random.uniform(-0.1, -0.2)), (random.uniform(225.0, 226.0), random.uniform(1.9, 2.0)), (random.uniform(235.0, 236.0), random.uniform(3.0, 3.14))], #3 fasori inmodulo e fase
                      analog=[9.91],
                      digital=[0x0001],
                      freq=10.1) # mHz di scostamento da 50 Hz
    pmu.join()
sstevan commented 4 years ago

Hey @Marcello-debug

I understand your issue much better now. The issue is caused by stopping the PDC. We have variable sending_measurements_enabled = False which is set to False once the PDC is stopped (command to stop sending is sent). This means you are putting measurements into the buffer but measurements are not getting sent but only stored into the buffer (queue) which is causing increased consumption of RAM.

At this point, there is no elegant way of letting know the feed script (that is generating measurements) that generating should stop. We will add this to our roadmap as a handy feature.

However, what you can do is to try to disconnect the PDC (close connection) and check pmu.clients list for connections. If it is empty you should stop generating measurements. Not sure if this is going to solve your problem, but you can try and let me know.

Marcello-debug commented 4 years ago

Thank you again for your reply. I have tested your proposals and still the application has two problems:

  1. Memory leak with one PDC connected (RAM consuption grows with 150 kB / minute rate)
  2. Big memory leak when a PDC - that was previously connected - disconnect itself (RAM consuption grows with more then 500 kB / minute rate)

Attached you can find my code if you want to test the issues yourself.

PMU PDC C37.118.zip

Regards

Marcello