lbry-sdk/scripts/simulate_sync_console.py

191 lines
6.4 KiB
Python
Raw Normal View History

import asyncio
2020-07-12 00:18:33 +02:00
import argparse
from random import randrange
2020-06-27 03:52:01 +02:00
from typing import List
2020-07-01 05:13:38 +02:00
from binascii import unhexlify
from google.protobuf.message import DecodeError
2020-07-12 00:18:33 +02:00
from lbry import Config, Ledger, FullNode
2020-06-27 03:52:01 +02:00
from lbry.console import Advanced, Basic
2020-07-12 00:18:33 +02:00
from lbry.schema.claim import Claim
2020-06-27 03:52:01 +02:00
from lbry.db.utils import chunk
2020-07-29 06:14:40 +02:00
from lbry.testcase import EventGenerator
2020-07-01 05:13:38 +02:00
def cause_protobuf_stderr():
try:
Claim.from_bytes(unhexlify(
'005a3c63779597cba4c0e6ee45c3074fc389bd564ccc5d4a90eb4baacb0b028f2f4930'
'0db003d6a27f0cac8be8b45fdda597303208b81845534e4543494c07123e0a420a'
))
except DecodeError:
pass
class Simulator:
2020-06-27 03:52:01 +02:00
def __init__(self, console):
self.console = console
self.sync = console.service.sync
self.progress = self.sync._on_progress_controller
self.starting_height = 0
2020-06-27 03:52:01 +02:00
self.ending_height = 0
self.starting_file = 0
2020-07-29 06:14:40 +02:00
self.workers = console.service.db.workers
2020-06-27 03:52:01 +02:00
self.txs = 0
self.claims = 0
self.supports = 0
@property
2020-06-27 03:52:01 +02:00
def blocks(self, ):
if self.starting_height == 0:
return self.ending_height-self.starting_height
return (self.ending_height-self.starting_height)+1
2020-07-12 00:18:33 +02:00
async def generate(self, name, units, eid, label, total, steps):
loop_time = min(5.0 / (total[0]/steps[0]), 1.0)
done = (0,)*len(total)
while not all(d >= t for d, t in zip(done, total)):
if done[0] == 0:
first_event = {
"event": name,
"data": {
"id": eid,
"done": done,
"total": total,
"units": units,
}
}
if label is not None:
first_event["data"]["label"] = label
await self.progress.add(first_event)
await asyncio.sleep(loop_time)
done = tuple(min(d+s, t) for d, s, t in zip(done, steps, total))
await self.progress.add({
"event": name,
"data": {
"id": eid,
"done": done,
}
})
async def generate_group(self, name, unit, init_steps, total, increment):
await self.generate(f"{name}.init", ("steps",), 0, None, (init_steps,), (1,))
await self.progress.add({
"event": f"{name}.main",
"data": {"id": 0, "done": (0,), "total": (total,), "units": (unit,)}
})
tasks = []
2020-07-29 06:14:40 +02:00
for group_range in self.make_ranges(total, max(int(total/self.workers), 1)):
2020-07-12 00:18:33 +02:00
tasks.append(self.generate(
f"{name}.insert", (unit,),
group_range[0], f"add {unit} at {group_range[0]}-{group_range[1]}",
(group_range[1] - group_range[0],), (increment,)
))
await asyncio.wait(tasks)
await self.close_event(f"{name}.main")
async def close_event(self, name):
await self.progress.add({"event": name, "data": {"id": 0, "done": (-1, -1)}})
@staticmethod
def make_ranges(num, size=1000):
ranges = []
for i in range(0, num, size):
if ranges:
ranges[-1][-1] = i-1
ranges.append([i, 0])
ranges[-1][-1] = num
return ranges
2020-06-27 03:52:01 +02:00
async def advance(self, initial_sync: bool, ending_height: int, files: List[int], txs: int):
self.ending_height = ending_height
self.txs = txs
self.claims = int(txs/4)
self.supports = int(txs/2)
2020-07-29 06:14:40 +02:00
eg = EventGenerator(
initial_sync=initial_sync,
start=self.starting_height,
end=ending_height,
block_files=[
(0, 191, 280, ((100, 0), (191, 280))),
(1, 89, 178, ((89, 178),)),
(2, 73, 86, ((73, 86),)),
(3, 73, 86, ((73, 86),)),
(4, 73, 86, ((73, 86),)),
(5, 73, 86, ((73, 86),)),
],
claims=[
(102, 120, 361, 361),
(121, 139, 361, 361),
(140, 158, 361, 361),
(159, 177, 361, 361),
(178, 196, 361, 361),
(197, 215, 361, 361),
(216, 234, 361, 361),
(235, 253, 361, 361),
(254, 272, 361, 361),
(273, 291, 361, 361),
],
supports=[
(352, 352, 2, 2),
]
)
for event in eg.events:
await self.progress.add(event)
await asyncio.sleep(0.5)
return
2020-06-23 19:11:16 +02:00
blocks_synced = txs_synced = 0
2020-07-29 06:14:40 +02:00
for file_group in chunk(files, self.workers):
tasks = []
2020-06-27 03:52:01 +02:00
for file in file_group:
if file == files[-1]:
2020-07-01 05:13:38 +02:00
cause_protobuf_stderr()
2020-07-12 00:18:33 +02:00
tasks.append(self.generate(
"blockchain.sync.block.file", ("blocks", "txs"), file, f"blk0000{file}.dat",
(self.blocks-blocks_synced, self.txs-txs_synced),
(50, 100)
))
2020-07-01 05:13:38 +02:00
cause_protobuf_stderr()
2020-06-23 19:11:16 +02:00
else:
2020-06-27 03:52:01 +02:00
blocks = int(self.blocks / len(files))
2020-06-23 19:11:16 +02:00
blocks_synced += blocks
2020-06-27 03:52:01 +02:00
txs = int(self.txs / len(files))
2020-06-23 19:11:16 +02:00
txs_synced += txs
2020-07-12 00:18:33 +02:00
tasks.append(self.generate(
"blockchain.sync.block.file", ("blocks", "txs"), file, f"blk0000{file}.dat",
(blocks, txs), (50, 100)
))
await asyncio.wait(tasks)
2020-06-27 03:52:01 +02:00
self.ending_height = ending_height+1
self.starting_height = self.ending_height
2020-06-27 03:52:01 +02:00
2020-07-12 00:18:33 +02:00
async def main(console):
2020-06-27 03:52:01 +02:00
sim = Simulator(console)
2020-07-12 00:18:33 +02:00
await sim.advance(True, 10_000, [1, 2, 3, 4, 5], 10_000)
#await sim.advance(True, 100_000, [1, 2, 3, 4, 5], 100_000)
#await sim.advance(False, 100_001, [5], 100)
if __name__ == "__main__":
2020-07-12 00:18:33 +02:00
parser = argparse.ArgumentParser()
parser.add_argument("--basic", default=False, action="store_true")
2020-07-29 06:14:40 +02:00
parser.add_argument("--workers", default=3)
2020-07-12 00:18:33 +02:00
args = parser.parse_args()
node = FullNode(Ledger(Config(
2020-07-29 06:14:40 +02:00
workers=args.workers,
2020-07-12 00:18:33 +02:00
spv_address_filters=False
)))
console = Basic(node) if args.basic else Advanced(node)
try:
console.starting()
asyncio.run(main(console))
except KeyboardInterrupt:
pass
finally:
console.stopping()