mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-03-29 13:33:24 -07:00
Merge branch 'ArchipelagoMW:main' into Satisfactory
This commit is contained in:
66
test/benchmark/match.py
Normal file
66
test/benchmark/match.py
Normal file
@@ -0,0 +1,66 @@
|
||||
"""Micro benchmark comparing match as "switch" with if-elif and dict access"""
|
||||
|
||||
from timeit import timeit
|
||||
|
||||
|
||||
def make_match(count: int) -> str:
|
||||
code = f"for val in range({count}):\n match val:\n"
|
||||
for n in range(count):
|
||||
m = n + 1
|
||||
code += f" case {n}:\n"
|
||||
code += f" res = {m}\n"
|
||||
return code
|
||||
|
||||
|
||||
def make_elif(count: int) -> str:
|
||||
code = f"for val in range({count}):\n"
|
||||
for n in range(count):
|
||||
m = n + 1
|
||||
code += f" {'' if n == 0 else 'el'}if val == {n}:\n"
|
||||
code += f" res = {m}\n"
|
||||
return code
|
||||
|
||||
|
||||
def make_dict(count: int, mode: str) -> str:
|
||||
if mode == "value":
|
||||
code = "dct = {\n"
|
||||
for n in range(count):
|
||||
m = n + 1
|
||||
code += f" {n}: {m},\n"
|
||||
code += "}\n"
|
||||
code += f"for val in range({count}):\n res = dct[val]"
|
||||
return code
|
||||
elif mode == "call":
|
||||
code = ""
|
||||
for n in range(count):
|
||||
m = n + 1
|
||||
code += f"def func{n}():\n val = {m}\n\n"
|
||||
code += "dct = {\n"
|
||||
for n in range(count):
|
||||
code += f" {n}: func{n},\n"
|
||||
code += "}\n"
|
||||
code += f"for val in range({count}):\n dct[val]()"
|
||||
return code
|
||||
return ""
|
||||
|
||||
|
||||
def timeit_best_of_5(stmt: str, setup: str = "pass") -> float:
|
||||
"""
|
||||
Benchmark some code, returning the best of 5 runs.
|
||||
:param stmt: Code to benchmark
|
||||
:param setup: Optional code to set up environment
|
||||
:return: Time taken in microseconds
|
||||
"""
|
||||
return min(timeit(stmt, setup, number=10000, globals={}) for _ in range(5)) * 100
|
||||
|
||||
|
||||
def main() -> None:
|
||||
for count in (3, 5, 8, 10, 20, 30):
|
||||
print(f"value of {count:-2} with match: {timeit_best_of_5(make_match(count)) / count:.3f} us")
|
||||
print(f"value of {count:-2} with elif: {timeit_best_of_5(make_elif(count)) / count:.3f} us")
|
||||
print(f"value of {count:-2} with dict: {timeit_best_of_5(make_dict(count, 'value')) / count:.3f} us")
|
||||
print(f"call of {count:-2} with dict: {timeit_best_of_5(make_dict(count, 'call')) / count:.3f} us")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,7 +1,7 @@
|
||||
import unittest
|
||||
|
||||
from Fill import distribute_items_restrictive
|
||||
from NetUtils import encode
|
||||
from NetUtils import convert_to_base_types
|
||||
from worlds.AutoWorld import AutoWorldRegister, call_all
|
||||
from worlds import failed_world_loads
|
||||
from . import setup_solo_multiworld
|
||||
@@ -47,7 +47,7 @@ class TestImplemented(unittest.TestCase):
|
||||
call_all(multiworld, "post_fill")
|
||||
for key, data in multiworld.worlds[1].fill_slot_data().items():
|
||||
self.assertIsInstance(key, str, "keys in slot data must be a string")
|
||||
self.assertIsInstance(encode(data), str, f"object {type(data).__name__} not serializable.")
|
||||
convert_to_base_types(data) # only put base data types into slot data
|
||||
|
||||
def test_no_failed_world_loads(self):
|
||||
if failed_world_loads:
|
||||
|
||||
@@ -63,12 +63,12 @@ if __name__ == "__main__":
|
||||
spacer = '=' * 80
|
||||
|
||||
with TemporaryDirectory() as tempdir:
|
||||
multis = [["Clique"], ["Temp World"], ["Clique", "Temp World"]]
|
||||
multis = [["VVVVVV"], ["Temp World"], ["VVVVVV", "Temp World"]]
|
||||
p1_games = []
|
||||
data_paths = []
|
||||
rooms = []
|
||||
|
||||
copy_world("Clique", "Temp World")
|
||||
copy_world("VVVVVV", "Temp World")
|
||||
try:
|
||||
for n, games in enumerate(multis, 1):
|
||||
print(f"Generating [{n}] {', '.join(games)}")
|
||||
@@ -101,7 +101,7 @@ if __name__ == "__main__":
|
||||
with Client(host.address, game, "Player1") as client:
|
||||
local_data_packages = client.games_packages
|
||||
local_collected_items = len(client.checked_locations)
|
||||
if collected_items < 2: # Clique only has 2 Locations
|
||||
if collected_items < 2: # Don't collect anything on the last iteration
|
||||
client.collect_any()
|
||||
# TODO: Ctrl+C test here as well
|
||||
|
||||
@@ -125,7 +125,7 @@ if __name__ == "__main__":
|
||||
with Client(host.address, game, "Player1") as client:
|
||||
web_data_packages = client.games_packages
|
||||
web_collected_items = len(client.checked_locations)
|
||||
if collected_items < 2: # Clique only has 2 Locations
|
||||
if collected_items < 2: # Don't collect anything on the last iteration
|
||||
client.collect_any()
|
||||
if collected_items == 1:
|
||||
sleep(1) # wait for the server to collect the item
|
||||
|
||||
@@ -34,7 +34,7 @@ def _generate_local_inner(games: Iterable[str],
|
||||
f.write(json.dumps({
|
||||
"name": f"Player{n}",
|
||||
"game": game,
|
||||
game: {"hard_mode": "true"},
|
||||
game: {},
|
||||
"description": f"generate_local slot {n} ('Player{n}'): {game}",
|
||||
}))
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ def copy(src: str, dst: str) -> None:
|
||||
_new_worlds[dst] = str(dst_folder)
|
||||
with open(dst_folder / "__init__.py", "r", encoding="utf-8-sig") as f:
|
||||
contents = f.read()
|
||||
contents = re.sub(r'game\s*=\s*[\'"]' + re.escape(src) + r'[\'"]', f'game = "{dst}"', contents)
|
||||
contents = re.sub(r'game\s*(:\s*[a-zA-Z\[\]]+)?\s*=\s*[\'"]' + re.escape(src) + r'[\'"]', f'game = "{dst}"', contents)
|
||||
with open(dst_folder / "__init__.py", "w", encoding="utf-8") as f:
|
||||
f.write(contents)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user