Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VSCode 用 debugpy 调试,加载 pinyin_dictphrases_dict 这两个步骤时,速度严重下降 #319

Open
qaqz111 opened this issue Mar 5, 2024 · 5 comments
Labels

Comments

@qaqz111
Copy link

qaqz111 commented Mar 5, 2024

运行环境

  • 操作系统(Linux/macOS/Windows):Windows10 Ent 22H2 更新到最新(2024.03.06 未检测到有未更新的系统补丁)
  • Python 版本:3.12.2
  • pypinyin 版本:0.50.0

问题描述

在 VSCode 不做特别配置的情况下,调试(VSCode 应该是默认使用的 debugpy)引用了 pypinyin 的 python 代码,
在加载 pinyin_dictphrases_dict 这两个步骤时,速度严重下降到不可接受的地步。

环境配置:win10 x64 企业版 22H2,VSCode 1.87.0,R7-5800H 3.20GHz,内存 16G,512G SSD。

同样是在 VSCode 中,以非调试模式运行相同的代码几乎感觉不到加载过程,
所以这并不是 pypinyin 代码的问题,应该是 debugpy 的调试机制严重拖慢了两个巨型 dict 的初始化过程。

在网络上搜了很久,发现没人提到过这个问题,请问这是个案吗?
应该如何在 VSCode 中调试引用了 pypinyin 的代码?

@mozillazg
Copy link
Owner

麻烦试试设置一下下面这两个环境变量,看看是否会有帮助:https://github.com/mozillazg/python-pinyin?tab=readme-ov-file#%E5%A6%82%E4%BD%95%E5%87%8F%E5%B0%91%E5%86%85%E5%AD%98%E5%8D%A0%E7%94%A8

@qaqz111
Copy link
Author

qaqz111 commented Mar 25, 2024

换了种方式解决了,魔改了几行源代码。
主要思路是从 pickle 二进制加载那几个硕大的 dict 数据,这样能避免因为 debugpy 介入导致的巨大耗时。

  1. 添加了一个源文件 dict_save_load.py
import os
import pickle


def pickle_path(py__file__):
    return py__file__[:-2] + "pkl"


def save_data_of(py__file__, data):
    fp = pickle_path(py__file__)
    with open(fp, "wb") as f:
        pickle.dump(data, f)


def try_load_data_of(py__file__):
    fp = pickle_path(py__file__)
    if not os.path.isfile(fp):
        return None
    with open(fp, "rb") as f:
        return pickle.load(f)
  1. 原本的 pinyin_dict.pyphrases_dict.pyphrases_dict_large.py 重命名为 *_code.py,然后用以下代码替换了原本的内容:

pinyin_dict.py

from pypinyin import dict_save_load
pinyin_dict = dict_save_load.try_load_data_of(__file__)
if not pinyin_dict:
    from pypinyin.pinyin_dict_code import pinyin_dict
    dict_save_load.save_data_of(__file__, pinyin_dict)

phrases_dict.py

from pypinyin import dict_save_load
phrases_dict = dict_save_load.try_load_data_of(__file__)
if not phrases_dict:
    from pypinyin.phrases_dict_code import phrases_dict
    dict_save_load.save_data_of(__file__, phrases_dict)

phrases_dict_large.py

from pypinyin import dict_save_load
phrases_dict = dict_save_load.try_load_data_of(__file__)
if not phrases_dict:
    from pypinyin.phrases_dict_large_code import phrases_dict
    dict_save_load.save_data_of(__file__, phrases_dict)

这个方案的缺点是,用户第一次必须以非 debug 模式运行一下代码,以确保在本地生成 pickle 二进制数据。如果第一次以 debug 模式运行的话,因为本地不存在 pickle 数据,所以必须从源代码初始化那几个硕大的 dict,这会导致第一次就以 debug 模式运行在初始化 dict 的时候会非常慢(我的机器上大概要等3~5分钟左右,R7-5800H 3.2GHz,DDR5-16G)。

更完善的思路是,让用户在安装 pypinyin 这个包的时候,就在本地生成 pickle 二进制数据,后面就可以直接加载 pickle 二进制,避免了第一次如果是 debug 模式会被 debugpy 拖慢的问题。本来想照这个思路做一个PR来提交,但是我不大清楚 py 包安装的脚本要怎么加这个过程所以没敢乱动安装脚本。

@qaqz111
Copy link
Author

qaqz111 commented Mar 25, 2024

麻烦试试设置一下下面这两个环境变量,看看是否会有帮助:https://github.com/mozillazg/python-pinyin?tab=readme-ov-file#%E5%A6%82%E4%BD%95%E5%87%8F%E5%B0%91%E5%86%85%E5%AD%98%E5%8D%A0%E7%94%A8

这个方法试过了但是貌似不管用,以 debugpy 启动调试后还是慢得不行,那两个 dict 实在太大了,除非环境变量开关能够免除这两个 dict 的初始化,不然就会被 debugpy 拖慢。

@mozillazg
Copy link
Owner

mozillazg commented Mar 31, 2024

@qaqz111 感谢分享经验!

@sz-wanghb
Copy link

python3.10没这问题,但3.12问题就出现了,我是改了个用法来规避这个问题:

import subprocess

_name = '测试'
command = ['pypinyin', '-s', 'FIRST_LETTER', _name]

result = subprocess.run(command, stdout=subprocess.PIPE, text=True)

_pinyin_list = result.stdout.strip().split()

print(_pinyin_list)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants