online-judge-tools / verification-helper

a testing framework for snippet libraries used in competitive programming
MIT License
225 stars 54 forks source link

C++ コードのメタデータの取得の高速化 #286

Closed beet-aizu closed 3 years ago

beet-aizu commented 4 years ago

Description

ファイルが増えすぎてdoc生成に時間がかかっているので、なんとかしたい 少なくとも2分以上はかかっている https://github.com/beet-aizu/library/runs/1056546075?check_suite_focus=true#step:5:759

verify自体は1分もかかってないのにdoc生成に2分以上かかるというのは結構なストレス

Possible implementations and the analysis (optional)

https://github.com/online-judge-tools/verification-helper/blob/a7e7f235733fe6a56820e97dcee7692fe882b28a/onlinejudge_verify/verify.py#L139 https://github.com/online-judge-tools/verification-helper/blob/a7e7f235733fe6a56820e97dcee7692fe882b28a/onlinejudge_verify/docs.py#L471 この辺をいじって書き換えられる可能性のあるmdファイルだけビルドするようにすればマシになるはず

kmyk commented 4 years ago

よさそう。「大規模ライブラリで使うとしんどい」はよくないのでぜひたのむ

以下注意点など?

kmyk commented 3 years ago

これなんですけど、g++ に頼らずに普通に手で include の依存関係解析をやれば済む気がする。数百ファイル舐めるだけなら高速なはず

beet-aizu commented 3 years ago

プリプロセッサを書くってことですか(まあmdファイルの依存関係はg++に頼れないしそのほうが筋が良さそうではあります)

kmyk commented 3 years ago

はい、そうなります。まあファイル中の #include を列挙するだけだしすぐだと思います。oj-bundle の中でもすでにこれをしてる

ところで markdown まわりはもともと早いのであまり関係ないはずで、忘れたほうがよい。単純に C++ の依存関係解析部分が遅いだけのはず

beet-aizu commented 3 years ago

list_attributes が 1ファイルあたり 0.2 secくらい掛かっていて、300ファイル以上あるので遅いみたいです(g++は支配的ではなさそう)

beet-aizu commented 3 years ago

間違えて閉じてしまった

beet-aizu commented 3 years ago

_cplusplus_list_defined_macros が遅かったので、g++でした(special comment のドキュメントってどこにありますか)

beet-aizu commented 3 years ago

ここに C++ でも special comment を使えることを明記した方がよくないですか https://online-judge-tools.github.io/verification-helper/document.html

beet-aizu commented 3 years ago

special comment だと 0.001 sec とかなので全部置き換えようと思います

kmyk commented 3 years ago

@beet-aizu 実行速度のプロファイルをとったならその結果を貼っておいてほしい。今後の参考になるので

beet-aizu commented 3 years ago
lang: 5.0067901611328125e-06
is_verification: 1.9073486328125e-06
timestamp: 0.0002288818359375
attributes: 0.0003037452697753906
0.0006971359252929688 sec for /Users/beet/git-library/test/yosupo/discrete_logarithm_mod.test.cpp
lang: 5.245208740234375e-06
is_verification: 1.6689300537109375e-06
timestamp: 0.0002009868621826172
macros: 0.2337779998779297
attributes: 0.23436498641967773
0.2348179817199707 sec for /Users/beet/git-library/bbst/pb_ds_tree.cpp

macros の行が https://github.com/online-judge-tools/verification-helper/blob/2c42ce8b61d92ae30c9445f4a84f085827573883/onlinejudge_verify/languages/cplusplus.py#L158 で

sec for の行が https://github.com/online-judge-tools/verification-helper/blob/2c42ce8b61d92ae30c9445f4a84f085827573883/onlinejudge_verify/documentation/configure.py#L172 です

beet-aizu commented 3 years ago

