[PYTHON] memory is not released just by plt.close (). It should be plt.clf () → plt.close ().

wrap up

# NG
#Memory is not released
plt.close()

# OK
#Memory is released
plt.clf()
plt.close()

# NG
#Memory is not released when the order is reversed
# plt.close()If you close the figure with, you will not be able to clear the drawn contents.
plt.close()
plt.clf()

Background

When I was drawing thousands of graphs at once, I got an out of memory error. Because I was doing plt.close () every time, I wondered why and investigated it by the following experimental method. As a result, it was found that the memory was not released only by plt.close (). And I found that memory is released by doing plt.clf () → plt.close ().

experimental method

Plot a graph with a large memory size 10 times in a row. Record the memory usage at the end of each plot and examine the relationship between the number of plots and the memory usage. Perform this procedure in the following 4 patterns.

Post-processing method
pattern 1 plt.clf()
Pattern 2 plt.clf() → plt.close()
Pattern 3 plt.close()
Pattern 4 plt.close() → plt.clf()

However, ** restart the kernel for each pattern. ** To align the memory usage baseline.

The code to do this is below.

import matplotlib.pyplot as plt
import numpy as np
import psutil

mem_ary = []

#Plot 10 times
for i in range(10):
    
    #Draw a graph with a large memory size
    x = np.arange(1e7)
    y = np.arange(1e7)
    plt.plot(x, y)
    
    # ===================================================
    #Execute any one of the following patterns 1 to 4
    #Comment out the rest
    # ===================================================

    #pattern 1
    plt.clf()
    
    #Pattern 2
    plt.clf()
    plt.close()
    
    #Pattern 3
    plt.close()
    
    #Pattern 4
    plt.close()
    plt.clf

    # ===================================================

    #Record memory usage
    mem = psutil.virtual_memory().used / 1e9
    mem = round(mem, 1)
    mem_ary.append(mem)

Results and conclusions

The results are summarized in a graph as follows.

スクリーンショット 2020-06-01 午後11.38.11.png

Only plt.clf () → plt.close (), the memory usage has not increased. Therefore, you can see that plt.clf () → plt.close () should be done.

Also, if you reverse the order and select plt.close () → plt.clf (), the memory will not be released. You should be careful. I think the cause is probably that if you close the figure with plt.close (), you will not be able to clear the drawn contents. (Reference: Official DOC of plt.close (), [Official DOC of plt.clf ()](https: // matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.close))

version

matplotlib:3.2.1

Recommended Posts

memory is not released just by plt.close (). It should be plt.clf () → plt.close ().
If it is not easy to understand, it cannot be improved.
I heard rumors that malloc is slow and should be stored in memory, so I compared it.