Skip to content

Instantly share code, notes, and snippets.

@cosven
Last active March 2, 2019 18:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cosven/800fe60aab5929592306e43c46116100 to your computer and use it in GitHub Desktop.
Save cosven/800fe60aab5929592306e43c46116100 to your computer and use it in GitHub Desktop.
FeelUOwn 内存使用分析

FeelUOwn 内存使用分析

2019-03-03 再次测试结论

NameUsage(MiB)Description
python37启动
mpv37import + init
requests10import
beautifulsoup6import
crypto4import

如果 GUI 模式启动:import PyQt 包,初始化 widgets,则会额外消耗 60MB 左右内存。

结论

  • Python 自身 -> 32 MiB 左右
  • 内存主要消耗在 import 各种包上
    • import MPV -> 30 MiB
    • import bs4 -> 7 MiB
    • import requests -> 10 MiB
    • import dbus.mainloop.pyqt -> 4 MiB
  • 初始化
    • MPV 初始化 -> 3 MiB

以上加起来大概 80 MiB 左右,但是我在 monitor 里面看到这个时候,程序其实只占了 40 MiB。 通过 ps 的百分比 * 系统内存,自己计算出来也是 80 MiB,这是一个稍微奇怪的地方,不过并不重要。

  • [ ] 根据之前的测试,加载播放列表和歌单,也会让内存占用增加很多:100 首歌大概会增加 1M 左右,记忆中,待之后具体测试

测试方法:在函数前面加两行代码,然后二分法定位具体是哪个东西耗费内存较多。

from memory_profiler import profile
@profile
def func():
    pass

公共部分消耗内存

什么都不干,只 import 包,运行 feeluown 的 __main__.py

Line #    Mem usage    Increment   Line Contents
================================================
    62     39.6 MiB     39.6 MiB   @profile
    63                             def main():

单独运行一个什么也不干,什么也不 import 的 main.py

Line #    Mem usage    Increment   Line Contents
================================================
     4     32.5 MiB     32.5 MiB   @profile
     5                             def main():
     6     32.5 MiB      0.0 MiB       pass

import 5 个标准库 sys, logging, traceback, os, asyncio 后,总共耗费 34.8 MiB

加上这一句 from fuocore.app import run_server 之后,总共耗费大约 68 MiB

二分法发现是这一行会消耗 34 MiB 内存

from mpv import MPV, MpvEventID, MpvEventEndFile, \
    _mpv_set_property_string

GUI 模式消耗内存

from PyQt5 import QtWidgets 这一句消耗 12.5 MiB

CLI 模式部分消耗内存

从 main 函数开始分析

95     83.6 MiB     10.4 MiB           from feeluown.app import CliApp
96
97     83.6 MiB      0.0 MiB           pubsub_gateway, pubsub_server = run_pubsub()
98     87.1 MiB      3.4 MiB           app = CliApp(pubsub_gateway)
99    102.0 MiB     14.9 MiB           app.initialize()  #

import CliApp 耗费 10.4 MiB

import requests 耗费了 10 MiB 内存

CliApp 初始化耗费 3.4 MiB

Line #    Mem usage    Increment   Line Contents
================================================
    49     84.0 MiB     84.0 MiB       @profile
    50                                 def __init__(self, pubsub_gateway):
    51     87.8 MiB      3.8 MiB           super().__init__()
    52
    53     87.8 MiB      0.0 MiB           self.pubsub_gateway = pubsub_gateway
    54     87.8 MiB      0.0 MiB           self._live_lyric_publisher = LiveLyricPublisher(pubsub_gateway)
    55
    56     87.8 MiB      0.0 MiB           self.live_lyric.sentence_changed.connect(self._live_lyric_publisher.publish)

MpvPlayer 初始化占用内存 3.7 MiB 左右

app.initialize 耗费 14.9 MiB

插件耗费内存 14.3 MiB

Line #    Mem usage    Increment   Line Contents
================================================
    36     87.8 MiB     87.8 MiB       @profile
    37                                 def initialize(self):
    38     87.8 MiB      0.0 MiB           self.player.position_changed.connect(self.live_lyric.on_position_changed)
    39     87.8 MiB      0.0 MiB           self.playlist.song_changed.connect(self.live_lyric.on_song_changed)
    40
    41    102.2 MiB     14.3 MiB           self.plugin_mgr.scan()
    42    102.2 MiB      0.0 MiB           loop = asyncio.get_event_loop()
    43    102.2 MiB      0.0 MiB           loop.call_later(10, partial(loop.create_task, self.version_mgr.check_release()))
mpris2 插件耗费内存 4.1 MiB
Line #    Mem usage    Increment   Line Contents
================================================
    12     88.0 MiB     88.0 MiB   @profile
    13                             def enable(app):
    14     88.0 MiB      0.0 MiB       logger = logging.getLogger(__name__)
    15     88.0 MiB      0.0 MiB       if not is_linux():
    16                                     logger.warning('not a linux system, wont load mpris2 plugin')
    17                                     return
    18     90.4 MiB      2.4 MiB       import dbus.mainloop.pyqt5
    19     90.4 MiB      0.0 MiB       from .service import MprisServer
    20     90.4 MiB      0.0 MiB       dbus.mainloop.pyqt5.DBusQtMainLoop(set_as_default=True)
    21     92.1 MiB      1.7 MiB       MprisServer(app)
    22     92.1 MiB      0.0 MiB       logger.info('load mpris2 plugin')
importlib.import_module local 耗费 2.6 MiB
Line #    Mem usage    Increment   Line Contents
================================================
    15     88.0 MiB     88.0 MiB   @profile
    16                             def enable(app):
    17     90.4 MiB      2.4 MiB       from fuocore.local.provider import provider
    18     90.4 MiB      0.0 MiB       from feeluown.app import App

注释 local/provider.py 下面两句,可以减少到 1.0 MiB

#from mutagen import MutagenError
#from mutagen.mp3 import EasyMP3
importlib.import_module neteasemusic 耗费 8.4 MiB

注释下面三句,就只消耗 1.0 MiB 了,呵呵

from Crypto.Cipher import AES
from Crypto.PublicKey import RSA  # 这两个大概 0.5 MiB 左右
from bs4 import BeautifulSoup  # 关键是这个
importlib.import_module qqmusic 基本不消耗内存
@cosven
Copy link
Author

cosven commented Jul 31, 2018

所以,可能可以做一些优化:

  • 基于其它播放器,而不是 MPV:比如 QMediaPlayer 或者 mplayer?(不知道其它播放器会怎样)
  • 去掉 bs4 依赖

试了下,用 mplayer 播放一首歌,占用 0.4% 的内存,而 mpv 会占用 0.7。
也就是说:mpv 大概 60 MiB 左右,mplayer 32 MiB 左右。

@cosven
Copy link
Author

cosven commented Feb 26, 2019

2019-02-26

  • FeelUOwn CLI 模式启动后,占用内存 50MiB
  • FeelUOwn GUI 模式启动后,接近 100 MiB

根据 memory_profiler 结果来看:

  • QApplication 实例化
  • Ui 类实例化
  • QApplication.setIcon

三个操作各占用 10MiB 内存左右。

另外,import PyQt5 等一些库也会 20+ MiB 左右。

setIcon 优化

setIcon(Pixmap(path)) 可以优化内存,从 10MiB -> 2MiB

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment