From c525fdd30570a108f0ab2427c6f78ca11c2893a2 Mon Sep 17 00:00:00 2001 From: Alexis Delhaie Date: Tue, 6 Oct 2020 21:56:55 +0200 Subject: [PATCH] Optimizing algo, changing args names --- .gitignore | 4 ++- src/basic_producer_consumer.py | 43 ++++++++++++++++------- src/main.py | 64 +++++++++++++++------------------- src/parameters.py | 5 +-- 4 files changed, 65 insertions(+), 51 deletions(-) diff --git a/.gitignore b/.gitignore index 5391d87..baad420 100644 --- a/.gitignore +++ b/.gitignore @@ -135,4 +135,6 @@ dmypy.json .pytype/ # Cython debug symbols -cython_debug/ \ No newline at end of file +cython_debug/ + +.vscode \ No newline at end of file diff --git a/src/basic_producer_consumer.py b/src/basic_producer_consumer.py index 88b5596..f98d4e3 100644 --- a/src/basic_producer_consumer.py +++ b/src/basic_producer_consumer.py @@ -4,6 +4,8 @@ import queue import os import sys +console = None + def get_available_threads(): if sys.platform == 'win32': return (int)(os.environ['NUMBER_OF_PROCESSORS']) @@ -12,7 +14,6 @@ def get_available_threads(): SIZE = get_available_threads() q = queue.Queue() -not_finished = True class ProducerThread(threading.Thread): def __init__(self, threads): @@ -20,7 +21,6 @@ class ProducerThread(threading.Thread): self.threads = threads def run(self): - global not_finished try: i = 0 while i < len(self.threads): @@ -29,31 +29,48 @@ class ProducerThread(threading.Thread): i += 1 while q.qsize() > 0: time.sleep(0.1) - except: - pass - not_finished = False + except Exception as e: + console.print("[red]Error[/]: {}".format(e), style="bold") class ConsumerThread(threading.Thread): def __init__(self): super(ConsumerThread,self).__init__() + self.alive = True + + def stop(self): + self.alive = False def run(self): - while not_finished: - if q.qsize() > 0: - t = q.get() - t.start() - t.join() + while self.alive: + try: + if q.qsize() > 0: + t = q.get(False) + t.start() + if t.is_alive(): + t.join(t.timeout) + except queue.Empty as e: + pass + except Exception as e: + console.print("[orange3]Warning[/]: {}".format(e), style="bold") def start(threads): + process(threads, get_available_threads()) + +def start_custom_limit(threads, limit): + process(threads, limit) + +def process(threads, limit): p = ProducerThread(threads) p.start() consumers = [] - for _ in range(get_available_threads()): + for _ in range(limit): c = ConsumerThread() consumers.append(c) c.start() p.join() for c in consumers: - c.join() - \ No newline at end of file + c.stop() + for c in consumers: + if c.is_alive(): + c.join() \ No newline at end of file diff --git a/src/main.py b/src/main.py index f6dc69c..27eb441 100644 --- a/src/main.py +++ b/src/main.py @@ -13,8 +13,9 @@ import thread import basic_producer_consumer console = Console(highlight=False) -VERSION = "1.4" +VERSION = "1.4.1" thread.console = console +basic_producer_consumer.console = console def main(): if ((len(sys.argv) >= 2) and (("--help" in sys.argv) or ("/?" in sys.argv))): @@ -28,29 +29,34 @@ def main(): options = Options() options.host = get_args("-h", True, 1001, 1002) options.allow_ssl = get_flag("--ssl") - options.port = int(get_args("--port", False, 1003, 1004, "80")) + options.port = int(get_args("--port", False, 1003, 1004, ("80", "443")[options.allow_ssl])) options.path = get_args("-p", False, 1005, 1006, "/") - options.thread_number = int(get_args("-t", False, 1007, 1008, "5")) - options.timeout = int(get_args("-tm", False, 1009, 1010, "10")) + options.request_number = int(get_args("-r", False, 1007, 1008, "5")) + options.limit = int(get_args("--thread-count", False, 1007, 1008, "1500")) + options.timeout = int(get_args("--timeout", False, 1009, 1010, "10")) options.one_by_one = get_flag("--one-by-one") - options.ignore_available_threads = get_flag("--ignore-available-threads") + options.no_limit = get_flag("--no-limit") options.self_signed = get_flag("--allow-self-signed") options.headers = get_headers() - if options.one_by_one and options.ignore_available_threads: - console.print("[red]Error[/]: ambigous arguments, --one-by-one and --ignore-available-threads cannot be in the same command", style="bold") + if options.no_limit and (options.request_number < options.limit): + console.print("[orange3]Warning[/]: Too much thread, starting only {} threads".format(options.request_number), style="bold") + options.limit = options.request_number + + if options.one_by_one and options.no_limit: + console.print("[red]Error[/]: ambigous arguments, --one-by-one and --no-limit cannot be in the same command", style="bold") return start(options) def start(options): thread_array = [] - for i in range(0, options.thread_number): + for i in range(0, options.request_number): thread_array.append(StressThread(options, i, VERSION)) if options.one_by_one: start_one_by_one(thread_array) - elif options.ignore_available_threads: - start_all(thread_array) + elif options.no_limit: + basic_producer_consumer.start_custom_limit(thread_array, options.limit) else: basic_producer_consumer.start(thread_array) show_stat(thread_array, (options.timeout * 1000)) @@ -60,19 +66,6 @@ def start_one_by_one(threads): for t in threads: t.run() -# Start all requests in the same time -def start_all(threads): - for t in threads: - started = False - while not started: - try: - t.start() - started = True - except: - time.sleep(1) - for t in threads: - t.join() - def show_stat(tArray, timeoutInMs): total, succeeded = [0, 0] Tmax, Tmin, Tavg = [0, timeoutInMs, 0] @@ -107,19 +100,20 @@ def show_help(): console.print(" py main.py -h www.google.fr -p / -t 10") console.print("") console.print("Available arguments:") - console.print(" -h host The server IP or domain name") - console.print(" -p path The path of the HTTP resource") - console.print(" --port port The server HTTP port") - console.print(" -t thread Number of threads") - console.print(" -tm second Timeout of the request") - console.print(" --one-by-one Send request one by one") - console.print(" --ignore-available-threads Ignore physical number of threads and start all request in the same time") - console.print(" --ssl Use HTTPS/SSL") - console.print(" --allow-self-signed Allow self signed SSL certificate") - console.print(" --header key=value Send a custom header (To add several headers, add several times the argument --header)") + console.print(" -h host The server IP or domain name") + console.print(" -p path The path of the HTTP resource") + console.print(" -r Number of request") + console.print(" --port port The server HTTP port") + console.print(" --timeout Timeout of the request") + console.print(" --thread-count Number of request") + console.print(" --one-by-one Send request one by one") + console.print(" --no-limit Disable CPU physical threads limit") + console.print(" --ssl Use HTTPS/SSL") + console.print(" --allow-self-signed Allow self signed SSL certificate") + console.print(" --header \"key=value\" Send a custom header (To add several headers, add several times the argument --header)") console.print(" --help") - console.print(" /? Show this page") - console.print(" --version Get information about the application and the system") + console.print(" /? Show this page") + console.print(" --version Get information about the application and the system") def show_author(): console.print("[bold]Basic HTTP Stress test[/]") diff --git a/src/parameters.py b/src/parameters.py index 857f367..a362aed 100644 --- a/src/parameters.py +++ b/src/parameters.py @@ -7,10 +7,11 @@ class Options: self.allow_ssl = False self.port = 80 self.path = "/" - self.thread_number = 5 + self.request_number = 5 + self.limit = 1500 self.timeout = 10 self.one_by_one = False - self.ignore_available_threads = False + self.no_limit = False self.self_signed = False self.headers = {}