2022-12-12 16:54:23 +00:00
|
|
|
"""
|
2022-12-14 16:18:17 +00:00
|
|
|
First attempt at benchmarking uploads and downloads.
|
2022-12-12 16:54:23 +00:00
|
|
|
|
2022-12-14 16:45:56 +00:00
|
|
|
To run:
|
|
|
|
|
2023-01-31 19:22:57 +00:00
|
|
|
$ pytest benchmarks/upload_download.py -s -v -Wignore
|
2022-12-14 16:45:56 +00:00
|
|
|
|
2023-01-06 16:15:59 +00:00
|
|
|
To add latency of e.g. 60ms on Linux:
|
|
|
|
|
|
|
|
$ tc qdisc add dev lo root netem delay 30ms
|
|
|
|
|
|
|
|
To reset:
|
|
|
|
|
|
|
|
$ tc qdisc del dev lo root netem
|
|
|
|
|
2023-02-13 13:59:04 +00:00
|
|
|
Frequency scaling can spoil the results.
|
|
|
|
To see the range of frequency scaling on a Linux system:
|
|
|
|
|
|
|
|
$ cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_available_frequencies
|
|
|
|
|
|
|
|
And to pin the CPU frequency to the lower bound found in these files:
|
|
|
|
|
|
|
|
$ sudo cpupower frequency-set -f <lowest available frequency>
|
|
|
|
|
2022-12-12 16:54:23 +00:00
|
|
|
TODO Parameterization (pytest?)
|
2023-01-31 19:22:57 +00:00
|
|
|
|
|
|
|
- Foolscap vs not foolscap
|
|
|
|
|
|
|
|
- Number of nodes
|
|
|
|
|
|
|
|
- Data size
|
|
|
|
|
|
|
|
- Number of needed/happy/total shares.
|
|
|
|
|
|
|
|
CAVEATS: The goal here isn't a realistic benchmark, or a benchmark that will be
|
|
|
|
measured over time, or is expected to be maintainable over time. This is just
|
|
|
|
a quick and easy way to measure the speed of certain operations, compare HTTP
|
|
|
|
and Foolscap, and see the short-term impact of changes.
|
|
|
|
|
|
|
|
Eventually this will be replaced by a real benchmark suite that can be run over
|
|
|
|
time to measure something more meaningful.
|
2022-12-12 16:54:23 +00:00
|
|
|
"""
|
|
|
|
|
2022-12-13 15:57:07 +00:00
|
|
|
from time import time, process_time
|
2022-12-12 18:38:25 +00:00
|
|
|
from contextlib import contextmanager
|
2022-12-14 16:43:59 +00:00
|
|
|
from tempfile import mkdtemp
|
|
|
|
import os
|
|
|
|
|
2022-12-12 16:54:23 +00:00
|
|
|
from twisted.trial.unittest import TestCase
|
2023-01-31 20:53:28 +00:00
|
|
|
from twisted.internet.defer import gatherResults
|
2022-12-12 16:54:23 +00:00
|
|
|
|
|
|
|
from allmydata.util.deferredutil import async_to_deferred
|
|
|
|
from allmydata.util.consumer import MemoryConsumer
|
|
|
|
from allmydata.test.common_system import SystemTestMixin
|
|
|
|
from allmydata.immutable.upload import Data as UData
|
2022-12-14 16:22:05 +00:00
|
|
|
from allmydata.mutable.publish import MutableData
|
2022-12-12 16:54:23 +00:00
|
|
|
|
|
|
|
|
2022-12-12 18:38:25 +00:00
|
|
|
@contextmanager
|
|
|
|
def timeit(name):
|
|
|
|
start = time()
|
2022-12-13 15:57:07 +00:00
|
|
|
start_cpu = process_time()
|
2022-12-12 18:38:25 +00:00
|
|
|
try:
|
|
|
|
yield
|
|
|
|
finally:
|
2022-12-14 16:43:59 +00:00
|
|
|
print(
|
|
|
|
f"{name}: {time() - start:.3f} elapsed, {process_time() - start_cpu:.3f} CPU"
|
|
|
|
)
|
2022-12-12 18:38:25 +00:00
|
|
|
|
|
|
|
|
2022-12-12 16:54:23 +00:00
|
|
|
class ImmutableBenchmarks(SystemTestMixin, TestCase):
|
|
|
|
"""Benchmarks for immutables."""
|
|
|
|
|
2022-12-14 16:46:30 +00:00
|
|
|
# To use Foolscap, change to True:
|
2022-12-12 18:38:25 +00:00
|
|
|
FORCE_FOOLSCAP_FOR_STORAGE = False
|
2022-12-12 16:54:23 +00:00
|
|
|
|
2023-02-21 14:57:21 +00:00
|
|
|
# Don't reduce HTTP connection timeouts, that messes up the more aggressive
|
|
|
|
# benchmarks:
|
|
|
|
REDUCE_HTTP_CLIENT_TIMEOUT = False
|
|
|
|
|
2022-12-12 16:54:23 +00:00
|
|
|
@async_to_deferred
|
2022-12-14 16:43:59 +00:00
|
|
|
async def setUp(self):
|
|
|
|
SystemTestMixin.setUp(self)
|
|
|
|
self.basedir = os.path.join(mkdtemp(), "nodes")
|
2022-12-12 16:54:23 +00:00
|
|
|
|
2022-12-14 16:23:06 +00:00
|
|
|
# 2 nodes
|
|
|
|
await self.set_up_nodes(2)
|
2022-12-12 16:54:23 +00:00
|
|
|
|
2022-12-14 16:18:17 +00:00
|
|
|
# 1 share
|
2022-12-12 16:54:23 +00:00
|
|
|
for c in self.clients:
|
2022-12-14 16:18:17 +00:00
|
|
|
c.encoding_params["k"] = 1
|
|
|
|
c.encoding_params["happy"] = 1
|
|
|
|
c.encoding_params["n"] = 1
|
2022-12-12 16:54:23 +00:00
|
|
|
|
2022-12-14 16:44:17 +00:00
|
|
|
print()
|
|
|
|
|
2022-12-14 16:43:59 +00:00
|
|
|
@async_to_deferred
|
|
|
|
async def test_upload_and_download_immutable(self):
|
|
|
|
# To test larger files, change this:
|
|
|
|
DATA = b"Some data to upload\n" * 10
|
|
|
|
|
2022-12-12 18:38:25 +00:00
|
|
|
for i in range(5):
|
|
|
|
# 1. Upload:
|
2022-12-14 16:45:32 +00:00
|
|
|
with timeit(" upload"):
|
2022-12-12 18:38:25 +00:00
|
|
|
uploader = self.clients[0].getServiceNamed("uploader")
|
|
|
|
results = await uploader.upload(UData(DATA, convergence=None))
|
|
|
|
|
|
|
|
# 2. Download:
|
|
|
|
with timeit("download"):
|
|
|
|
uri = results.get_uri()
|
|
|
|
node = self.clients[1].create_node_from_uri(uri)
|
|
|
|
mc = await node.read(MemoryConsumer(), 0, None)
|
|
|
|
self.assertEqual(b"".join(mc.chunks), DATA)
|
2022-12-14 16:22:05 +00:00
|
|
|
|
|
|
|
@async_to_deferred
|
|
|
|
async def test_upload_and_download_mutable(self):
|
|
|
|
# To test larger files, change this:
|
|
|
|
DATA = b"Some data to upload\n" * 10
|
|
|
|
|
|
|
|
for i in range(5):
|
|
|
|
# 1. Upload:
|
2022-12-14 16:45:32 +00:00
|
|
|
with timeit(" upload"):
|
2022-12-14 16:22:05 +00:00
|
|
|
result = await self.clients[0].create_mutable_file(MutableData(DATA))
|
|
|
|
|
|
|
|
# 2. Download:
|
|
|
|
with timeit("download"):
|
|
|
|
data = await result.download_best_version()
|
2022-12-14 16:23:06 +00:00
|
|
|
self.assertEqual(data, DATA)
|
2023-01-31 20:53:28 +00:00
|
|
|
|
|
|
|
@async_to_deferred
|
|
|
|
async def test_upload_mutable_in_parallel(self):
|
|
|
|
# To test larger files, change this:
|
|
|
|
DATA = b"Some data to upload\n" * 1_000_000
|
|
|
|
with timeit(" upload"):
|
|
|
|
await gatherResults([
|
|
|
|
self.clients[0].create_mutable_file(MutableData(DATA))
|
|
|
|
for _ in range(20)
|
|
|
|
])
|