https://github.com/beet-aizu/library/actions/runs/272183212  一分くらい縮みました language.list_attribute の中で verification_file ではない場合でも old-style のパーサー( https://github.com/online-judge-tools/verification-helper/blob/2c42ce8b61d92ae30c9445f4a84f085827573883/onlinejudge_verify/languages/cplusplus.py#L152 )が呼ばれていて遅い(0.2 sec * 202 files = 40 sec)みたいなんですが、場合分けを追加してもいいですか

beet-aizu commented 3 years ago

is_verification_file = false で old-style の special comments が必要になることはないと思っています

kmyk commented 3 years ago

language.list_attribute の中で verification_file ではない場合でも old-style のパーサー(…)が呼ばれていて遅い(0.2 sec * 202 files = 40 sec)みたいなんですが、場合分けを追加してもいいですか

よさそう。たのむ

kmyk commented 3 years ago

もし time module とかで手動で計測していたなら、ちゃんとしたプロファイラでの計測もしておくとよいかも

https://docs.python.org/ja/3/library/profile.html

例:

$ python3 -m cProfile -s cumtime -- $(which oj-verify) run | head -n 100
INFO:onlinejudge_verify.config:no config file
INFO:onlinejudge_verify.verify:all tests succeeded
         1131554 function calls (1107824 primitive calls) in 4.408 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
   1552/1    0.020    0.000    4.410    4.410 {built-in method builtins.exec}
        1    0.000    0.000    4.410    4.410 oj-verify:3(<module>)
        1    0.000    0.000    3.280    3.280 main.py:204(main)
        2    0.000    0.000    3.244    1.622 marker.py:134(get_verification_marker)
        1    0.000    0.000    3.244    3.244 marker.py:29(__init__)
        1    0.000    0.000    3.244    3.244 marker.py:82(load_timestamps)
       80    3.236    0.040    3.236    0.040 {method 'acquire' of '_thread.lock' objects}
        1    0.000    0.000    3.236    3.236 _base.py:610(__exit__)
        1    0.000    0.000    3.236    3.236 thread.py:146(shutdown)
        1    0.000    0.000    3.236    3.236 threading.py:1024(join)
        1    0.000    0.000    3.236    3.236 threading.py:1062(_wait_for_tstate_lock)
   1017/5    0.005    0.000    1.127    0.225 <frozen importlib._bootstrap>:966(_find_and_load)
   1017/5    0.004    0.000    1.126    0.225 <frozen importlib._bootstrap>:936(_find_and_load_unlocked)
    914/5    0.005    0.000    1.125    0.225 <frozen importlib._bootstrap>:651(_load_unlocked)
    813/4    0.002    0.000    1.124    0.281 <frozen importlib._bootstrap_external>:672(exec_module)
   1155/6    0.001    0.000    1.124    0.187 <frozen importlib._bootstrap>:211(_call_with_frames_removed)
        1    0.000    0.000    1.081    1.081 oj-verify:18(importlib_load_entry_point)
        1    0.000    0.000    1.076    1.076 __init__.py:99(load)
        1    0.000    0.000    1.076    1.076 __init__.py:108(import_module)
      2/1    0.000    0.000    1.076    1.076 <frozen importlib._bootstrap>:982(_gcd_import)
        1    0.000    0.000    1.076    1.076 main.py:3(<module>)
        2    0.000    0.000    0.686    0.343 main.py:1(<module>)
   481/82    0.001    0.000    0.541    0.007 {built-in method builtins.__import__}
        5    0.000    0.000    0.497    0.099 __init__.py:2(<module>)
        7    0.000    0.000    0.448    0.064 __init__.py:3(<module>)
       42    0.001    0.000    0.371    0.009 __init__.py:1(<module>)
