diff options
author | Alexandru Croitor <alexandru.croitor@qt.io> | 2019-09-30 18:16:20 +0200 |
---|---|---|
committer | Tobias Hunger <tobias.hunger@qt.io> | 2019-10-01 14:14:16 +0000 |
commit | f23b7e1476ded2be43d5e3f03195f522d307b163 (patch) | |
tree | 76c5fa3d2de29fbbedc01a6647198b6f123fbaa6 /util | |
parent | 590213e531f3a14f9b5365a10122f815d5fd6e8f (diff) |
Implement persistent caching for simplify_condition
Store the results of simplify_condition in a json cache file,
next to the pro2cmake.py script.
Dramatically speeds up re-conversion of projects.
The cache is cleared whenever the content of the
condition_simplifier.py file changes, effectively presuming that the
condition computing code has changed.
Sample times.
Initial corelib.pro conversion - 142.13 seconds.
Next re-conversion with hot cache - 1.17 seconds.
Change-Id: I8790b2736358236e4b23bcb5f10f45a36fdfa426
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Reviewed-by: Qt CMake Build Bot
Diffstat (limited to 'util')
-rw-r--r-- | util/cmake/condition_simplifier.py | 3 | ||||
-rw-r--r-- | util/cmake/condition_simplifier_cache.py | 113 |
2 files changed, 115 insertions, 1 deletions
diff --git a/util/cmake/condition_simplifier.py b/util/cmake/condition_simplifier.py index c67b78ffad..de329be1d4 100644 --- a/util/cmake/condition_simplifier.py +++ b/util/cmake/condition_simplifier.py @@ -29,8 +29,8 @@ import re - from sympy import simplify_logic, And, Or, Not, SympifyError +from condition_simplifier_cache import simplify_condition_memoize def _iterate_expr_tree(expr, op, matches): @@ -160,6 +160,7 @@ def _recursive_simplify(expr): return expr +@simplify_condition_memoize def simplify_condition(condition: str) -> str: input_condition = condition.strip() diff --git a/util/cmake/condition_simplifier_cache.py b/util/cmake/condition_simplifier_cache.py new file mode 100644 index 0000000000..b405ef23f8 --- /dev/null +++ b/util/cmake/condition_simplifier_cache.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 +############################################################################# +## +## Copyright (C) 2018 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the plugins of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + + +import atexit +import hashlib +import json +import os +import sys +import time + +from typing import Callable + + +def get_current_file_path() -> str: + try: + this_file = __file__ + except NameError: + this_file = sys.argv[0] + this_file = os.path.abspath(this_file) + return this_file + + +def get_cache_location() -> str: + this_file = get_current_file_path() + dir_path = os.path.dirname(this_file) + cache_path = os.path.join(dir_path, ".pro2cmake_cache", "cache.json") + return cache_path + + +def get_file_checksum(file_path: str) -> str: + try: + with open(file_path, "r") as content_file: + content = content_file.read() + except IOError: + content = time.time() + checksum = hashlib.md5(content.encode("utf-8")).hexdigest() + return checksum + + +def get_condition_simplifier_checksum() -> str: + current_file_path = get_current_file_path() + dir_name = os.path.dirname(current_file_path) + condition_simplifier_path = os.path.join(dir_name, "condition_simplifier.py") + return get_file_checksum(condition_simplifier_path) + + +def init_cache_dict(): + return { + "checksum": get_condition_simplifier_checksum(), + "schema_version": "1", + "cache": {"conditions": {}}, + } + + +def simplify_condition_memoize(f: Callable[[str], str]): + cache_path = get_cache_location() + cache_file_content = None + + if os.path.exists(cache_path): + try: + with open(cache_path, "r") as cache_file: + cache_file_content = json.load(cache_file) + except (IOError, ValueError): + pass + + if not cache_file_content: + cache_file_content = init_cache_dict() + + current_checksum = get_condition_simplifier_checksum() + if cache_file_content["checksum"] != current_checksum: + cache_file_content = init_cache_dict() + + def update_cache_file(): + if not os.path.exists(cache_path): + os.makedirs(os.path.dirname(cache_path), exist_ok=True) + with open(cache_path, "w") as cache_file_write_handle: + json.dump(cache_file_content, cache_file_write_handle, indent=4) + + atexit.register(update_cache_file) + + def helper(condition: str) -> str: + if condition not in cache_file_content["cache"]["conditions"]: + cache_file_content["cache"]["conditions"][condition] = f(condition) + return cache_file_content["cache"]["conditions"][condition] + + return helper |