From a99d5708e6d603e8f7cfd1b8c6595f8026219ba0 Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Mon, 17 Jul 2023 20:10:24 +0300 Subject: skip installing packages with pip if theyare already installed record time it took to launch --- modules/launch_utils.py | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) (limited to 'modules/launch_utils.py') diff --git a/modules/launch_utils.py b/modules/launch_utils.py index 434facbc..03552bc2 100644 --- a/modules/launch_utils.py +++ b/modules/launch_utils.py @@ -1,4 +1,5 @@ # this scripts installs necessary requirements and launches main program in webui.py +import re import subprocess import os import sys @@ -9,6 +10,9 @@ from functools import lru_cache from modules import cmd_args, errors from modules.paths_internal import script_path, extensions_dir +from modules import timer + +timer.startup_timer.record("start") args, _ = cmd_args.parser.parse_known_args() @@ -226,6 +230,44 @@ def run_extensions_installers(settings_file): run_extension_installer(os.path.join(extensions_dir, dirname_extension)) +re_requirement = re.compile(r"\s*([-_a-zA-Z0-9]+)\s*(?:==\s*([-+_.a-zA-Z0-9]+))?\s*") + + +def requrements_met(requirements_file): + """ + Does a simple parse of a requirements.txt file to determine if all rerqirements in it + are already installed. Returns True if so, False if not installed or parsing fails. + """ + + import importlib.metadata + import packaging.version + + with open(requirements_file, "r", encoding="utf8") as file: + for line in file: + if line.strip() == "": + continue + + m = re.match(re_requirement, line) + if m is None: + return False + + package = m.group(1).strip() + version_required = (m.group(2) or "").strip() + + if version_required == "": + continue + + try: + version_installed = importlib.metadata.version(package) + except Exception: + return False + + if packaging.version.parse(version_required) != packaging.version.parse(version_installed): + return False + + return True + + def prepare_environment(): torch_index_url = os.environ.get('TORCH_INDEX_URL', "https://download.pytorch.org/whl/cu118") torch_command = os.environ.get('TORCH_COMMAND', f"pip install torch==2.0.1 torchvision==0.15.2 --extra-index-url {torch_index_url}") @@ -311,7 +353,9 @@ def prepare_environment(): if not os.path.isfile(requirements_file): requirements_file = os.path.join(script_path, requirements_file) - run_pip(f"install -r \"{requirements_file}\"", "requirements") + + if not requrements_met(requirements_file): + run_pip(f"install -r \"{requirements_file}\"", "requirements") run_extensions_installers(settings_file=args.ui_settings_file) -- cgit v1.2.3 From 3c570421d3a2eb24528b5f5bb615dcb0c7717e4a Mon Sep 17 00:00:00 2001 From: wfjsw Date: Tue, 18 Jul 2023 19:00:16 +0800 Subject: move start timer --- launch.py | 4 +++- modules/api/models.py | 2 +- modules/launch_utils.py | 3 --- 3 files changed, 4 insertions(+), 5 deletions(-) (limited to 'modules/launch_utils.py') diff --git a/launch.py b/launch.py index b103c8f3..e9667c88 100644 --- a/launch.py +++ b/launch.py @@ -1,4 +1,4 @@ -from modules import launch_utils +from modules import launch_utils, timer args = launch_utils.args @@ -25,6 +25,8 @@ start = launch_utils.start def main(): + timer.startup_timer.record("start") + if not args.skip_prepare_environment: prepare_environment() diff --git a/modules/api/models.py b/modules/api/models.py index b55fa728..96cfe920 100644 --- a/modules/api/models.py +++ b/modules/api/models.py @@ -213,7 +213,7 @@ for key, metadata in opts.data_labels.items(): value = None optType = opts.typemap.get(type(metadata.default), type(value)) - if optType == types.NoneType: + if isinstance(optType, types.NoneType): pass elif metadata is not None: fields.update({key: (Optional[optType], Field(default=metadata.default, description=metadata.label))}) diff --git a/modules/launch_utils.py b/modules/launch_utils.py index 03552bc2..ea995eda 100644 --- a/modules/launch_utils.py +++ b/modules/launch_utils.py @@ -10,9 +10,6 @@ from functools import lru_cache from modules import cmd_args, errors from modules.paths_internal import script_path, extensions_dir -from modules import timer - -timer.startup_timer.record("start") args, _ = cmd_args.parser.parse_known_args() -- cgit v1.2.3 From 118529a6dc9481499ebcd589a9b42f98b58bca8a Mon Sep 17 00:00:00 2001 From: Jabasukuriputo Wang Date: Fri, 21 Jul 2023 21:49:33 +0800 Subject: typo fix --- modules/launch_utils.py | 6 +++--- webui.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'modules/launch_utils.py') diff --git a/modules/launch_utils.py b/modules/launch_utils.py index 03552bc2..8e11bf42 100644 --- a/modules/launch_utils.py +++ b/modules/launch_utils.py @@ -233,7 +233,7 @@ def run_extensions_installers(settings_file): re_requirement = re.compile(r"\s*([-_a-zA-Z0-9]+)\s*(?:==\s*([-+_.a-zA-Z0-9]+))?\s*") -def requrements_met(requirements_file): +def requirements_met(requirements_file): """ Does a simple parse of a requirements.txt file to determine if all rerqirements in it are already installed. Returns True if so, False if not installed or parsing fails. @@ -293,7 +293,7 @@ def prepare_environment(): try: # the existance of this file is a signal to webui.sh/bat that webui needs to be restarted when it stops execution os.remove(os.path.join(script_path, "tmp", "restart")) - os.environ.setdefault('SD_WEBUI_RESTARTING ', '1') + os.environ.setdefault('SD_WEBUI_RESTARTING', '1') except OSError: pass @@ -354,7 +354,7 @@ def prepare_environment(): if not os.path.isfile(requirements_file): requirements_file = os.path.join(script_path, requirements_file) - if not requrements_met(requirements_file): + if not requirements_met(requirements_file): run_pip(f"install -r \"{requirements_file}\"", "requirements") run_extensions_installers(settings_file=args.ui_settings_file) diff --git a/webui.py b/webui.py index 2aafc09f..2314735f 100644 --- a/webui.py +++ b/webui.py @@ -407,7 +407,7 @@ def webui(): ssl_verify=cmd_opts.disable_tls_verify, debug=cmd_opts.gradio_debug, auth=gradio_auth_creds, - inbrowser=cmd_opts.autolaunch and os.getenv('SD_WEBUI_RESTARTING ') != '1', + inbrowser=cmd_opts.autolaunch and os.getenv('SD_WEBUI_RESTARTING') != '1', prevent_thread_lock=True, allowed_paths=cmd_opts.gradio_allowed_path, app_kwargs={ -- cgit v1.2.3 From 16eddc622e6d091f51d22269742afddc9b6d0f4b Mon Sep 17 00:00:00 2001 From: Jabasukuriputo Wang Date: Fri, 21 Jul 2023 22:00:03 +0800 Subject: prepend the pythonpath instead of overriding it --- modules/launch_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules/launch_utils.py') diff --git a/modules/launch_utils.py b/modules/launch_utils.py index 609a181e..231ebc5f 100644 --- a/modules/launch_utils.py +++ b/modules/launch_utils.py @@ -190,7 +190,7 @@ def run_extension_installer(extension_dir): try: env = os.environ.copy() - env['PYTHONPATH'] = os.path.abspath(".") + env['PYTHONPATH'] = f"{os.path.abspath('.')}{os.pathsep}{env['PYTHONPATH']}" print(run(f'"{python}" "{path_installer}"', errdesc=f"Error running install.py for extension {extension_dir}", custom_env=env)) except Exception as e: -- cgit v1.2.3 From 90eb731ff1d73fdc5872ff9682d5c88c9737ba38 Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Sat, 22 Jul 2023 12:21:05 +0300 Subject: start timer early anyway --- launch.py | 3 --- modules/launch_utils.py | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'modules/launch_utils.py') diff --git a/launch.py b/launch.py index 114466cf..d46e9e27 100644 --- a/launch.py +++ b/launch.py @@ -1,6 +1,5 @@ from modules import launch_utils - args = launch_utils.args python = launch_utils.python git = launch_utils.git @@ -26,8 +25,6 @@ start = launch_utils.start def main(): - from modules import timer - timer.startup_timer.record("start") if not args.skip_prepare_environment: prepare_environment() diff --git a/modules/launch_utils.py b/modules/launch_utils.py index aaa671ab..18b444d4 100644 --- a/modules/launch_utils.py +++ b/modules/launch_utils.py @@ -10,6 +10,7 @@ from functools import lru_cache from modules import cmd_args, errors from modules.paths_internal import script_path, extensions_dir +from modules import timer # noqa:F401 args, _ = cmd_args.parser.parse_known_args() -- cgit v1.2.3 From 2a7e34fe79c82ac264919be8965b8d51afa32ac1 Mon Sep 17 00:00:00 2001 From: Jabasukuriputo Wang Date: Sat, 22 Jul 2023 18:09:00 +0800 Subject: fix https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/11921#issuecomment-1646547908 --- modules/launch_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules/launch_utils.py') diff --git a/modules/launch_utils.py b/modules/launch_utils.py index 18b444d4..0c863e4a 100644 --- a/modules/launch_utils.py +++ b/modules/launch_utils.py @@ -194,7 +194,7 @@ def run_extension_installer(extension_dir): try: env = os.environ.copy() - env['PYTHONPATH'] = f"{os.path.abspath('.')}{os.pathsep}{env['PYTHONPATH']}" + env['PYTHONPATH'] = f"{os.path.abspath('.')}{os.pathsep}{env.get('PYTHONPATH')}" print(run(f'"{python}" "{path_installer}"', errdesc=f"Error running install.py for extension {extension_dir}", custom_env=env)) except Exception as e: -- cgit v1.2.3 From 3c26734d603560f57f7a145eed6cbdd50d20379c Mon Sep 17 00:00:00 2001 From: Jabasukuriputo Wang Date: Sat, 22 Jul 2023 18:33:59 +0800 Subject: nop --- modules/launch_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules/launch_utils.py') diff --git a/modules/launch_utils.py b/modules/launch_utils.py index 0c863e4a..c61edb36 100644 --- a/modules/launch_utils.py +++ b/modules/launch_utils.py @@ -194,7 +194,7 @@ def run_extension_installer(extension_dir): try: env = os.environ.copy() - env['PYTHONPATH'] = f"{os.path.abspath('.')}{os.pathsep}{env.get('PYTHONPATH')}" + env['PYTHONPATH'] = f"{os.path.abspath('.')}{os.pathsep}{env.get('PYTHONPATH', '')}" print(run(f'"{python}" "{path_installer}"', errdesc=f"Error running install.py for extension {extension_dir}", custom_env=env)) except Exception as e: -- cgit v1.2.3 From c76a30af41e50932847230631d26bfa9635ebd62 Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Sat, 22 Jul 2023 13:49:29 +0300 Subject: more info for startup timings --- launch.py | 6 ++++-- modules/launch_utils.py | 26 +++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 5 deletions(-) (limited to 'modules/launch_utils.py') diff --git a/launch.py b/launch.py index d46e9e27..e4c2ce99 100644 --- a/launch.py +++ b/launch.py @@ -25,9 +25,11 @@ start = launch_utils.start def main(): + launch_utils.startup_timer.record("initial startup") - if not args.skip_prepare_environment: - prepare_environment() + with launch_utils.startup_timer.subcategory("prepare environment"): + if not args.skip_prepare_environment: + prepare_environment() if args.test_server: configure_for_tests() diff --git a/modules/launch_utils.py b/modules/launch_utils.py index 18b444d4..0178e1b0 100644 --- a/modules/launch_utils.py +++ b/modules/launch_utils.py @@ -10,7 +10,7 @@ from functools import lru_cache from modules import cmd_args, errors from modules.paths_internal import script_path, extensions_dir -from modules import timer # noqa:F401 +from modules.timer import startup_timer args, _ = cmd_args.parser.parse_known_args() @@ -224,8 +224,10 @@ def run_extensions_installers(settings_file): if not os.path.isdir(extensions_dir): return - for dirname_extension in list_extensions(settings_file): - run_extension_installer(os.path.join(extensions_dir, dirname_extension)) + with startup_timer.subcategory("run extensions installers"): + for dirname_extension in list_extensions(settings_file): + run_extension_installer(os.path.join(extensions_dir, dirname_extension)) + startup_timer.record(dirname_extension) re_requirement = re.compile(r"\s*([-_a-zA-Z0-9]+)\s*(?:==\s*([-+_.a-zA-Z0-9]+))?\s*") @@ -298,8 +300,11 @@ def prepare_environment(): if not args.skip_python_version_check: check_python_version() + startup_timer.record("checks") + commit = commit_hash() tag = git_tag() + startup_timer.record("git version info") print(f"Python {sys.version}") print(f"Version: {tag}") @@ -307,21 +312,27 @@ def prepare_environment(): if args.reinstall_torch or not is_installed("torch") or not is_installed("torchvision"): run(f'"{python}" -m {torch_command}', "Installing torch and torchvision", "Couldn't install torch", live=True) + startup_timer.record("install torch") if not args.skip_torch_cuda_test and not check_run_python("import torch; assert torch.cuda.is_available()"): raise RuntimeError( 'Torch is not able to use GPU; ' 'add --skip-torch-cuda-test to COMMANDLINE_ARGS variable to disable this check' ) + startup_timer.record("torch GPU test") + if not is_installed("gfpgan"): run_pip(f"install {gfpgan_package}", "gfpgan") + startup_timer.record("install gfpgan") if not is_installed("clip"): run_pip(f"install {clip_package}", "clip") + startup_timer.record("install clip") if not is_installed("open_clip"): run_pip(f"install {openclip_package}", "open_clip") + startup_timer.record("install open_clip") if (not is_installed("xformers") or args.reinstall_xformers) and args.xformers: if platform.system() == "Windows": @@ -335,8 +346,11 @@ def prepare_environment(): elif platform.system() == "Linux": run_pip(f"install -U -I --no-deps {xformers_package}", "xformers") + startup_timer.record("install xformers") + if not is_installed("ngrok") and args.ngrok: run_pip("install ngrok", "ngrok") + startup_timer.record("install ngrok") os.makedirs(os.path.join(script_path, dir_repos), exist_ok=True) @@ -346,22 +360,28 @@ def prepare_environment(): git_clone(codeformer_repo, repo_dir('CodeFormer'), "CodeFormer", codeformer_commit_hash) git_clone(blip_repo, repo_dir('BLIP'), "BLIP", blip_commit_hash) + startup_timer.record("clone repositores") + if not is_installed("lpips"): run_pip(f"install -r \"{os.path.join(repo_dir('CodeFormer'), 'requirements.txt')}\"", "requirements for CodeFormer") + startup_timer.record("install CodeFormer requirements") if not os.path.isfile(requirements_file): requirements_file = os.path.join(script_path, requirements_file) if not requirements_met(requirements_file): run_pip(f"install -r \"{requirements_file}\"", "requirements") + startup_timer.record("install requirements") run_extensions_installers(settings_file=args.ui_settings_file) if args.update_check: version_check(commit) + startup_timer.record("check version") if args.update_all_extensions: git_pull_recursive(extensions_dir) + startup_timer.record("update extensions") if "--exit" in sys.argv: print("Exiting because of --exit argument") -- cgit v1.2.3 From a8d4213317c6970aa3ca8cbeeaacb07b936b591c Mon Sep 17 00:00:00 2001 From: AUTOMATIC1111 <16777216c@gmail.com> Date: Sat, 22 Jul 2023 17:08:45 +0300 Subject: add --log-startup option to print detailed startup progress --- modules/cmd_args.py | 1 + modules/launch_utils.py | 7 +++++-- modules/timer.py | 23 +++++++++++++++++++---- 3 files changed, 25 insertions(+), 6 deletions(-) (limited to 'modules/launch_utils.py') diff --git a/modules/cmd_args.py b/modules/cmd_args.py index e401f641..dd5fadc4 100644 --- a/modules/cmd_args.py +++ b/modules/cmd_args.py @@ -13,6 +13,7 @@ parser.add_argument("--reinstall-xformers", action='store_true', help="launch.py parser.add_argument("--reinstall-torch", action='store_true', help="launch.py argument: install the appropriate version of torch even if you have some version already installed") parser.add_argument("--update-check", action='store_true', help="launch.py argument: check for updates at startup") parser.add_argument("--test-server", action='store_true', help="launch.py argument: configure server for testing") +parser.add_argument("--log-startup", action='store_true', help="launch.py argument: print a detailed log of what's happening at startup") parser.add_argument("--skip-prepare-environment", action='store_true', help="launch.py argument: skip all environment preparation") parser.add_argument("--skip-install", action='store_true', help="launch.py argument: skip installation of packages") parser.add_argument("--do-not-download-clip", action='store_true', help="do not download CLIP model even if it's not included in the checkpoint") diff --git a/modules/launch_utils.py b/modules/launch_utils.py index c9e4344b..f77b577a 100644 --- a/modules/launch_utils.py +++ b/modules/launch_utils.py @@ -226,8 +226,11 @@ def run_extensions_installers(settings_file): with startup_timer.subcategory("run extensions installers"): for dirname_extension in list_extensions(settings_file): - run_extension_installer(os.path.join(extensions_dir, dirname_extension)) - startup_timer.record(dirname_extension) + path = os.path.join(extensions_dir, dirname_extension) + + if os.path.isdir(path): + run_extension_installer(path) + startup_timer.record(dirname_extension) re_requirement = re.compile(r"\s*([-_a-zA-Z0-9]+)\s*(?:==\s*([-+_.a-zA-Z0-9]+))?\s*") diff --git a/modules/timer.py b/modules/timer.py index da99e49f..1d38595c 100644 --- a/modules/timer.py +++ b/modules/timer.py @@ -1,4 +1,5 @@ import time +import argparse class TimerSubcategory: @@ -11,20 +12,27 @@ class TimerSubcategory: def __enter__(self): self.start = time.time() self.timer.base_category = self.original_base_category + self.category + "/" + self.timer.subcategory_level += 1 + + if self.timer.print_log: + print(f"{' ' * self.timer.subcategory_level}{self.category}:") def __exit__(self, exc_type, exc_val, exc_tb): elapsed_for_subcategroy = time.time() - self.start self.timer.base_category = self.original_base_category self.timer.add_time_to_record(self.original_base_category + self.category, elapsed_for_subcategroy) - self.timer.record(self.category) + self.timer.subcategory_level -= 1 + self.timer.record(self.category, disable_log=True) class Timer: - def __init__(self): + def __init__(self, print_log=False): self.start = time.time() self.records = {} self.total = 0 self.base_category = '' + self.print_log = print_log + self.subcategory_level = 0 def elapsed(self): end = time.time() @@ -38,13 +46,16 @@ class Timer: self.records[category] += amount - def record(self, category, extra_time=0): + def record(self, category, extra_time=0, disable_log=False): e = self.elapsed() self.add_time_to_record(self.base_category + category, e + extra_time) self.total += e + extra_time + if self.print_log and not disable_log: + print(f"{' ' * self.subcategory_level}{category}: done in {e + extra_time:.3f}s") + def subcategory(self, name): self.elapsed() @@ -71,6 +82,10 @@ class Timer: self.__init__() -startup_timer = Timer() +parser = argparse.ArgumentParser(add_help=False) +parser.add_argument("--log-startup", action='store_true', help="print a detailed log of what's happening at startup") +args = parser.parse_known_args()[0] + +startup_timer = Timer(print_log=args.log_startup) startup_record = None -- cgit v1.2.3