3133/2097    0.003    0.000    0.337    0.000 <frozen importlib._bootstrap>:997(_handle_fromlist)
        1    0.000    0.000    0.328    0.328 build.py:2(<module>)
        1    0.000    0.000    0.326    0.326 __init__.py:16(<module>)
        1    0.000    0.000    0.323    0.323 list.py:1(<module>)
        1    0.000    0.000    0.296    0.296 python.py:2(<module>)
        1    0.000    0.000    0.292    0.292 graph.py:1(<module>)
        1    0.000    0.000    0.290    0.290 __init__.py:54(<module>)
     1245    0.006    0.000    0.274    0.000 re.py:286(_compile)
      422    0.000    0.000    0.272    0.001 re.py:231(compile)
        5    0.000    0.000    0.270    0.054 __init__.py:4(<module>)
      298    0.002    0.000    0.265    0.001 sre_compile.py:557(compile)
        2    0.000    0.000    0.248    0.124 __init__.py:3239(_call_aside)
        1    0.000    0.000    0.248    0.248 __init__.py:3256(_initialize_master_working_set)
        1    0.000    0.000    0.221    0.221 anarchygolf.py:4(<module>)
        3    0.000    0.000    0.221    0.074 __init__.py:15(<module>)
1607/1592    0.031    0.000    0.220    0.000 {built-in method builtins.__build_class__}
       30    0.001    0.000    0.205    0.007 __init__.py:610(add_entry)
      724    0.002    0.000    0.197    0.000 __init__.py:2047(find_on_path)
        1    0.000    0.000    0.159    0.159 element.py:2(<module>)
      298    0.001    0.000    0.146    0.000 sre_compile.py:542(_code)
        2    0.000    0.000    0.146    0.073 __init__.py:27(<module>)
        1    0.000    0.000    0.143    0.143 css_parser.py:1(<module>)
        1    0.000    0.000    0.135    0.135 intersection.py:4(<module>)
        1    0.000    0.000    0.135    0.135 dispatch.py:20(<module>)
 4301/298    0.030    0.000    0.129    0.000 sre_compile.py:64(_compile)
        2    0.000    0.000    0.121    0.060 __init__.py:41(<module>)
      813    0.006    0.000    0.121    0.000 <frozen importlib._bootstrap_external>:743(get_code)
        1    0.000    0.000    0.120    0.120 type.py:7(<module>)
     1392    0.004    0.000    0.115    0.000 __init__.py:2137(distributions_from_metadata)
      298    0.002    0.000    0.115    0.000 sre_parse.py:844(parse)
        1    0.000    0.000    0.108    0.108 __init__.py:568(_build_master)
        1    0.000    0.000    0.108    0.108 __init__.py:555(__init__)
 1584/299    0.008    0.000    0.107    0.000 sre_parse.py:407(_parse_sub)
 2317/314    0.037    0.000    0.106    0.000 sre_parse.py:470(_parse)
        1    0.000    0.000    0.094    0.094 css_parser.py:417(CSSParser)
        1    0.000    0.000    0.093    0.093 geometric.py:16(<module>)
       15    0.000    0.000    0.089    0.006 css_parser.py:294(__init__)
  982/980    0.008    0.000    0.088    0.000 <frozen importlib._bootstrap>:870(_find_spec)
      696    0.004    0.000    0.087    0.000 __init__.py:2587(from_location)
     2275    0.019    0.000    0.083    0.000 <frozen importlib._bootstrap_external>:1233(find_spec)
  900/811    0.002    0.000    0.083    0.000 <frozen importlib._bootstrap>:564(module_from_spec)
      677    0.004    0.000    0.081    0.000 decorator.py:197(create)
      813    0.002    0.000    0.072    0.000 <frozen importlib._bootstrap_external>:485(_compile_bytecode)
      961    0.001    0.000    0.072    0.000 <frozen importlib._bootstrap_external>:1149(find_spec)
      961    0.004    0.000    0.071    0.000 <frozen importlib._bootstrap_external>:1117(_get_spec)
      813    0.069    0.000    0.069    0.000 {built-in method marshal.loads}
       39    0.003    0.000    0.065    0.002 {built-in method builtins.sorted}
       28    0.000    0.000    0.064    0.002 __init__.py:2021(_by_version_descending)
    66/43    0.000    0.000    0.059    0.001 <frozen importlib._bootstrap_external>:919(create_module)
    66/43    0.023    0.000    0.059    0.001 {built-in method _imp.create_dynamic}
        1    0.000    0.000    0.058    0.058 connectionpool.py:1(<module>)
    16207    0.023    0.000    0.058    0.000 enum.py:803(__and__)
        1    0.000    0.000    0.056    0.056 __init__.py:56(<module>)
        1    0.000    0.000    0.052    0.052 __init__.py:106(<module>)
      338    0.002    0.000    0.050    0.000 decorator.py:225(decorate)
      356    0.001    0.000    0.050    0.000 __init__.py:2991(_reload_version)
      677    0.007    0.000    0.050    0.000 decorator.py:162(make)
      356    0.000    0.000    0.049    0.000 __init__.py:2779(_get_version)
      356    0.001    0.000    0.048    0.000 __init__.py:2557(_version_from_file)
        1    0.000    0.000    0.048    0.048 css_parser.py:314(__init__)
     1361    0.001    0.000    0.047    0.000 {built-in method builtins.next}
      696    0.001    0.000    0.045    0.000 __init__.py:2036(_by_version)
     3104    0.017    0.000    0.044    0.000 version.py:217(__init__)
      317    0.000    0.000    0.043    0.000 __init__.py:3283(<genexpr>)
      316    0.001    0.000    0.042    0.000 __init__.py:2785(activate)
     1747    0.002    0.000    0.042    0.000 __init__.py:2774(_get_metadata)
      696    0.001    0.000    0.041    0.000 __init__.py:2042(<listcomp>)
        1    0.000    0.000    0.041    0.041 requirements.py:4(<module>)
        2    0.000    0.000    0.040    0.020 connection.py:1(<module>)
