我制作了一个本地仪表板应用程序,让学生能够有效地查找/研究他们的(测量)数据。为了进一步发展,我尝试从 pandas 和 duckdb 过渡到 Polars。经过几周的工作将其集成到这个广泛的应用程序中,我意识到我遇到了一个主要问题。
该应用程序以前很稳定,但现在有了 Polars,RAM 占用空间(pythonw.exe 进程的)随着每次连续的回调而膨胀。虽然应用程序启动时大约为 100 MB;每个回调都会增加大约 5MB 的大小。我似乎还没有稳定下来;已达到 1500 MB,并且仍在增长。
我有点卡住了,非常感谢一些如何解决这个问题的建议。
我做了一个最小示例来说明这个问题。如果我使用“polars_check=True”运行它,那么我从 98MB 开始,经过 100 次迭代后它变成了 261MB。如果我使用“polars_check”=False(即 pandas)来执行此操作,那么我以 98MB 开始和结束。
import pathlib, os, shutil
import polars as pl, pandas as pd, numpy as np, datetime as dt
from dash import Dash, dcc, html, Input, Output
import plotly.graph_objects as go
#Check-input
polars_check = True ### Whether the example returns with polars or with pandas.
if polars_check: #To accomdate the slower data retrieval with pandas.
interval_time = 3E3
else:
interval_time = 3E3
#Constants
folder = pathlib.Path(r'C:\PerovskiteCell example')
n_files = 100 #Number of files in folder
n_lines = 500000 #Number of total lines in folder
n_cols = 25
#Generating sample data in example folder (Only once).
if not folder.exists():
size = int(n_lines / n_files)
col = np.linspace(-1E3, 1E3, num=size)
df = pl.DataFrame({f'col{n}': col for n in range(n_cols)})
# Creating folder & files
os.makedirs(folder)
f_path0 = folder.joinpath('0.csv')
df.write_csv(f_path0)
for n in range(1, n_files):
shutil.copy2(f_path0, folder.joinpath(f'{n}.csv'))
#Functions
def pl_data():
"""Retrieves data via the polars route"""
lf = (pl.scan_csv(folder.joinpath(f'{n}.csv'),
schema={f'col{n}': pl.Float64 for n in range(n_cols)})
.select(pl.all().get(n)) for n in range(n_files))
lf = pl.concat(lf)
lf = lf.select('col0', 'col1')
return lf.collect()
def pd_data():
"""Retrieves data via the pandas route"""
dfs = (pd.read_csv(folder.joinpath(f'{n}.csv'), usecols=['col0', 'col1']).iloc[n:n+1]
for n in range(n_files))
return pd.concat(dfs, ignore_index=True)
#App (initialization)
app = Dash()
app.layout = html.Div([dcc.Graph(id='graph'),
dcc.Interval(id = 'check',
interval = interval_time,
max_intervals = 100)])
@app.callback(
Output('graph', 'figure'),
Input('check', 'n_intervals'))
def plot(_):
#Data retrieval
if polars_check:
df = pl_data()
else:
df = pd_data()
#Plotting
fig = go.Figure()
trace = go.Scattergl(x = list(df['col0']), y=list(df['col1']), mode='lines+markers')
fig.add_trace(trace)
fig.update_xaxes(title = str(dt.datetime.now()))
return fig
if __name__ == '__main__':
app.run(debug=False, port = 8050)
您可以尝试使用垃圾收集器的python包来清空未使用的内存。希望有帮助。
gc.enable()
gc.collect(generation=2)