Make benchmarker work properly

This commit is contained in:
Andrew Godwin 2016-02-23 21:40:30 +00:00
parent 9a9eb26d36
commit ca4e3f0af5
3 changed files with 100 additions and 49 deletions

View File

@ -1,11 +1,11 @@
import random from __future__ import unicode_literals
import time
import random
from autobahn.twisted.websocket import WebSocketClientProtocol, \ from autobahn.twisted.websocket import WebSocketClientProtocol, \
WebSocketClientFactory WebSocketClientFactory
NUM_CONNECTIONS = 100
PER_SECOND = 10
stats = {} stats = {}
@ -15,84 +15,133 @@ class MyClientProtocol(WebSocketClientProtocol):
message_gap = 1 message_gap = 1
def onConnect(self, response): def onConnect(self, response):
self.opened = time.time()
self.sent = 0 self.sent = 0
self.last_send = None
self.received = 0 self.received = 0
self.corrupted = 0 self.corrupted = 0
self.out_of_order = 0 self.out_of_order = 0
self.latencies = []
self.fingerprint = "".join(random.choice("abcdefghijklmnopqrstuvwxyz") for i in range(16)) self.fingerprint = "".join(random.choice("abcdefghijklmnopqrstuvwxyz") for i in range(16))
stats[self.fingerprint] = {} stats[self.fingerprint] = {}
def onOpen(self): def onOpen(self):
def hello(): def hello():
self.sendMessage("%s:%s" % (self.sent, self.fingerprint)) if self.last_send is None:
self.sent += 1 if self.sent >= self.num_messages:
if self.sent < self.num_messages: self.sendClose()
self.factory.reactor.callLater(1, hello) return
self.sendMessage(("%s:%s" % (self.sent, self.fingerprint)).encode("ascii"))
self.last_send = time.time()
self.sent += 1
else: else:
self.sendClose() # Wait for receipt of ping
pass
self.factory.reactor.callLater(1, hello)
hello() hello()
def onMessage(self, payload, isBinary): def onMessage(self, payload, isBinary):
num, fingerprint = payload.split(":") num, fingerprint = payload.decode("ascii").split(":")
if fingerprint != self.fingerprint: if fingerprint != self.fingerprint:
self.corrupted += 1 self.corrupted += 1
if num != self.received: if int(num) != self.received:
self.out_of_order += 1 self.out_of_order += 1
self.received += 1 self.received += 1
self.latencies.append(time.time() - self.last_send)
self.last_send = None
def onClose(self, wasClean, code, reason): def onClose(self, wasClean, code, reason):
stats[self.fingerprint] = { if hasattr(self, "sent"):
"sent": self.sent, stats[self.fingerprint] = {
"received": self.received, "sent": self.sent,
"corrupted": self.corrupted, "received": self.received,
"out_of_order": self.out_of_order, "corrupted": self.corrupted,
} "out_of_order": self.out_of_order,
"connect": True,
}
else:
self.fingerprint = "".join(random.choice("abcdefghijklmnopqrstuvwxyz") for i in range(16))
stats[self.fingerprint] = {
"sent": 0,
"received": 0,
"corrupted": 0,
"out_of_order": 0,
"connect": False,
}
def spawn_connections():
if len(stats) >= NUM_CONNECTIONS:
return
for i in range(PER_SECOND):
reactor.connectTCP("127.0.0.1", 9000, factory)
reactor.callLater(1, spawn_connections)
class Benchmarker(object):
"""
Performs benchmarks against WebSockets.
"""
def print_progress(): def __init__(self, url, num, rate):
open_protocols = len([x for x in stats.values() if not x]) self.url = url
print "%s open, %s total" % ( self.num = num
open_protocols, self.rate = rate
len(stats), self.factory = WebSocketClientFactory(
) args.url,
reactor.callLater(1, print_progress) debug=False,
if open_protocols == 0 and len(stats) >= NUM_CONNECTIONS: )
reactor.stop() self.factory.protocol = MyClientProtocol
print_stats()
def loop(self):
self.spawn_connections()
self.print_progress()
reactor.callLater(1, self.loop)
def print_stats(): def spawn_connections(self):
num_incomplete = len([x for x in stats.values() if x['sent'] != x['received']]) if len(stats) >= self.num:
num_corruption = len([x for x in stats.values() if x['corrupted']]) return
num_out_of_order = len([x for x in stats.values() if x['out_of_order']]) for i in range(self.rate):
print "-------" # TODO: Look at URL
print "Sockets opened: %s" % len(stats) reactor.connectTCP("127.0.0.1", 8000, self.factory)
print "Incomplete sockets: %s (%.2f%%)" % (num_incomplete, (float(num_incomplete) / len(stats))*100)
print "Corrupt sockets: %s (%.2f%%)" % (num_corruption, (float(num_corruption) / len(stats))*100) def print_progress(self):
print "Out of order sockets: %s (%.2f%%)" % (num_out_of_order, (float(num_out_of_order) / len(stats))*100) open_protocols = len([x for x in stats.values() if not x])
print("%s open, %s total" % (
open_protocols,
len(stats),
))
if open_protocols == 0 and len(stats) >= self.num:
print("Reached %s open connections, quitting" % self.num)
reactor.stop()
self.print_stats()
def print_stats(self):
num_incomplete = len([x for x in stats.values() if x['sent'] != x['received']])
num_corruption = len([x for x in stats.values() if x['corrupted']])
num_out_of_order = len([x for x in stats.values() if x['out_of_order']])
num_failed = len([x for x in stats.values() if not x['connect']])
print("-------")
print("Sockets opened: %s" % len(stats))
print("Incomplete sockets: %s (%.2f%%)" % (num_incomplete, (float(num_incomplete) / len(stats))*100))
print("Corrupt sockets: %s (%.2f%%)" % (num_corruption, (float(num_corruption) / len(stats))*100))
print("Out of order sockets: %s (%.2f%%)" % (num_out_of_order, (float(num_out_of_order) / len(stats))*100))
print("Failed to connect: %s (%.2f%%)" % (num_failed, (float(num_failed) / len(stats))*100))
if __name__ == '__main__': if __name__ == '__main__':
import sys import sys
import argparse
from twisted.python import log from twisted.python import log
from twisted.internet import reactor from twisted.internet import reactor
# log.startLogging(sys.stdout) # log.startLogging(sys.stdout)
factory = WebSocketClientFactory(u"ws://127.0.0.1:9000", debug=False) parser = argparse.ArgumentParser()
factory.protocol = MyClientProtocol parser.add_argument("url")
parser.add_argument("-n", "--num", type=int, default=100)
reactor.callLater(1, spawn_connections) parser.add_argument("-r", "--rate", type=int, default=10)
reactor.callLater(1, print_progress) args = parser.parse_args()
benchmarker = Benchmarker(
url=args.url,
num=args.num,
rate=args.rate,
)
benchmarker.loop()
reactor.run() reactor.run()

View File

@ -18,6 +18,8 @@ ROOT_URLCONF = 'testproject.urls'
WSGI_APPLICATION = 'testproject.wsgi.application' WSGI_APPLICATION = 'testproject.wsgi.application'
STATIC_URL = "/static/"
DATABASES = { DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.sqlite3', 'ENGINE': 'django.db.backends.sqlite3',
@ -25,9 +27,9 @@ DATABASES = {
} }
} }
CHANNEL_BACKENDS = { CHANNEL_LAYERS = {
"default": { "default": {
"BACKEND": "channels.database_layer.DatabaseChannelLayer", "BACKEND": "asgiref.inmemory.ChannelLayer",
"ROUTING": "testproject.urls.channel_routing", "ROUTING": "testproject.urls.channel_routing",
}, },
} }

View File

@ -3,5 +3,5 @@ from chtest import consumers
urlpatterns = [] urlpatterns = []
channel_routing = { channel_routing = {
"websocket.message": consumers.ws_message, "websocket.receive": consumers.ws_message,
} }