beet-aizu commented 3 years ago

before

Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
   1376/1    0.004    0.000  188.540  188.540 {built-in method builtins.exec}
        1    0.000    0.000  188.540  188.540 main.py:3(<module>)
        1    0.000    0.000  187.830  187.830 main.py:204(main)
        1    0.003    0.003  169.318  169.318 main.py:158(subcommand_docs)
        1    0.038    0.038  169.314  169.314 main.py:62(main)
        1    0.009    0.009  150.405  150.405 configure.py:180(generate_source_code_stats)
        1    0.032    0.032  100.135  100.135 configure.py:48(_build_dependency_graph)
     1092    0.029    0.000   97.837    0.090 cplusplus.py:189(list_dependencies)
      446    0.073    0.000   97.638    0.219 cplusplus.py:45(_cplusplus_list_depending_files)
      446    0.020    0.000   96.770    0.217 subprocess.py:332(check_call)
      446    0.039    0.000   96.749    0.217 subprocess.py:315(call)
     2430    0.023    0.000   95.734    0.039 subprocess.py:985(wait)
     2430    0.046    0.000   95.711    0.039 subprocess.py:1592(_wait)
     1215    0.026    0.000   95.656    0.079 subprocess.py:1579(_try_wait)
     1215   95.629    0.079   95.629    0.079 {built-in method posix.waitpid}
      769    0.035    0.000   53.739    0.070 subprocess.py:351(check_output)
      769    0.090    0.000   53.703    0.070 subprocess.py:431(run)
      769    0.050    0.000   51.325    0.067 subprocess.py:895(communicate)
     4848   51.223    0.011   51.223    0.011 {method 'read' of '_io.BufferedReader' objects}
      547    0.027    0.000   50.009    0.091 configure.py:132(_get_source_code_stat)
      546    0.027    0.000   47.377    0.087 cplusplus.py:144(list_attributes)
      230    0.651    0.003   47.053    0.205 cplusplus.py:66(_cplusplus_list_defined_macros)
        2    0.000    0.000   18.508    9.254 marker.py:134(get_verification_marker)
        1    0.000    0.000   18.508   18.508 marker.py:29(__init__)
        1    0.000    0.000   18.508   18.508 marker.py:82(load_timestamps)
        7   18.497    2.642   18.497    2.642 {method 'acquire' of '_thread.lock' objects}
        1    0.000    0.000   18.497   18.497 _base.py:610(__exit__)
        1    0.000    0.000   18.497   18.497 thread.py:198(shutdown)
        1    0.000    0.000   18.497   18.497 threading.py:1000(join)
        1    0.000    0.000   18.497   18.497 threading.py:1038(_wait_for_tstate_lock)
        1    0.049    0.049   18.436   18.436 build.py:155(render_pages)
      538    0.027    0.000   10.895    0.020 build.py:89(_render_source_code_stat_for_page)
      538    0.063    0.000   10.708    0.020 build.py:65(_render_source_code_stat)
      538    0.009    0.000   10.476    0.019 cplusplus.py:194(bundle)
 1129/538    0.287    0.000   10.461    0.019 cplusplus_bundle.py:260(update)
     1129    0.142    0.000    8.756    0.008 cplusplus_bundle.py:191(get_uncommented_code)
      538    0.015    0.000    8.206    0.015 cplusplus_bundle.py:177(_get_uncommented_code)
      540    0.007    0.000    7.405    0.014 front_matter.py:30(merge_front_matter)
      540    0.005    0.000    7.397    0.014 __init__.py:300(safe_dump)
      540    0.022    0.000    7.391    0.014 __init__.py:252(dump_all)
      540    0.003    0.000    7.305    0.014 representer.py:26(represent)
      540    0.006    0.000    7.065    0.013 serializer.py:46(serialize)
