結論
環境変数で条件分岐させることで、提出時に削除不要かつ速度のオーバーヘッドを低く抑えることが可能です
import os
IS_ATCODER = bool(int(os.getenv("ATCODER", "0")))
def debug(*args, **kwargs) -> None:
if not IS_ATCODER:
print(*args, **kwargs)
for i in range(10 ** 7):
debug(i)
...
はじめに
競技プログラミングのデバッグはどのように行なっていますか?
最も簡単な方法はprintデバッグでしょう
for i in range(10 ** 7):
print(i)
...
しかしこの方法には大きな欠点があります。
それは、AtCoderに提出する際にprint文を削除する必要があり、削除を忘れるとWAを食らってしまいます。
stderr(標準エラー出力)
削除する必要がないデバッグ方法として、stderrも候補です
import sys
def debug(*args, **kwargs) -> None:
print(*args, **kwargs, file=sys.stderr)
for i in range(10 ** 7):
debug(i)
...
しかし、この方法も標準エラー出力にかかる時間がオーバーヘッドになるため、TLEになるリスクがあります。
環境変数で実行環境を判別して条件分岐
さて、AtCoderの環境には以下の環境変数が指定されています(言語には依らないと思いますが、Python (PyPy 3.10-v7.3.12)で調査しています。なお公式で明言されているわけではないと思うので、利用は自己責任でお願いします)
環境変数名 | 値 |
---|---|
PATH | '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' |
LANG | 'C.UTF-8' |
'ATCODER' | '1' |
'HOME' | '/home/runner' |
ちなみに、以下のコードで調べることができます
import os
print(os.environ)
この内、ATCODER
の値を取得することで、環境を判別することが可能です
import os
IS_ATCODER = bool(int(os.getenv("ATCODER", "0")))
def debug(*args, **kwargs) -> None:
if not IS_ATCODER:
print(*args, **kwargs)
for i in range(10 ** 7):
debug(i)
...
そして、この方法では標準エラー出力のようなI/Oが発生しないため、高速であることが期待できます
速度比較
実際に幾つかのコードで速度を比較してみました
1. デバッグなし
for i in range(10 ** 8):
a = i # ダミーの処理
2. stderrでデバッグ
import sys
def debug(*args, **kwargs) -> None:
print(*args, **kwargs, file=sys.stderr)
for i in range(10 ** 8):
a = i # ダミーの処理
debug("hello", a)
1より明らかに遅くなったことがわかります
3. 環境変数で条件分岐してデバッグ
import os
IS_ATCODER = bool(int(os.getenv("ATCODER", "0")))
def debug(*args, **kwargs) -> None:
if not IS_ATCODER:
print(*args, **kwargs)
for i in range(10 ** 8):
a = i # ダミーの処理
debug("hello", a)
2より圧倒的に高速で、1とほぼ同じ速度(+33ms)で処理することができました
4. 環境変数で条件分岐してデバッグ(改良)
ちなみに、lambda式にすると+2msまでオーバーヘッドを抑えることができました
import os
IS_ATCODER = bool(int(os.getenv("ATCODER", "0")))
debug = (lambda *args, **kwargs: None) if IS_ATCODER else print
for i in range(10 ** 8):
a = i # ダミーの処理
debug("hello", a)
個人的には、可読性を優先した3の書き方で良いと思いますが、とにかく速度を求めたい方はこちらでも良いでしょう
まとめ
ぜひ、ご活用ください。
それでは、よい競プロライフを!