[개발이야기] 내장 함수로 코드의 실행 시간 측정하기

"블루펭귄 개발 과정"

Posted by 예띠 on October 14, 2019

블루펭귄 개발 과정

주식회사 와들의 첫 iOS 앱인 블루펭귄을 개발하는 과정을 담은 글이다.

내장 함수로 코드의 실행 시간 측정하기

예띠님, 이거 진짜 7초 맞나요? 더 빨리 되는 것 같은데……”

나른한 가을 오후, 램프님과 쿠팡 제품 페이지를 크롤링하고 있었다. 제품의 상세 정보를 가져오는 코드를 짰다. 우리가 만든 파이썬 함수가 실행되는데 얼마나 걸리는지 알아보기 위해 함수의 처음과 끝에 내장 시간 함수를 실행했다. 한 개의 페이지를 분석하는 데 걸린 시간은 약 7초였다. 그런데, 크롬 드라이버가 브라우저를 켜고 끄는 그래픽이 워낙 현란했던지 램프님의 육안엔 더 적은 시간이 흐른 것처럼 보였던 것 같다. 결국, 램프님은 스톱와치를 켰다. 결과는 역시나 7초.

“저 살면서 언어에 내장된 시간 함수를 의심한 사람은 램프님이 처음이예요”

램프님의 귀여운 의심 이후 시간 함수에 대해 공부하기로 했다. 현재, 와들에서 개발 언어로 사용하고 있는 Python, Java, Swift의 시간 함수에 대해 알아보자.

  • Python
1
2
3
4
5
import time
start = time.time()
# parse_html()
end = time.time()
time_elapsed = end – start

Python에서는 time 모듈을 불러와서 time.time()을 실행하면 기준 시간으로부터 흐른 현재 시간을 부동 소수점 숫자로 알려준다. Python 3 Documentation에 따르면 기준 시간과 윤초를 어떻게 처리할지는 컴퓨터 OS마다 다르다고 한다. (The specific date of the epoch and the handling of leap seconds is platform dependent.) 윤초는 지구의 불규칙한 자전속도로 인해 세계시와 원자시 사이의 차이를 보정하기 위해 추가하는 1초이다.

  • Java
1
2
3
4
5
6
7
8
9
10
// check elapsed time with currentTimeMillis()
long beforeTimeMillis = System.currentTimeMillis();
parseHTML();
long afterTimeMillis = System.currentTimeMillis();
long secDiffTime = (afterTimeMillis - beforeTimeMillis) / 1000;

// check elapsed time with nanoTime()
long startNanoTime = System.nanoTime();
parseHTML();
long secDiffTime = (System.nanoTime() - startNanoTime) / 1000000000;

System 클래스는 Java에서 따로 불러올 필요없는 java.lang 패키지 안에 있다. System 은 두 가지 시간 함수를 제공한다. 하나는 currentTimeMillis()로 현재 시간과 1970년 1월 1일 오전 12시 (UTC)의 차를 밀리 초로 변환하여 알려주는 함수이다. Java API Document에 따르면, 밀리 초를 얼마나 세밀하게 측정할지는 컴퓨터 OS에 따라 다르다고 한다. (“the granularity of the value depends on the underlying operating system and may be larger.”)

다른 하나는 nanoTime()로 임의의 고정 시간에 대해 상대적인 현재 시간을 알려주는 함수이다. 이는 리턴값이 음수일 있음을 의미한다. 함수의 특성 상 하나의 JVM 내에서 시간 차이를 측정할 때만 사용할 수 있다. 이 함수는 나노초 단위의 정밀도를 제공하지만 나노 단위의 분해능을 가지고 있지는 않다. 분해능이 적어도 currentTimeMillis()만큼은 좋을 수는 있으나 그 이상을 보장하지는 않는다. (“This method provides nanosecond precision, but not necessarily nanosecond resolution (that is, how frequently the value changes) - no guarantees are made except that the resolution is at least as good as that of currentTimeMillis()”).

  • Swift
1
2
3
4
var start = CFAbsoluteTimeGetCurrent()
parseHTML()
var end = CFAbsoluteTimeGetCurrent()
var timeElapsed = end - start

Swift에서는 CFAbsoluteTimeGetCurrent() 함수로 시간을 측정할 수 있다. 현재 시간과 2001년 1월 1일 오전 12시 GMT의 차를 리턴하는데, 리턴값의 type alias는 CFAbsoluteTime이다.

코드를 분석할 때 Big-O 표기법을 통한 시간복잡도, 공간복잡도를 계산하는 것은 알고리즘의 효율성을 따지는 경우 편리하다. 하지만, 코드의 어떤 부분에서 시간이 지체되는지, 실제 기기에서의 속도가 어느 정도 될지 궁금할 때 내장 함수를 통해 시간을 측정하면 좋을 것이다.