41507/540    0.205    0.000    7.003    0.013 serializer.py:78(serialize_node)
    51658    0.102    0.000    6.663    0.000 emitter.py:111(emit)
    41507    0.102    0.000    5.693    0.000 emitter.py:232(expect_node)
    17991    0.023    0.000    5.202    0.000 emitter.py:409(expect_block_mapping_simple_value)
        2    0.000    0.000    4.357    2.178 python.py:78(list_dependencies)
        2    0.000    0.000    4.357    2.178 python.py:49(_python_list_depending_files)
        2    0.000    0.000    4.354    2.177 graph.py:212(create)
        2    0.004    0.002    4.334    2.167 graph.py:89(add_file_recursive)
      296    0.008    0.000    4.319    0.015 graph.py:236(get_file_deps)
      296    0.003    0.000    4.157    0.014 parsepy.py:76(get_imports)
      296    0.066    0.000    4.149    0.014 import_finder.py:137(get_imports)
     1215    0.173    0.000    3.302    0.003 subprocess.py:656(__init__)
     1215    0.170    0.000    3.097    0.003 subprocess.py:1383(_execute_child)
    33516    0.051    0.000    2.971    0.000 emitter.py:266(expect_scalar)
825840/296    0.499    0.000    2.888    0.010 ast.py:258(visit)
823856/296    1.181    0.000    2.887    0.010 ast.py:264(generic_visit)
    33516    0.045    0.000    2.883    0.000 emitter.py:515(process_scalar)
    33516    2.220    0.000    2.698    0.000 emitter.py:626(analyze_scalar)
    41507    0.046    0.000    2.558    0.000 emitter.py:469(process_tag)
    33516    0.044    0.000    2.507    0.000 emitter.py:494(choose_scalar_style)
      547    0.010    0.000    2.496    0.005 marker.py:35(get_current_timestamp)
     1080    1.828    0.002    2.438    0.002 emitter.py:926(write_double_quoted)
     1215    1.355    0.001    1.355    0.001 {built-in method _posixsubprocess.fork_exec}
     1215    1.329    0.001    1.329    0.001 {built-in method posix.read}
     1206    1.301    0.001    1.301    0.001 {built-in method builtins.compile}
    15181    0.079    0.000    1.177    0.000 pathlib.py:1136(resolve)
