Index: head/benchmarks/Makefile =================================================================== --- head/benchmarks/Makefile (revision 490785) +++ head/benchmarks/Makefile (revision 490786) @@ -1,100 +1,101 @@ # $FreeBSD$ # COMMENT = Benchmarking tools SUBDIR += apib SUBDIR += autobench SUBDIR += blogbench SUBDIR += bombardier SUBDIR += bonnie SUBDIR += bonnie++ SUBDIR += clpeak SUBDIR += cpipe SUBDIR += dbench SUBDIR += dbs SUBDIR += dhrystone SUBDIR += dkftpbench SUBDIR += fhourstones SUBDIR += filebench SUBDIR += fio SUBDIR += flamegraph SUBDIR += flops SUBDIR += flowgrind SUBDIR += forkbomb SUBDIR += glmark2 SUBDIR += gtkperf SUBDIR += hey SUBDIR += himenobench SUBDIR += hpl SUBDIR += hs-criterion SUBDIR += hs-criterion-measurement SUBDIR += httperf SUBDIR += imb SUBDIR += interbench SUBDIR += iorate SUBDIR += iozone SUBDIR += iozone21 SUBDIR += iperf SUBDIR += iperf3 SUBDIR += libcelero SUBDIR += libmicro SUBDIR += linux-vdbench SUBDIR += lmbench SUBDIR += lzbench SUBDIR += mdtest SUBDIR += nbench SUBDIR += netio SUBDIR += netperf SUBDIR += netperfmeter SUBDIR += nosqlbench SUBDIR += nqueens SUBDIR += nttcp SUBDIR += nuttcp SUBDIR += octave-forge-benchmark SUBDIR += p5-Benchmark-Forking SUBDIR += p5-Benchmark-Stopwatch SUBDIR += p5-Dumbbench SUBDIR += pathchirp SUBDIR += pathload SUBDIR += pathrate SUBDIR += pear-Benchmark SUBDIR += perftest SUBDIR += phoronix-test-suite SUBDIR += pipebench SUBDIR += polygraph SUBDIR += postal SUBDIR += postmark + SUBDIR += py-locust SUBDIR += py-naarad SUBDIR += py-throughpy SUBDIR += py-zopkio SUBDIR += pybench SUBDIR += raidtest SUBDIR += ramspeed SUBDIR += randomio SUBDIR += rubygem-benchmark-ips SUBDIR += rubygem-railsbench SUBDIR += scimark2 SUBDIR += scimark2c SUBDIR += siege SUBDIR += sipp SUBDIR += slowloris SUBDIR += smhasher SUBDIR += spp SUBDIR += stream SUBDIR += stress-ng SUBDIR += super-smack SUBDIR += sysbench SUBDIR += tcpblast SUBDIR += thrulay SUBDIR += tsung SUBDIR += ttcp SUBDIR += typometer SUBDIR += ubench SUBDIR += unixbench SUBDIR += uperf SUBDIR += vegeta SUBDIR += webbench SUBDIR += wrk .include Index: head/benchmarks/py-locust/Makefile =================================================================== --- head/benchmarks/py-locust/Makefile (nonexistent) +++ head/benchmarks/py-locust/Makefile (revision 490786) @@ -0,0 +1,34 @@ +# $FreeBSD$ + +PORTNAME= locust +PORTVERSION= 0.9.0 +CATEGORIES= benchmarks www python +MASTER_SITES= CHEESESHOP +PKGNAMEPREFIX= ${PYTHON_PKGNAMEPREFIX} +DISTNAME= locustio-${PORTVERSION} + +MAINTAINER= egypcio@FreeBSD.org +COMMENT= Python utility for doing easy, distributed load testing + +LICENSE= MIT + +RUN_DEPENDS= ${PYTHON_PKGNAMEPREFIX}Flask>=0.10.1:www/py-flask@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}gevent>=1.2.2:devel/py-gevent@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}msgpack>=0.4.2:devel/py-msgpack@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}pyzmq>=16.0.2:net/py-pyzmq@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}requests>=2.9.1:www/py-requests@${PY_FLAVOR} \ + ${PYTHON_PKGNAMEPREFIX}six>=1.10.0:devel/py-six@${PY_FLAVOR} +TEST_DEPENDS= ${PYTHON_PKGNAMEPREFIX}mock>=0:devel/py-mock@${PY_FLAVOR} + +USES= python +USE_PYTHON= autoplist distutils + +NO_ARCH= yes + +OPTIONS_DEFINE= EXAMPLES + +post-install-EXAMPLES-on: + ${MKDIR} ${STAGEDIR}${EXAMPLESDIR} + ${INSTALL_DATA} ${FILESDIR}/extra-EXAMPLES* ${STAGEDIR}${EXAMPLESDIR} + +.include Property changes on: head/benchmarks/py-locust/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/benchmarks/py-locust/distinfo =================================================================== --- head/benchmarks/py-locust/distinfo (nonexistent) +++ head/benchmarks/py-locust/distinfo (revision 490786) @@ -0,0 +1,3 @@ +TIMESTAMP = 1547833536 +SHA256 (locustio-0.9.0.tar.gz) = c77b471e0e08e215c93a7af9a95b79193268072873fbbc0effca40f3d9b58be4 +SIZE (locustio-0.9.0.tar.gz) = 226870 Property changes on: head/benchmarks/py-locust/distinfo ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Index: head/benchmarks/py-locust/files/extra-EXAMPLES-basic.py =================================================================== --- head/benchmarks/py-locust/files/extra-EXAMPLES-basic.py (nonexistent) +++ head/benchmarks/py-locust/files/extra-EXAMPLES-basic.py (revision 490786) @@ -0,0 +1,26 @@ +from locust import HttpLocust, TaskSet, task + + +def index(l): + l.client.get("/") + +def stats(l): + l.client.get("/stats/requests") + +class UserTasks(TaskSet): + # one can specify tasks like this + tasks = [index, stats] + + # but it might be convenient to use the @task decorator + @task + def page404(self): + self.client.get("/does_not_exist") + +class WebsiteUser(HttpLocust): + """ + Locust user class that does requests to the locust web server running on localhost + """ + host = "http://127.0.0.1:8089" + min_wait = 2000 + max_wait = 5000 + task_set = UserTasks Property changes on: head/benchmarks/py-locust/files/extra-EXAMPLES-basic.py ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Index: head/benchmarks/py-locust/files/extra-EXAMPLES-browse_docs_sequence_test.py =================================================================== --- head/benchmarks/py-locust/files/extra-EXAMPLES-browse_docs_sequence_test.py (nonexistent) +++ head/benchmarks/py-locust/files/extra-EXAMPLES-browse_docs_sequence_test.py (revision 490786) @@ -0,0 +1,50 @@ +# This locust test script example will simulate a user +# browsing the Locust documentation on https://docs.locust.io/ + +import random +from locust import HttpLocust, TaskSquence, seq_task, task +from pyquery import PyQuery + + +class BrowseDocumentationSequence(TaskSquence): + def on_start(self): + self.urls_on_current_page = self.toc_urls + + # assume all users arrive at the index page + @seq_task(1) + def index_page(self): + r = self.client.get("/") + pq = PyQuery(r.content) + link_elements = pq(".toctree-wrapper a.internal") + self.toc_urls = [ + l.attrib["href"] for l in link_elements + ] + + @seq_task(2) + @task(50) + def load_page(self, url=None): + url = random.choice(self.toc_urls) + r = self.client.get(url) + pq = PyQuery(r.content) + link_elements = pq("a.internal") + self.urls_on_current_page = [ + l.attrib["href"] for l in link_elements + ] + + @seq_task(3) + @task(30) + def load_sub_page(self): + url = random.choice(self.urls_on_current_page) + r = self.client.get(url) + + +class AwesomeUser(HttpLocust): + task_set = BrowseDocumentationSequence + host = "https://docs.locust.io/en/latest/" + + # we assume someone who is browsing the Locust docs, + # generally has a quite long waiting time (between + # 20 and 600 seconds), since there's a bunch of text + # on each page + min_wait = 20 * 1000 + max_wait = 600 * 1000 Property changes on: head/benchmarks/py-locust/files/extra-EXAMPLES-browse_docs_sequence_test.py ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Index: head/benchmarks/py-locust/files/extra-EXAMPLES-browse_docs_test.py =================================================================== --- head/benchmarks/py-locust/files/extra-EXAMPLES-browse_docs_test.py (nonexistent) +++ head/benchmarks/py-locust/files/extra-EXAMPLES-browse_docs_test.py (revision 490786) @@ -0,0 +1,49 @@ +# This locust test script example will simulate a user +# browsing the Locust documentation on https://docs.locust.io/ + +import random +from locust import HttpLocust, TaskSet, task +from pyquery import PyQuery + + +class BrowseDocumentation(TaskSet): + def on_start(self): + # assume all users arrive at the index page + self.index_page() + self.urls_on_current_page = self.toc_urls + + @task(10) + def index_page(self): + r = self.client.get("/") + pq = PyQuery(r.content) + link_elements = pq(".toctree-wrapper a.internal") + self.toc_urls = [ + l.attrib["href"] for l in link_elements + ] + + @task(50) + def load_page(self, url=None): + url = random.choice(self.toc_urls) + r = self.client.get(url) + pq = PyQuery(r.content) + link_elements = pq("a.internal") + self.urls_on_current_page = [ + l.attrib["href"] for l in link_elements + ] + + @task(30) + def load_sub_page(self): + url = random.choice(self.urls_on_current_page) + r = self.client.get(url) + + +class AwesomeUser(HttpLocust): + task_set = BrowseDocumentation + host = "https://docs.locust.io/en/latest/" + + # we assume someone who is browsing the Locust docs, + # generally has a quite long waiting time (between + # 20 and 600 seconds), since there's a bunch of text + # on each page + min_wait = 20 * 1000 + max_wait = 600 * 1000 Property changes on: head/benchmarks/py-locust/files/extra-EXAMPLES-browse_docs_test.py ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Index: head/benchmarks/py-locust/files/extra-EXAMPLES-custom_wait_function.py =================================================================== --- head/benchmarks/py-locust/files/extra-EXAMPLES-custom_wait_function.py (nonexistent) +++ head/benchmarks/py-locust/files/extra-EXAMPLES-custom_wait_function.py (revision 490786) @@ -0,0 +1,51 @@ +from locust import HttpLocust, TaskSet, task +import random + +def index(l): + l.client.get("/") + +def stats(l): + l.client.get("/stats/requests") + +class UserTasks(TaskSet): + # one can specify tasks like this + tasks = [index, stats] + + # but it might be convenient to use the @task decorator + @task + def page404(self): + self.client.get("/does_not_exist") + +class WebsiteUser(HttpLocust): + """ + Locust user class that does requests to the locust web server running on localhost + """ + host = "http://127.0.0.1:8089" + # Most task inter-arrival times approximate to exponential distributions + # We will model this wait time as exponentially distributed with a mean of 1 second + wait_function = lambda self: random.expovariate(1)*1000 # *1000 to convert to milliseconds + task_set = UserTasks + +def strictExp(min_wait,max_wait,mu=1): + """ + Returns an exponentially distributed time strictly between two bounds. + """ + while True: + x = random.expovariate(mu) + increment = (max_wait-min_wait)/(mu*6.0) + result = min_wait + (x*increment) + if result 0: + user, passw = USER_CREDENTIALS.pop() + self.client.post("/login", {"username":user, "password":passw}) + + @task + def some_task(self): + # user should be logged in here (unless the USER_CREDENTIALS ran out) + self.client.get("/protected/resource") + +class User(HttpLocust): + task_set = UserBehaviour + min_wait = 5000 + max_wait = 60000 Property changes on: head/benchmarks/py-locust/files/extra-EXAMPLES-dynamice_user_credentials.py ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Index: head/benchmarks/py-locust/files/extra-EXAMPLES-events.py =================================================================== --- head/benchmarks/py-locust/files/extra-EXAMPLES-events.py (nonexistent) +++ head/benchmarks/py-locust/files/extra-EXAMPLES-events.py (revision 490786) @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- + +""" +This is an example of a locustfile that uses Locust's built in event hooks to +track the sum of the content-length header in all successful HTTP responses +""" + +from locust import HttpLocust, TaskSet, events, task, web + + +class MyTaskSet(TaskSet): + @task(2) + def index(l): + l.client.get("/") + + @task(1) + def stats(l): + l.client.get("/stats/requests") + +class WebsiteUser(HttpLocust): + host = "http://127.0.0.1:8089" + min_wait = 2000 + max_wait = 5000 + task_set = MyTaskSet + + +""" +We need somewhere to store the stats. + +On the master node stats will contain the aggregated sum of all content-lengths, +while on the slave nodes this will be the sum of the content-lengths since the +last stats report was sent to the master +""" +stats = {"content-length":0} + +def on_request_success(request_type, name, response_time, response_length): + """ + Event handler that get triggered on every successful request + """ + stats["content-length"] += response_length + +def on_report_to_master(client_id, data): + """ + This event is triggered on the slave instances every time a stats report is + to be sent to the locust master. It will allow us to add our extra content-length + data to the dict that is being sent, and then we clear the local stats in the slave. + """ + data["content-length"] = stats["content-length"] + stats["content-length"] = 0 + +def on_slave_report(client_id, data): + """ + This event is triggered on the master instance when a new stats report arrives + from a slave. Here we just add the content-length to the master's aggregated + stats dict. + """ + stats["content-length"] += data["content-length"] + +# Hook up the event listeners +events.request_success += on_request_success +events.report_to_master += on_report_to_master +events.slave_report += on_slave_report + +@web.app.route("/content-length") +def total_content_length(): + """ + Add a route to the Locust web app, where we can see the total content-length + """ + return "Total content-length recieved: %i" % stats["content-length"] Property changes on: head/benchmarks/py-locust/files/extra-EXAMPLES-events.py ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Index: head/benchmarks/py-locust/files/extra-EXAMPLES-multiple_hosts.py =================================================================== --- head/benchmarks/py-locust/files/extra-EXAMPLES-multiple_hosts.py (nonexistent) +++ head/benchmarks/py-locust/files/extra-EXAMPLES-multiple_hosts.py (revision 490786) @@ -0,0 +1,31 @@ +import os + +from locust import HttpLocust, TaskSet, task +from locust.clients import HttpSession + +class MultipleHostsLocust(HttpLocust): + abstract = True + + def __init__(self, *args, **kwargs): + super(MultipleHostsLocust, self).__init__(*args, **kwargs) + self.api_client = HttpSession(base_url=os.environ["API_HOST"]) + + +class UserTasks(TaskSet): + # but it might be convenient to use the @task decorator + @task + def index(self): + self.locust.client.get("/") + + @task + def index_other_host(self): + self.locust.api_client.get("/stats/requests") + +class WebsiteUser(MultipleHostsLocust): + """ + Locust user class that does requests to the locust web server running on localhost + """ + host = "http://127.0.0.1:8089" + min_wait = 2000 + max_wait = 5000 + task_set = UserTasks Property changes on: head/benchmarks/py-locust/files/extra-EXAMPLES-multiple_hosts.py ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Index: head/benchmarks/py-locust/files/extra-EXAMPLES-semaphore_wait.py =================================================================== --- head/benchmarks/py-locust/files/extra-EXAMPLES-semaphore_wait.py (nonexistent) +++ head/benchmarks/py-locust/files/extra-EXAMPLES-semaphore_wait.py (revision 490786) @@ -0,0 +1,25 @@ +from locust import HttpLocust, TaskSet, task, events + +from gevent.coros import Semaphore +all_locusts_spawned = Semaphore() +all_locusts_spawned.acquire() + +def on_hatch_complete(**kw): + all_locusts_spawned.release() + +events.hatch_complete += on_hatch_complete + +class UserTasks(TaskSet): + def on_start(self): + all_locusts_spawned.wait() + self.wait() + + @task + def index(self): + self.client.get("/") + +class WebsiteUser(HttpLocust): + host = "http://127.0.0.1:8089" + min_wait = 2000 + max_wait = 5000 + task_set = UserTasks Property changes on: head/benchmarks/py-locust/files/extra-EXAMPLES-semaphore_wait.py ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Index: head/benchmarks/py-locust/pkg-descr =================================================================== --- head/benchmarks/py-locust/pkg-descr (nonexistent) +++ head/benchmarks/py-locust/pkg-descr (revision 490786) @@ -0,0 +1,9 @@ +Locust is an easy-to-use, distributed, user load testing tool. It is intended +for load-testing web sites (or other systems) and figuring out how many +concurrent users a system can handle. + +The behavior of each locust (or test user if you will) is defined by you and the +swarming process is monitored from a web UI in real-time. This will help you +battle test and identify bottlenecks in your code before letting real users in. + +WWW: https://locust.io/ Property changes on: head/benchmarks/py-locust/pkg-descr ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Index: head/benchmarks/py-locust/pkg-plist =================================================================== --- head/benchmarks/py-locust/pkg-plist (nonexistent) +++ head/benchmarks/py-locust/pkg-plist (revision 490786) @@ -0,0 +1,9 @@ +%%PORTEXAMPLES%%%%EXAMPLESDIR%%/extra-EXAMPLES-basic.py +%%PORTEXAMPLES%%%%EXAMPLESDIR%%/extra-EXAMPLES-browse_docs_sequence_test.py +%%PORTEXAMPLES%%%%EXAMPLESDIR%%/extra-EXAMPLES-browse_docs_test.py +%%PORTEXAMPLES%%%%EXAMPLESDIR%%/extra-EXAMPLES-custom_wait_function.py +%%PORTEXAMPLES%%%%EXAMPLESDIR%%/extra-EXAMPLES-custom_xmlrpc_client.py +%%PORTEXAMPLES%%%%EXAMPLESDIR%%/extra-EXAMPLES-dynamice_user_credentials.py +%%PORTEXAMPLES%%%%EXAMPLESDIR%%/extra-EXAMPLES-events.py +%%PORTEXAMPLES%%%%EXAMPLESDIR%%/extra-EXAMPLES-multiple_hosts.py +%%PORTEXAMPLES%%%%EXAMPLESDIR%%/extra-EXAMPLES-semaphore_wait.py Property changes on: head/benchmarks/py-locust/pkg-plist ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property