mirror of
https://github.com/dashpay/dash.git
synced 2024-12-24 19:42:46 +01:00
perf: enable more multi-threading and caching in linters (#4807)
* perf: enable more multi-threading and caching in linters 20s -> 6s * ci: add multiprocess to ci dockerfile * Update test/lint/lint-cppcheck-dash.sh Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com> Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com>
This commit is contained in:
parent
ba4a7b1d07
commit
b421cfacae
6
.gitignore
vendored
6
.gitignore
vendored
@ -160,3 +160,9 @@ dist/
|
|||||||
*.background.tiff
|
*.background.tiff
|
||||||
|
|
||||||
/guix-build-*
|
/guix-build-*
|
||||||
|
|
||||||
|
# cppcheck cache-directory
|
||||||
|
.cppcheck/*
|
||||||
|
|
||||||
|
# flake8 cache location
|
||||||
|
.cache/*
|
||||||
|
@ -39,7 +39,8 @@ RUN pip3 install \
|
|||||||
jinja2 \
|
jinja2 \
|
||||||
pyzmq \
|
pyzmq \
|
||||||
vulture==2.3 \
|
vulture==2.3 \
|
||||||
yq
|
yq \
|
||||||
|
multiprocess
|
||||||
|
|
||||||
# dash_hash
|
# dash_hash
|
||||||
RUN git clone --depth 1 --no-tags https://github.com/dashpay/dash_hash
|
RUN git clone --depth 1 --no-tags https://github.com/dashpay/dash_hash
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
import re
|
import re
|
||||||
|
from multiprocess import Pool
|
||||||
|
|
||||||
MAPPING = {
|
MAPPING = {
|
||||||
'core_read.cpp': 'core_io.cpp',
|
'core_read.cpp': 'core_io.cpp',
|
||||||
@ -37,7 +38,7 @@ if __name__=="__main__":
|
|||||||
|
|
||||||
RE = re.compile("^#include <(.*)>")
|
RE = re.compile("^#include <(.*)>")
|
||||||
|
|
||||||
def handle_module(module):
|
def handle_module(arg):
|
||||||
module = module_name(arg)
|
module = module_name(arg)
|
||||||
if module is None:
|
if module is None:
|
||||||
print("Ignoring file %s (does not constitute module)\n" % arg)
|
print("Ignoring file %s (does not constitute module)\n" % arg)
|
||||||
@ -45,6 +46,26 @@ if __name__=="__main__":
|
|||||||
files[arg] = module
|
files[arg] = module
|
||||||
deps[module] = set()
|
deps[module] = set()
|
||||||
|
|
||||||
|
def handle_module2(module):
|
||||||
|
# Build the transitive closure of dependencies of module
|
||||||
|
closure = dict()
|
||||||
|
for dep in deps[module]:
|
||||||
|
closure[dep] = []
|
||||||
|
while True:
|
||||||
|
old_size = len(closure)
|
||||||
|
old_closure_keys = sorted(closure.keys())
|
||||||
|
for src in old_closure_keys:
|
||||||
|
for dep in deps[src]:
|
||||||
|
if dep not in closure:
|
||||||
|
closure[dep] = closure[src] + [src]
|
||||||
|
if len(closure) == old_size:
|
||||||
|
break
|
||||||
|
# If module is in its own transitive closure, it's a circular dependency; check if it is the shortest
|
||||||
|
if module in closure:
|
||||||
|
return [module] + closure[module]
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
# Iterate over files, and create list of modules
|
# Iterate over files, and create list of modules
|
||||||
for arg in sys.argv[1:]:
|
for arg in sys.argv[1:]:
|
||||||
@ -71,32 +92,20 @@ if __name__=="__main__":
|
|||||||
def shortest_c_dep():
|
def shortest_c_dep():
|
||||||
have_cycle = False
|
have_cycle = False
|
||||||
|
|
||||||
def handle_module(module, shortest_cycle):
|
sorted_keys = None
|
||||||
|
|
||||||
# Build the transitive closure of dependencies of module
|
|
||||||
closure = dict()
|
|
||||||
for dep in deps[module]:
|
|
||||||
closure[dep] = []
|
|
||||||
while True:
|
|
||||||
old_size = len(closure)
|
|
||||||
old_closure_keys = sorted(closure.keys())
|
|
||||||
for src in old_closure_keys:
|
|
||||||
for dep in deps[src]:
|
|
||||||
if dep not in closure:
|
|
||||||
closure[dep] = closure[src] + [src]
|
|
||||||
if len(closure) == old_size:
|
|
||||||
break
|
|
||||||
# If module is in its own transitive closure, it's a circular dependency; check if it is the shortest
|
|
||||||
if module in closure and (shortest_cycle is None or len(closure[module]) + 1 < len(shortest_cycle)):
|
|
||||||
shortest_cycle = [module] + closure[module]
|
|
||||||
|
|
||||||
return shortest_cycle
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
|
||||||
shortest_cycles = None
|
shortest_cycles = None
|
||||||
for module in sorted(deps.keys()):
|
if sorted_keys is None:
|
||||||
shortest_cycles = handle_module(module, shortest_cycles)
|
sorted_keys = sorted(deps.keys())
|
||||||
|
|
||||||
|
with Pool(8) as pool:
|
||||||
|
cycles = pool.map(handle_module2, sorted_keys)
|
||||||
|
|
||||||
|
for cycle in cycles:
|
||||||
|
if cycle is not None and (shortest_cycles is None or len(cycle) < len(shortest_cycles)):
|
||||||
|
shortest_cycles = cycle
|
||||||
|
|
||||||
if shortest_cycles is None:
|
if shortest_cycles is None:
|
||||||
break
|
break
|
||||||
@ -104,7 +113,8 @@ if __name__=="__main__":
|
|||||||
module = shortest_cycles[0]
|
module = shortest_cycles[0]
|
||||||
print("Circular dependency: %s" % (" -> ".join(shortest_cycles + [module])))
|
print("Circular dependency: %s" % (" -> ".join(shortest_cycles + [module])))
|
||||||
# And then break the dependency to avoid repeating in other cycles
|
# And then break the dependency to avoid repeating in other cycles
|
||||||
deps[shortest_cycles[-1]] = deps[shortest_cycles[-1]] - set([module])
|
deps[shortest_cycles[-1]] -= {module}
|
||||||
|
sorted_keys = None
|
||||||
have_cycle = True
|
have_cycle = True
|
||||||
|
|
||||||
if have_cycle:
|
if have_cycle:
|
||||||
|
@ -48,6 +48,8 @@ IGNORED_WARNINGS=(
|
|||||||
# "Consider using std::count_if algorithm instead of a raw loop."
|
# "Consider using std::count_if algorithm instead of a raw loop."
|
||||||
# "Consider using std::find_if algorithm instead of a raw loop."
|
# "Consider using std::find_if algorithm instead of a raw loop."
|
||||||
# "Member variable '.*' is not initialized in the constructor."
|
# "Member variable '.*' is not initialized in the constructor."
|
||||||
|
|
||||||
|
"unusedFunction"
|
||||||
)
|
)
|
||||||
|
|
||||||
# We should attempt to update this with all dash specific code
|
# We should attempt to update this with all dash specific code
|
||||||
@ -108,8 +110,14 @@ function join_array {
|
|||||||
ENABLED_CHECKS_REGEXP=$(join_array "|" "${ENABLED_CHECKS[@]}")
|
ENABLED_CHECKS_REGEXP=$(join_array "|" "${ENABLED_CHECKS[@]}")
|
||||||
IGNORED_WARNINGS_REGEXP=$(join_array "|" "${IGNORED_WARNINGS[@]}")
|
IGNORED_WARNINGS_REGEXP=$(join_array "|" "${IGNORED_WARNINGS[@]}")
|
||||||
FILES_REGEXP=$(join_array "|" "${FILES[@]}")
|
FILES_REGEXP=$(join_array "|" "${FILES[@]}")
|
||||||
|
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||||
|
CPPCHECK_DIR=$SCRIPT_DIR/.cppcheck/
|
||||||
|
if [ ! -d $CPPCHECK_DIR ]
|
||||||
|
then
|
||||||
|
mkdir $CPPCHECK_DIR
|
||||||
|
fi
|
||||||
WARNINGS=$(echo "${FILES}" | \
|
WARNINGS=$(echo "${FILES}" | \
|
||||||
xargs cppcheck --enable=all --inline-suppr -j "$(getconf _NPROCESSORS_ONLN)" --language=c++ --std=c++17 --template=gcc -D__cplusplus -DENABLE_WALLET -DCLIENT_VERSION_BUILD -DCLIENT_VERSION_IS_RELEASE -DCLIENT_VERSION_MAJOR -DCLIENT_VERSION_MINOR -DCLIENT_VERSION_REVISION -DCOPYRIGHT_YEAR -DDEBUG -DHAVE_WORKING_BOOST_SLEEP_FOR -DCHAR_BIT=8 -I src/ -q 2>&1 | sort -u | \
|
xargs cppcheck --enable=all --inline-suppr --cppcheck-build-dir=$CPPCHECK_DIR -j "$(getconf _NPROCESSORS_ONLN)" --language=c++ --std=c++17 --template=gcc -D__cplusplus -DENABLE_WALLET -DCLIENT_VERSION_BUILD -DCLIENT_VERSION_IS_RELEASE -DCLIENT_VERSION_MAJOR -DCLIENT_VERSION_MINOR -DCLIENT_VERSION_REVISION -DCOPYRIGHT_YEAR -DDEBUG -DHAVE_WORKING_BOOST_SLEEP_FOR -DCHAR_BIT=8 -I src/ -q 2>&1 | sort -u | \
|
||||||
grep -E "${ENABLED_CHECKS_REGEXP}" | \
|
grep -E "${ENABLED_CHECKS_REGEXP}" | \
|
||||||
grep -vE "${IGNORED_WARNINGS_REGEXP}" | \
|
grep -vE "${IGNORED_WARNINGS_REGEXP}" | \
|
||||||
grep -E "${FILES_REGEXP}")
|
grep -E "${FILES_REGEXP}")
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
from functools import partial
|
||||||
|
from multiprocessing import Pool
|
||||||
|
|
||||||
FALSE_POSITIVES = [
|
FALSE_POSITIVES = [
|
||||||
("src/batchedlogger.h", "strprintf(fmt, args...)"),
|
("src/batchedlogger.h", "strprintf(fmt, args...)"),
|
||||||
@ -261,6 +263,28 @@ def count_format_specifiers(format_string):
|
|||||||
return n
|
return n
|
||||||
|
|
||||||
|
|
||||||
|
def handle_filename(filename, args):
|
||||||
|
exit_code = 0
|
||||||
|
with open(filename, "r", encoding="utf-8") as f:
|
||||||
|
for function_call_str in parse_function_calls(args.function_name, f.read()):
|
||||||
|
parts = parse_function_call_and_arguments(args.function_name, function_call_str)
|
||||||
|
relevant_function_call_str = unescape("".join(parts))[:512]
|
||||||
|
if (f.name, relevant_function_call_str) in FALSE_POSITIVES:
|
||||||
|
continue
|
||||||
|
if len(parts) < 3 + args.skip_arguments:
|
||||||
|
exit_code = 1
|
||||||
|
print("{}: Could not parse function call string \"{}(...)\": {}".format(f.name, args.function_name, relevant_function_call_str))
|
||||||
|
continue
|
||||||
|
argument_count = len(parts) - 3 - args.skip_arguments
|
||||||
|
format_str = parse_string_content(parts[1 + args.skip_arguments])
|
||||||
|
format_specifier_count = count_format_specifiers(format_str)
|
||||||
|
if format_specifier_count != argument_count:
|
||||||
|
exit_code = 1
|
||||||
|
print("{}: Expected {} argument(s) after format string but found {} argument(s): {}".format(f.name, format_specifier_count, argument_count, relevant_function_call_str))
|
||||||
|
continue
|
||||||
|
return exit_code
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description="This program checks that the number of arguments passed "
|
parser = argparse.ArgumentParser(description="This program checks that the number of arguments passed "
|
||||||
"to a variadic format string function matches the number of format "
|
"to a variadic format string function matches the number of format "
|
||||||
@ -270,26 +294,12 @@ def main():
|
|||||||
parser.add_argument("function_name", help="function name (e.g. fprintf)", default=None)
|
parser.add_argument("function_name", help="function name (e.g. fprintf)", default=None)
|
||||||
parser.add_argument("file", nargs="*", help="C++ source code file (e.g. foo.cpp)")
|
parser.add_argument("file", nargs="*", help="C++ source code file (e.g. foo.cpp)")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
exit_code = 0
|
exit_codes = []
|
||||||
for filename in args.file:
|
|
||||||
with open(filename, "r", encoding="utf-8") as f:
|
with Pool(8) as pool:
|
||||||
for function_call_str in parse_function_calls(args.function_name, f.read()):
|
exit_codes = pool.map(partial(handle_filename, args=args), args.file)
|
||||||
parts = parse_function_call_and_arguments(args.function_name, function_call_str)
|
|
||||||
relevant_function_call_str = unescape("".join(parts))[:512]
|
sys.exit(max(exit_codes))
|
||||||
if (f.name, relevant_function_call_str) in FALSE_POSITIVES:
|
|
||||||
continue
|
|
||||||
if len(parts) < 3 + args.skip_arguments:
|
|
||||||
exit_code = 1
|
|
||||||
print("{}: Could not parse function call string \"{}(...)\": {}".format(f.name, args.function_name, relevant_function_call_str))
|
|
||||||
continue
|
|
||||||
argument_count = len(parts) - 3 - args.skip_arguments
|
|
||||||
format_str = parse_string_content(parts[1 + args.skip_arguments])
|
|
||||||
format_specifier_count = count_format_specifiers(format_str)
|
|
||||||
if format_specifier_count != argument_count:
|
|
||||||
exit_code = 1
|
|
||||||
print("{}: Expected {} argument(s) after format string but found {} argument(s): {}".format(f.name, format_specifier_count, argument_count, relevant_function_call_str))
|
|
||||||
continue
|
|
||||||
sys.exit(exit_code)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -88,7 +88,15 @@ elif PYTHONWARNINGS="ignore" flake8 --version | grep -q "Python 2"; then
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
PYTHONWARNINGS="ignore" flake8 --ignore=B,C,E,F,I,N,W --select=$(IFS=","; echo "${enabled[*]}")$(
|
FLAKECMD=flake8
|
||||||
|
|
||||||
|
if command -v flake8-cached > /dev/null; then
|
||||||
|
FLAKECMD=flake8-cached
|
||||||
|
else
|
||||||
|
echo "Consider install flake8-cached for cached flake8 results."
|
||||||
|
fi
|
||||||
|
|
||||||
|
PYTHONWARNINGS="ignore" $FLAKECMD --ignore=B,C,E,F,I,N,W --select=$(IFS=","; echo "${enabled[*]}")$(
|
||||||
if [[ $# == 0 ]]; then
|
if [[ $# == 0 ]]; then
|
||||||
git ls-files "*.py"
|
git ls-files "*.py"
|
||||||
else
|
else
|
||||||
|
Loading…
Reference in New Issue
Block a user