14853714/14805320    1.146    0.000    1.163    0.000 {built-in method builtins.len}
      296    0.001    0.000    1.031    0.003 ast.py:30(parse)
   575870    0.262    0.000    0.894    0.000 re.py:170(match)
    21651    0.041    0.000    0.882    0.000 emitter.py:395(expect_block_mapping_key)
   778/96    0.003    0.000    0.760    0.008 <frozen importlib._bootstrap>:978(_find_and_load)
   777/96    0.002    0.000    0.758    0.008 <frozen importlib._bootstrap>:948(_find_and_load_unlocked)
    15181    0.077    0.000    0.755    0.000 pathlib.py:311(resolve)
   638/18    0.002    0.000    0.739    0.041 <frozen importlib._bootstrap>:663(_load_unlocked)
   590/17    0.002    0.000    0.738    0.043 <frozen importlib._bootstrap_external>:722(exec_module)
   855/38    0.000    0.000    0.738    0.019 <frozen importlib._bootstrap>:211(_call_with_frames_removed)
  2040230    0.480    0.000    0.679    0.000 ast.py:172(iter_fields)
  4136394    0.599    0.000    0.601    0.000 {built-in method builtins.isinstance}
    15181    0.139    0.000    0.582    0.000 pathlib.py:315(_resolve)
   577959    0.295    0.000    0.549    0.000 re.py:271(_compile)
    40987    0.094    0.000    0.523    0.000 pathlib.py:633(_parse_args)
  979/903    0.003    0.000    0.514    0.001 {built-in method builtins.__import__}
        5    0.000    0.000    0.490    0.098 __init__.py:3(<module>)
    17991    0.075    0.000    0.471    0.000 emitter.py:437(check_simple_key)
  2061554    0.428    0.000    0.428    0.000 {built-in method builtins.getattr}
    75234    0.040    0.000    0.424    0.000 pathlib.py:435(readlink)
    40986    0.217    0.000    0.404    0.000 pathlib.py:62(parse_parts)
    24120    0.045    0.000    0.402    0.000 pathlib.py:653(_from_parts)
    75236    0.384    0.000    0.384    0.000 {built-in method posix.readlink}
  2019123    0.368    0.000    0.368    0.000 {method 'startswith' of 'str' objects}
beet-aizu commented 3 years ago

after

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
   1376/1    0.006    0.000  158.871  158.871 {built-in method builtins.exec}
        1    0.000    0.000  158.871  158.871 main.py:3(<module>)
        1    0.000    0.000  157.830  157.830 main.py:204(main)
        1    0.003    0.003  139.683  139.683 main.py:158(subcommand_docs)
        1    0.063    0.063  139.680  139.680 main.py:62(main)
        1    0.003    0.003  117.186  117.186 configure.py:180(generate_source_code_stats)
        1    0.033    0.033  106.596  106.596 configure.py:48(_build_dependency_graph)
     1092    0.026    0.000  101.938    0.093 cplusplus.py:189(list_dependencies)
      446    0.079    0.000  101.735    0.228 cplusplus.py:45(_cplusplus_list_depending_files)
      446    0.017    0.000  100.818    0.226 subprocess.py:332(check_call)
      446    0.042    0.000  100.799    0.226 subprocess.py:315(call)
     2026    0.021    0.000   99.697    0.049 subprocess.py:985(wait)
     2026    0.063    0.000   99.676    0.049 subprocess.py:1592(_wait)
     1013    0.011    0.000   99.605    0.098 subprocess.py:1579(_try_wait)
     1013   99.594    0.098   99.594    0.098 {built-in method posix.waitpid}
        1    0.053    0.053   21.936   21.936 build.py:155(render_pages)
        2    0.000    0.000   18.144    9.072 marker.py:134(get_verification_marker)
        1    0.000    0.000   18.143   18.143 marker.py:29(__init__)
        1    0.000    0.000   18.143   18.143 marker.py:82(load_timestamps)
        7   18.130    2.590   18.130    2.590 {method 'acquire' of '_thread.lock' objects}
        1    0.000    0.000   18.130   18.130 _base.py:610(__exit__)
        1    0.000    0.000   18.130   18.130 thread.py:198(shutdown)
        1    0.000    0.000   18.130   18.130 threading.py:1000(join)
        1    0.000    0.000   18.130   18.130 threading.py:1038(_wait_for_tstate_lock)
      567    0.029    0.000   15.995    0.028 subprocess.py:351(check_output)
      567    0.081    0.000   15.965    0.028 subprocess.py:431(run)
      567    0.054    0.000   14.236    0.025 subprocess.py:895(communicate)
     4646   14.153    0.003   14.153    0.003 {method 'read' of '_io.BufferedReader' objects}
      538    0.031    0.000   12.756    0.024 build.py:89(_render_source_code_stat_for_page)
      538    0.073    0.000   12.533    0.023 build.py:65(_render_source_code_stat)
      538    0.010    0.000   12.252    0.023 cplusplus.py:194(bundle)
 1129/538    0.353    0.000   12.233    0.023 cplusplus_bundle.py:260(update)
      547    0.013    0.000   10.207    0.019 configure.py:132(_get_source_code_stat)
     1129    0.157    0.000   10.082    0.009 cplusplus_bundle.py:191(get_uncommented_code)
      538    0.017    0.000    9.443    0.018 cplusplus_bundle.py:177(_get_uncommented_code)
      540    0.009    0.000    9.024    0.017 front_matter.py:30(merge_front_matter)
      540    0.006    0.000    9.014    0.017 __init__.py:300(safe_dump)
      540    0.027    0.000    9.008    0.017 __init__.py:252(dump_all)
      540    0.004    0.000    8.907    0.016 representer.py:26(represent)
      540    0.008    0.000    8.593    0.016 serializer.py:46(serialize)
