Python 使用 psutil 计算网速和显示进程,如何提高并发?

51 天前
 mingwiki

我刚开始学 fastapi ,写了一些简单的接口,不想搞 netdata 或者 glances 之类的复杂界面,想把服务器基本的参数服务之类的的直接显示在接口里,其中计算网速和显示进程部分严重拖累性能,qps 仅为个位数,不知道异步怎么写,有什么改进的方案,请各位大佬指导一下谢谢。

计算网速,用了 asyncio 但是并发不高,qps 个位数。

async def calculate_network_speed():
    initial_time = time.time()
    initial_bytes_sent = psutil.net_io_counters().bytes_sent
    initial_bytes_recv = psutil.net_io_counters().bytes_recv
    await asyncio.sleep(1)
    current_bytes_sent = psutil.net_io_counters().bytes_sent
    current_bytes_recv = psutil.net_io_counters().bytes_recv
    elapsed_time = time.time() - initial_time
    download_speed = (current_bytes_recv - initial_bytes_recv) / elapsed_time
    upload_speed = (current_bytes_sent - initial_bytes_sent) / elapsed_time
    return download_speed, upload_speed

显示进程,用的同步,写了个装饰器按时间 cache 结果,qps50 左右也不高。

@time_cache(5)
def get_top_processes(slice: int = 10):
    processes = [
        (
            proc.info["pid"],
            proc.info["name"],
            proc.info["cpu_percent"],
            proc.info["memory_percent"],
            " ".join(proc.info["cmdline"]),
        )
        for proc in psutil.process_iter(
            ["pid", "name", "cpu_percent", "memory_percent", "cmdline"]
        )
        if proc.info["cpu_percent"] > 0 or proc.info["memory_percent"] > 0
    ]
    top_cpu = sorted(processes, key=lambda x: x[2], reverse=True)[:slice]
    top_mem = sorted(processes, key=lambda x: x[3], reverse=True)[:slice]
    return top_cpu, top_mem

def time_cache(max_age=10, maxsize=128, typed=False):
    def decorator(fn):
        @lru_cache(maxsize=maxsize, typed=typed)
        def _new(*args, __time_salt, **kwargs):
            return fn(*args, **kwargs)

        @wraps(fn)
        def wrapped(*args, **kwargs):
            return _new(*args, **kwargs, __time_salt=int(time.time() / max_age))

        return wrapped

    return decorator

我的网站显示如下:https://api.naizi.fun/status 安装浏览器插件自动格式化一下就行了。请大佬说说 python 异步咋写,有没有好的参考?

2885 次点击
所在节点    Python
24 条回复
mingwiki
51 天前
@kneo #20 只有 python 和 uvicorn 占用 cpu ,没有磁盘读写,没有其他的系统进程占用
kneo
51 天前
@mingwiki 我说的是“系统调用”。
GeruzoniAnsasu
51 天前
@mingwiki #1 的方向就是对的。 取样是个很慢的操作。 你需要单独一个允许 block 的 routine 来处理取样周期。

而且在 linux 里大部分的「系统信息」相关的实现最后都会退化成读 procfs / sysfs 之类的,大家都不喜欢自找麻烦去调系统 API 再自己去转换那些结构/枚举/字符串…… 所以

不管什么实现都一样慢。你能做的只有把取样和查询隔离开。
julyclyde
49 天前
这事就提高不了
因为有几个参数需要多次取样然后相减
间隔时间不能太短

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1031320

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX