mirror of
https://github.com/beetbox/beets.git
synced 2026-07-20 19:46:57 -04:00
Introduce Source class to encapsulate metadata extraction logic, replacing scattered `get_most_common_tags` calls throughout codebase. - Add Source class in importer.tasks with artist, name, and metadata - Simplify `distance()` to accept Source.data instead of items list - Update display functions to use Source objects - Cache Source creation with @cached_property on ImportTask This centralizes metadata handling and reduces coupling between autotag and library modules.
118 lines
3.4 KiB
Python
118 lines
3.4 KiB
Python
"""Some simple performance benchmarks for beets."""
|
|
|
|
import cProfile
|
|
import timeit
|
|
|
|
from beets import importer, plugins, ui
|
|
from beets.autotag import Source, tag_album
|
|
from beets.plugins import BeetsPlugin
|
|
from beets.util.functemplate import Template
|
|
from beets.util.pathformats import PF_KEY_DEFAULT
|
|
from beetsplug._utils import vfs
|
|
|
|
|
|
def aunique_benchmark(lib, prof):
|
|
def _build_tree():
|
|
vfs.libtree(lib)
|
|
|
|
# Measure path generation performance with %aunique{} included.
|
|
lib.path_formats = [
|
|
(
|
|
PF_KEY_DEFAULT,
|
|
Template("$albumartist/$album%aunique{}/$track $title"),
|
|
)
|
|
]
|
|
if prof:
|
|
cProfile.runctx(
|
|
"_build_tree()",
|
|
{},
|
|
{"_build_tree": _build_tree},
|
|
"paths.withaunique.prof",
|
|
)
|
|
else:
|
|
interval = timeit.timeit(_build_tree, number=1)
|
|
print("With %aunique:", interval)
|
|
|
|
# And with %aunique replaced with a "cheap" no-op function.
|
|
lib.path_formats = [
|
|
(PF_KEY_DEFAULT, Template("$albumartist/$album%lower{}/$track $title"))
|
|
]
|
|
if prof:
|
|
cProfile.runctx(
|
|
"_build_tree()",
|
|
{},
|
|
{"_build_tree": _build_tree},
|
|
"paths.withoutaunique.prof",
|
|
)
|
|
else:
|
|
interval = timeit.timeit(_build_tree, number=1)
|
|
print("Without %aunique:", interval)
|
|
|
|
|
|
def match_benchmark(lib, prof, query=None, album_id=None):
|
|
# If no album ID is provided, we'll match against a suitably huge
|
|
# album.
|
|
if not album_id:
|
|
album_id = "9c5c043e-bc69-4edb-81a4-1aaf9c81e6dc"
|
|
|
|
# Get an album from the library to use as the source for the match.
|
|
items = lib.albums(query).get().items()
|
|
|
|
# Ensure fingerprinting is invoked (if enabled).
|
|
plugins.send(
|
|
"import_task_start",
|
|
task=importer.ImportTask(None, None, items),
|
|
session=importer.ImportSession(lib, None, None, None),
|
|
)
|
|
|
|
# Run the match.
|
|
def _run_match():
|
|
source = Source.from_items(items)
|
|
tag_album(source, search_ids=[album_id])
|
|
|
|
if prof:
|
|
cProfile.runctx(
|
|
"_run_match()", {}, {"_run_match": _run_match}, "match.prof"
|
|
)
|
|
else:
|
|
interval = timeit.timeit(_run_match, number=1)
|
|
print("match duration:", interval)
|
|
|
|
|
|
class BenchmarkPlugin(BeetsPlugin):
|
|
"""A plugin for performing some simple performance benchmarks."""
|
|
|
|
def commands(self):
|
|
aunique_bench_cmd = ui.Subcommand(
|
|
"bench_aunique", help="benchmark for %aunique{}"
|
|
)
|
|
aunique_bench_cmd.parser.add_option(
|
|
"-p",
|
|
"--profile",
|
|
action="store_true",
|
|
default=False,
|
|
help="performance profiling",
|
|
)
|
|
aunique_bench_cmd.func = lambda lib, opts, args: aunique_benchmark(
|
|
lib, opts.profile
|
|
)
|
|
|
|
match_bench_cmd = ui.Subcommand(
|
|
"bench_match", help="benchmark for track matching"
|
|
)
|
|
match_bench_cmd.parser.add_option(
|
|
"-p",
|
|
"--profile",
|
|
action="store_true",
|
|
default=False,
|
|
help="performance profiling",
|
|
)
|
|
match_bench_cmd.parser.add_option(
|
|
"-i", "--id", default=None, help="album ID to match against"
|
|
)
|
|
match_bench_cmd.func = lambda lib, opts, args: match_benchmark(
|
|
lib, opts.profile, args, opts.id
|
|
)
|
|
|
|
return [aunique_bench_cmd, match_bench_cmd]
|