41103/540    0.252    0.000    8.516    0.016 serializer.py:78(serialize_node)
    51254    0.122    0.000    8.101    0.000 emitter.py:111(emit)
      546    0.012    0.000    7.206    0.013 cplusplus.py:144(list_attributes)
        2    0.000    0.000    7.106    3.553 python.py:78(list_dependencies)
        2    0.000    0.000    7.106    3.553 python.py:49(_python_list_depending_files)
        2    0.000    0.000    7.102    3.551 graph.py:212(create)
        2    0.006    0.003    7.071    3.536 graph.py:89(add_file_recursive)
      296    0.014    0.000    7.048    0.024 graph.py:236(get_file_deps)
    41103    0.120    0.000    6.923    0.000 emitter.py:232(expect_node)
       28    0.100    0.004    6.917    0.247 cplusplus.py:66(_cplusplus_list_defined_macros)
      296    0.004    0.000    6.774    0.023 parsepy.py:76(get_imports)
      296    0.108    0.000    6.761    0.023 import_finder.py:137(get_imports)
    17789    0.028    0.000    6.340    0.000 emitter.py:409(expect_block_mapping_simple_value)
825840/296    0.841    0.000    4.812    0.016 ast.py:258(visit)
823856/296    1.940    0.000    4.809    0.016 ast.py:264(generic_visit)
    33112    0.059    0.000    3.590    0.000 emitter.py:266(expect_scalar)
    33112    0.054    0.000    3.485    0.000 emitter.py:515(process_scalar)
    33112    2.724    0.000    3.308    0.000 emitter.py:626(analyze_scalar)
    41103    0.056    0.000    3.140    0.000 emitter.py:469(process_tag)
    33112    0.052    0.000    3.078    0.000 emitter.py:494(choose_scalar_style)
     1080    2.210    0.002    2.957    0.003 emitter.py:926(write_double_quoted)
      547    0.006    0.000    2.896    0.005 marker.py:35(get_current_timestamp)
     1013    0.141    0.000    2.734    0.003 subprocess.py:656(__init__)
     1013    0.168    0.000    2.564    0.003 subprocess.py:1383(_execute_child)
     1206    1.980    0.002    1.980    0.002 {built-in method builtins.compile}
      296    0.001    0.000    1.632    0.006 ast.py:30(parse)
