Search

GDB Time Checker

GDB 사용 도중 중단점과 중단점 사이의 시간을 체크해보고 싶었다.
GDB의 내장 파이썬을 사용해 진행하였다. (따라서 GDB가 파이썬을 지원하지 않는다면 필자가 서술하는 방법은 사용할 수 없다.)
최종 결과물은 다음과 같이 보여졌다.
확실히 어디 중단점 간의 시간이 가장 많이 걸렸는지 체크할 수 있었다.
우선 홈 디렉토리에 .gdbinit 파일을 생성한다
touch ~/.gdbinit
Python
필자는 걸린 시간을 좀 더 깔끔하게 표시하고 싶어 TrueType 폰트 기준 깔끔하게 표시해주는 함수를 하나 생성하였다. 아래 코드는 첫 번째 결과값의 사진처럼 내용물을 사각형으로 표시하기 위해 공백 및 파이프라인 ( | ) 문자를 추가해주는 함수이다.
# SET TIMEIT FUNCTION ================================================= python import time python line_str = "+=================================================+" python line_str_len = len(line_str) - 1 python def set_ti_line(ti_str, ed_len): ti_str_len = len(ti_str) for i in range(ti_str_len, ed_len): ti_str += ' ' if (ti_str_len < ed_len): ti_str += '|' return ti_str end
Python
이후 continue 전후로 실행 결과를 출력하는 define을 정의한다.
필자는 ‘c’로 설정하였다.
GDB의 continue의 약자가 c이기 때문에 해당 define을 설정하면 c 입력 시 continue가 동작되는 것이 아닌 define된 값이 동작하게 된다.
이것 이 싫다면 define value를 변경해주면 된다.
# define chktime define c python import time python start_time = 0 python end_time = 0 # python st = time.perf_counter() python start_time = time.time() continue python end_time = time.time() # python ed = time.perf_counter() # python print(f"time elapsed : {int(round((ed - st) * 1000))}ms") python dur_time = end_time - start_time python time_str = "| time elapsed : {:.3f} sec, {:.3f} ms".format(dur_time, (dur_time * 1000)) python time_str = set_ti_line(time_str, line_str_len) python print(line_str) python print(time_str) python print(line_str) python print("") end document c Time execution of next function Usage: c end # document chktime # Time execution of next function # Usage: chktime # end # =====================================================================
Python
설정 후 저장한다.
이후 gdb를 돌려 C 명령을 실행해보면 중단점 사이의 실행 시간을 획득할 수 있다.
아래와 같이 중단점을 4개 지정하였다.
중단점 별로 실행 시간이 출력된느 것을 확인할 수 있다.
.gdbinit 추가된 내용 정리
# .gdbinit 추가된 내용 정리 # SET TIMEIT FUNCTION ================================================= python import time python line_str = "+=================================================+" python line_str_len = len(line_str) - 1 python def set_ti_line(ti_str, ed_len): ti_str_len = len(ti_str) for i in range(ti_str_len, ed_len): ti_str += ' ' if (ti_str_len < ed_len): ti_str += '|' return ti_str end define c python import time python start_time = 0 python end_time = 0 # python st = time.perf_counter() python start_time = time.time() continue python end_time = time.time() # python ed = time.perf_counter() # python print(f"time elapsed : {int(round((ed - st) * 1000))}ms") python dur_time = end_time - start_time python time_str = "| time elapsed : {:.3f} sec, {:.3f} ms".format(dur_time, (dur_time * 1000)) python time_str = set_ti_line(time_str, line_str_len) python print(line_str) python print(time_str) python print(line_str) python print("") end document c Time execution of next function Usage: c end # =====================================================================
Python

해당 command를 VS Code로?

필자는 콘솔 GDB보다 주로 VS Code의 C/C++ 확장을 이용해 디버깅을 하는 관계로
해당 명령어를 VSCode에서도 사용하고 싶어졌다.
필자는 VS Code 확장을 만드는 능력은 없으므로 편법을 통하여 VS Code 디버그 콘솔에서 Continue하는 명령을 손수 지정하면 될 것 같았다.
아래 확장을 설치한다. (multi-command) macros 등 multi-command 를 지원하는 확장이라면 OK
settings.json을 열고 multi-commands 확장을 이용해 커스텀 명령어를 작성한다.
"multiCommand.commands": [ { "command": "multiCommand.continue_custom", "sequence": [ "workbench.debug.action.focusRepl", // "workbench.debug.action.toggleRepl", // snippet으로 명령을 삽입하기 전 기존 작성된 내용이 있다면 지운다. "editor.action.deleteLines", { "command": "editor.action.insertSnippet", "args": { // -exec가 들어가는 이유는 // C/C++ 확장에서 GDB 명령어를 직접 사용할 시 // 앞에 -exec를 붙여줘야 한다. // define 이름을 다르게 설정했을 경우 바꿔줘야 함 "snippet": "-exec c" } }, "repl.action.acceptInput" ] }, ]
JSON
이제 multiCommand.continue_custom 명령을 실행하게 되면 .gdbinit 에 적용시켰던 c define이 실행될 것이다.
아, keybindings.json을 열어 커스텀한 명령을 키바인딩 해주는 것도 잊지 않았다.
디버그 상태이며 중단점에 걸려있을 경우에만 alt + f1 키가 동작하도록 설정.
{ "key": "alt+f1", "command": "multiCommand.continue_custom", "when": "debugState == 'stopped'" },
JSON
alt + f1키를 눌렀을 때 gdb 콘솔창에서 duration time이 제대로 찍힌 것을 확인할 수 있었다.

번외

GDB define 작성 도중 특정 명령어 전/후로 명령어를 실행시킬 수 있는
hook, hookpost 명령이 존재하는 것을 새롭게 알게 되었다.
hook, hookpost 기능을 사용해 이렇게 명령어를 작성해서 시간을 체크해보려고 했다.
hook-continue로 continue 하기 전 start_time을 체크하고 hookpost-continue로 continue한 후 end_time을 체크해 걸린 시간을 파악하는 방식
# hook cannot check duration time. Async processing define hook-continue python start_time = 0 python end_time = 0 python start_time = time.time() end define hookpost-continue python end_time = time.time() python dur_time = end_time - start_time python time_str = "| time elapsed : {:.3f} sec, {:.3f} ms".format(dur_time, (dur_time * 1000)) python time_str = set_ti_line(time_str, line_str_len) python print(line_str) python print(time_str) python print(line_str) python print("") end
Python
그러나 아쉽게도 해당 명령어로는 제대로 된 시간 파악이 불가능하였다.
이유인즉슨 hook-continue로 continue 하기 전 start_time을 체크하는 것 까지는 좋았으나
hookpost 실행 시점이 continue 명령이 실행되어 다음 중단점에 걸려지고난 뒤 동작하는 것이 아니라 continue 명령이 실행되지마자 hookpost가 실행되는 방식이었다.
따라서 해당 방법으로는 다음 중단점까지의 실행 시간을 획득할 수 없었다.