为什么子类化 Thread 比调用 Thread 慢得多?
Why is subclassing Thread so much slower than calling Thread?
我有 Python 2.7 代码,可以发出 1,000 个请求来检查我当前的 IP 地址。我用 200 个线程和套接字编写了它。该代码使用两种方法完成相同的任务。除了一个子类 threading.Thread
之外,我找不到下面两个之间的任何区别
#!/usr/bin/env python2.7
import sys, ssl, time, socket, threading
class Counter:
def __init__(self):
self._value = 0
self._LOCK = threading.Lock()
def increment(self):
with self._LOCK:
self._value += 1
return self._value
def pr(out):
sys.stdout.write('{}\n'.format(out))
sys.stdout.flush()
def recvAll(sock):
data = ''
BUF_SIZE = 1024
while True:
part = sock.recv(BUF_SIZE)
data += part
length = len(part)
if length < BUF_SIZE: break
return data
class Speed(threading.Thread):
_COUNTER = Counter()
def __init__(self):
super(Speed, self).__init__()
self.daemon = True
self._sock = ssl.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
self._sock.settimeout(5)
self._sock.connect(('checkip.amazonaws.com', 443))
self._request = 'GET / HTTP/1.1\r\n'
self._request += 'Host: checkip.amazonaws.com\r\n\r\n'
def run(self):
i = 0
while i < 5:
self._sock.write(self._request)
response = recvAll(self._sock)
if '200 OK' not in response: continue
count = Speed._COUNTER.increment()
pr('#{} - {}'.format(count, response))
i += 1
self._sock.close()
def speed():
sock = ssl.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
sock.settimeout(5)
sock.connect(('checkip.amazonaws.com', 443))
request = 'GET / HTTP/1.1\r\n'
request += 'Host: checkip.amazonaws.com\r\n\r\n'
i = 0
while i < 5:
sock.write(request)
response = recvAll(sock)
if '200 OK' not in response: continue
count = counter.increment()
pr('#{} - {}'.format(count, response))
i += 1
sock.close()
slow = False
if slow:
for _ in xrange(200):
thread = Speed()
thread.start()
else:
counter = Counter()
for _ in xrange(200):
thread = threading.Thread(target = speed)
thread.daemon = True
thread.start()
while threading.active_count() > 1: time.sleep(1)
我预计两者的速度相似。但是,子类 threading.Thread
的变体要慢很多很多。关于原因有什么想法吗?
您的 Thread
子类在 __init__
中完成了过多的工作,它不会在新线程中执行。结果,使用子类的版本最终大部分按顺序执行。
我有 Python 2.7 代码,可以发出 1,000 个请求来检查我当前的 IP 地址。我用 200 个线程和套接字编写了它。该代码使用两种方法完成相同的任务。除了一个子类 threading.Thread
#!/usr/bin/env python2.7
import sys, ssl, time, socket, threading
class Counter:
def __init__(self):
self._value = 0
self._LOCK = threading.Lock()
def increment(self):
with self._LOCK:
self._value += 1
return self._value
def pr(out):
sys.stdout.write('{}\n'.format(out))
sys.stdout.flush()
def recvAll(sock):
data = ''
BUF_SIZE = 1024
while True:
part = sock.recv(BUF_SIZE)
data += part
length = len(part)
if length < BUF_SIZE: break
return data
class Speed(threading.Thread):
_COUNTER = Counter()
def __init__(self):
super(Speed, self).__init__()
self.daemon = True
self._sock = ssl.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
self._sock.settimeout(5)
self._sock.connect(('checkip.amazonaws.com', 443))
self._request = 'GET / HTTP/1.1\r\n'
self._request += 'Host: checkip.amazonaws.com\r\n\r\n'
def run(self):
i = 0
while i < 5:
self._sock.write(self._request)
response = recvAll(self._sock)
if '200 OK' not in response: continue
count = Speed._COUNTER.increment()
pr('#{} - {}'.format(count, response))
i += 1
self._sock.close()
def speed():
sock = ssl.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
sock.settimeout(5)
sock.connect(('checkip.amazonaws.com', 443))
request = 'GET / HTTP/1.1\r\n'
request += 'Host: checkip.amazonaws.com\r\n\r\n'
i = 0
while i < 5:
sock.write(request)
response = recvAll(sock)
if '200 OK' not in response: continue
count = counter.increment()
pr('#{} - {}'.format(count, response))
i += 1
sock.close()
slow = False
if slow:
for _ in xrange(200):
thread = Speed()
thread.start()
else:
counter = Counter()
for _ in xrange(200):
thread = threading.Thread(target = speed)
thread.daemon = True
thread.start()
while threading.active_count() > 1: time.sleep(1)
我预计两者的速度相似。但是,子类 threading.Thread
的变体要慢很多很多。关于原因有什么想法吗?
您的 Thread
子类在 __init__
中完成了过多的工作,它不会在新线程中执行。结果,使用子类的版本最终大部分按顺序执行。