14291267/14242873    1.336    0.000    1.354    0.000 {built-in method builtins.len}
    14979    0.088    0.000    1.343    0.000 pathlib.py:1136(resolve)
  2040230    0.795    0.000    1.146    0.000 ast.py:172(iter_fields)
   575870    0.322    0.000    1.134    0.000 re.py:170(match)
     1013    1.129    0.001    1.129    0.001 {built-in method posix.read}
   778/96    0.005    0.000    1.120    0.012 <frozen importlib._bootstrap>:978(_find_and_load)
   777/96    0.004    0.000    1.117    0.012 <frozen importlib._bootstrap>:948(_find_and_load_unlocked)
   638/18    0.004    0.000    1.087    0.060 <frozen importlib._bootstrap>:663(_load_unlocked)
   855/38    0.001    0.000    1.086    0.029 <frozen importlib._bootstrap>:211(_call_with_frames_removed)
   590/17    0.003    0.000    1.085    0.064 <frozen importlib._bootstrap_external>:722(exec_module)
    21449    0.049    0.000    1.061    0.000 emitter.py:395(expect_block_mapping_key)
     1013    1.049    0.001    1.049    0.001 {built-in method _posixsubprocess.fork_exec}
  4119718    0.860    0.000    0.862    0.000 {built-in method builtins.isinstance}
    14979    0.068    0.000    0.854    0.000 pathlib.py:311(resolve)
  2061352    0.731    0.000    0.731    0.000 {built-in method builtins.getattr}
   577959    0.381    0.000    0.680    0.000 re.py:271(_compile)
    14979    0.153    0.000    0.672    0.000 pathlib.py:315(_resolve)
  979/903    0.005    0.000    0.635    0.001 {built-in method builtins.__import__}
    40583    0.106    0.000    0.607    0.000 pathlib.py:633(_parse_args)
        1    0.000    0.000    0.573    0.573 main.py:1(<module>)
        5    0.000    0.000    0.571    0.114 __init__.py:3(<module>)
    17789    0.087    0.000    0.570    0.000 emitter.py:437(check_simple_key)
    74198    0.046    0.000    0.497    0.000 pathlib.py:435(readlink)
    40582    0.254    0.000    0.473    0.000 pathlib.py:62(parse_parts)
    23716    0.046    0.000    0.467    0.000 pathlib.py:653(_from_parts)
    74200    0.451    0.000    0.451    0.000 {built-in method posix.readlink}
beet-aizu commented 3 years ago
      230    0.651    0.003   47.053    0.205 cplusplus.py:66(_cplusplus_list_defined_macros)
       28    0.100    0.004    6.917    0.247 cplusplus.py:66(_cplusplus_list_defined_macros)

切り出し

kmyk commented 3 years ago

残るボトルネックは全体 140 秒中の 100 秒を占めてる _cplusplus_list_depending_files ですね。

        1    0.063    0.063  139.680  139.680 main.py:62(main)
        1    0.003    0.003  139.683  139.683 main.py:158(subcommand_docs)
        1    0.003    0.003  117.186  117.186 configure.py:180(generate_source_code_stats)
        1    0.033    0.033  106.596  106.596 configure.py:48(_build_dependency_graph)
      446    0.079    0.000  101.735    0.228 cplusplus.py:45(_cplusplus_list_depending_files)

これも同様に #include <...> を Python で自前で解析すれば速くなるはずです。たぶん 100 秒が 10 秒くらいになるんじゃないかな。 「#include "..."#include <...> の差は扱えますか?」とか「CXXFLAGS がカスタマイズされてるときの include パスはどうなるの?」などの面倒要素はあるのだけど、oj-bundle みたいに「#include <...> は無視します。CXXFLAGS も無視します」でやってしまえば十分だと思っています。

kmyk commented 3 years ago

ところでやっぱりドキュメント関係なかったのでタイトルを更新

kmyk commented 3 years ago

「g++ をしてるのが遅さの原因で、// verification-helper: [KEY] [VALUE] って書けば解決する」で結論が出ているはず。これがドキュメントには書かれてないのはでよくないのだけど、この issue はとりあえず閉じておきます。