python-3.x 同时ping代码变慢,并打破了计算机的时间增加.这是怎么回事?

nsc4cvqm  于 2023-01-10  发布在  Python
关注(0)|答案(1)|浏览(172)

我的Python代码可以处理多个物联网设备,可以同时使用ssh进入多个设备,没有任何问题(使用pexpect库)。这是在multiprocessing. pool. ThreadPool中完成的。在重新启动我的MacBook之后,ping线程池中的多个主机也可以正常工作。ping 55个活动主机一次,每个主机大约需要一秒钟,ping时间和预期的一样。然而,随着时间的推移,ping代码的工作开始变得很糟糕。Ping时间增加,直到后来启动的线程超时。第一个启动的线程成功地使用了合理的ping时间,但ping操作的墙时间非常长--几秒钟后返回的ping时间低于100毫秒。
我简化了一些测试代码以隔离问题:

import subprocess
import time
from multiprocessing.pool import ThreadPool as Pool
import pythonping
import ping3

# ping using a subprocess and ping command
def ping_1(ip):
    a = time.time()
    cmd = ['ping', '-c 1', '-W 2000', ip]
    result = subprocess.run(cmd, capture_output=True, check=False)
    b = time.time()
    res = result.stdout.decode('utf-8')
    idx = res.find('time=')+len('time=')
    rtt = res[idx:res.find(' ', idx)]
    if not rtt and result.returncode == 0:
        print(res)
    rtt = '0' if not rtt else rtt
    return a, b, result.returncode == 0, float(rtt)

# ping using pythonping library
def ping_2(ip):
    a = time.time()
    result = pythonping.ping(ip, count=1, timeout=2.0)
    b = time.time()
    return a, b, result.success(), result.rtt_avg*1000

# ping using ping3 library
def ping_3(ip):
    a = time.time()
    result = ping3.ping(ip, timeout=2.0)
    b = time.time()
    return a, b, result is not None, result*1000 if result else result

# a dummy function to make sure threading works
def ding(_):
    a = time.time()
    time.sleep(1)
    b = time.time()
    return a, b

# executes one of the above in a thread pool
def test(func, ip_list, n_proc=20):
    start_time = time.time()
    if n_proc == 0:
        result = map(func, ip_list)
    else:
        with Pool(processes=n_proc) as pool:
            result = pool.map(func, ip_list)
    print(f'{f"start(s)":>8}  {f"end(s)":>6}  {"success":>7}  {"ping time (ms)":>14}')
    for start, end, success, ping_ms in result:
        print(f'{f"{start-start_time:0.3f}":>8}  {f"{end-start_time:0.3f}":>6}  '
            f'{str(success):>7}  {round(ping_ms):>14}')

# ping using n non-blocking subprocesses
def test2(ip_list):
    procs = [subprocess.Popen(['ping', '-c 1', '-W 2000', ip]) for ip in ip_list]
    while any(proc.poll() is None for proc in procs):
        time.sleep(0.1)
    return [proc.poll() for proc in procs]

重新启动后,我得到如下所示的输出。

>>> junk.test(junk.ping_1, ips, 30)
start(s)  end(s)  success  ping time (ms)
   0.020   0.071     True              31
   0.021   0.115     True              58
   0.026   0.118     True              32
   0.029   0.079     True              34
   0.031   0.098     True              32
   0.041   0.097     True              31
   0.051   0.141     True              55
   0.054   0.142     True              33
   0.071   0.288     True              56
   0.072   0.141     True              29
   0.079   0.133     True              30
   0.087   0.190     True              35
   0.098   0.184     True              32
   0.098   0.256     True              32
   0.098   0.308     True              30
   0.115   0.213     True              35
   0.118   0.307     True              36
   0.140   0.394     True              51
   0.141   0.264     True              53
   0.141   0.235     True              36
   0.142   0.412     True              36
   0.142   0.236     True              27
   0.142   0.270     True              33
   0.142   0.186     True              28
   0.148   0.247     True              31
   0.163   0.253     True              34
   0.176   0.353     True              33
   0.184   0.401     True              30
   0.185   0.333     True              32
   0.186   0.347     True              32
   0.190   0.441     True              56
   0.213   0.353     True              34
   0.221   0.386     True              32
   0.235   0.344     True              35
   0.236   0.374     True              56
   0.248   0.307     True              32
   0.248   0.447     True              51
   0.253   0.447     True              31
   0.256   0.423     True              29
   0.264   0.321     True              32
   0.270   0.412     True              51
   0.288   0.449     True              32
   0.303   0.443     True              34
   0.307   0.368     True              31
   0.307   0.380     True              30
   0.308   0.472     True              32
   0.314   0.458     True              33
   0.321   0.434     True              29
   0.333   0.452     True              30
   0.337   0.448     True              28
   0.344   0.412     True              29
   0.347   0.448     True              33
   0.353   0.442     True              28
   0.353   0.501     True              55
   0.371   0.464     True              34

经过几个小时到几天的正常运行时间,它逐渐变成这样:

start(s)  end(s)  success  ping time (ms)
   0.005   0.084     True              48
   0.005  10.217     True              39
   0.009  10.242     True              44
   0.012  10.207     True              51
   0.013  10.156     True             171
   0.029  10.217     True              50
   0.035  10.177     True              48
   0.053  10.157     True             166
   0.060  10.216     True             483
   0.061  10.124     True             689
   0.061  10.091     True             944
   0.085  10.111     True             945
   0.086  10.121     True             684
   0.095  10.100     True             955
   0.113  10.089     True             950
   0.126  10.117     True             959
   0.136  10.150     True             966
   0.136  10.141     True             964
   0.147   9.283     True            1003
   0.147  10.176     True             973
   0.148   9.245     True            1009
   0.148  10.175     True             976
   0.164  10.231     True             980
   0.173  10.177     True             973
   0.179  10.236     True             983
   0.194   9.276     True             997
   0.203   9.257     True            1000
   0.219   9.721     True            1470
   0.220   9.247     True            1007
   0.245   9.934     True            1960
   0.238   9.945     True            1947
   9.246  13.269    False               0
   9.247  13.271    False               0
   9.257  13.282    False               0
   9.277  13.291    False               0
   9.283  13.303    False               0
   9.722  13.747    False               0
   9.935  13.954    False               0
   9.945  13.967    False               0
  10.090  14.107    False               0
  10.091  14.116    False               0
  10.101  14.126    False               0
  10.111  14.136    False               0
  10.117  14.153    False               0
  10.121  14.153    False               0
  10.125  14.236    False               0
  10.142  14.170    False               0
  10.151  14.163    False               0
  10.156  14.187    False               0
  10.157  14.213    False               0
  10.175  14.247    False               0
  10.176  14.205    False               0
  10.177  14.219    False               0
  10.177  14.191    False               0
  10.207  14.230    False               0

上面代码中的所有ping方法都遵循相同的模式。(ping 3似乎在重启后也表现得很奇怪,但随着时间的推移,情况会变得更糟。)我尝试过通过WiFi、有线以太网和手机的热点功能来重启所有Python内核,升级Python(通过Anaconda),升级MacOS(主要和次要),升级VPN客户端(思科)、删除防病毒软件(MS Defender)。一旦它进入这种状态,除了重新启动之外,没有任何东西可以修复它。该模式在所有列出的更新中都会持续存在。
有趣的是,当计算机处于这种状态时,我可以启动一个Docker容器,用相同的Python版本运行相同的代码,效果很好。关闭Docker Desktop既不能修复问题,也不能防止问题发生,如果在重新启动后立即关闭的话。
我也观察过Angry IP Scanner(设置为使用128个线程)的操作。在重新启动后,一个特定的IP扫描需要14秒。在ping问题出现后,同样的扫描需要145秒!
我尝试了30次并行ping我的路由器,问题也出现了,尽管程度要小得多。ping没有超时,只是对于较晚启动的线程来说时间更长。第一个线程在〈10 ms内得到一个ping。最后一个线程测量的ping时间为数百毫秒。
Update 1:昨晚睡觉前,我用愤怒的IP扫描仪运行了扫描,大约花了15秒。今天早上花了90秒。问题似乎已经表现出来,而计算机不在使用中。
Update 2:再次,问题突然出现,而我离开了电脑。它可能与Mac的省电功能有什么关系?在这两个最近发生的事件,MacBook连接到交流电源,所以省电功能被部分禁用(“防止Mac从自动睡眠时,显示器关闭”在设置中启用)。

r3i60tvu

r3i60tvu1#

这里的问题出在思科VPN软件上。不是客户端本身,而是一些与之配套的叫做包过滤器的辅助扩展。由于它们是系统网络扩展,即使VPN断开连接,它们也是活动的。引入了一个bug在Cisco AnyConnect for MacOS 4.10版中(或重新引入),并在5.0版中继续使用(重命名为Cisco Secure Client)。它会导致非常高的CPU负载(在我的系统上钉住一个处理器核心)在网络活动期间,尤其是并行操作,如发生在主机扫描期间。性能问题是如此严重,愤怒的IP扫描程序,例如,扫描200个IP地址所需的时间可能比正常情况下多10倍,并且无法检测到所找到的主机上打开的 * 任何 * 端口。
解决方案是关闭包过滤器,然后删除软件。如this post中所述,停用是通过以下控制台命令完成的:
sudo /Applications/Cisco/Cisco\ AnyConnect\ Socket\ Filter.app/Contents/MacOS/Cisco\ AnyConnect\ Socket\ Filter -deactivateExt.
Cisco安全客户端的路径略有不同:
sudo /Applications/Cisco/Cisco\ Secure\ Client\ -\ Socket\ Filter.app/Contents/MacOS/Cisco\ Secure\ Client\ -\ Socket\ Filter -deactivateExt
一旦这样做,垃圾包过滤器应用程序下的应用程序/思科。VPN连接似乎没有它工作得很好。

相关问题