[JavaScript] 실행 시간 측정 - Date, console.time(), performance.now()
자바스크립트에서 실행 시간을 측정하는 것은 코드의 성능을 평가하고 최적화하는 데 도움이 된다.
이를 통해 어떤 부분이 느린지 파악하고, 개선이 필요한 부분을 찾아낼 수 있다.
프로그래머스로 문제를 풀다보니 실행 시간을 측정하고 싶어서 방법이 없을까 생각하다보니 몇 가지 방법을 알게 되었다.
크게
- Date
- console.time()과 console.timeEnd()
- performance.now()
를 활용하는 세 가지 방법이 있다.
Date
Date 객체는 1970년 1월 1일 UTC(협정 세계시) 자정과의 시간 차이를 밀리초로 나타내는 정수 값을 담고 있다.
이를 활용하여 시작 시각과 종료 시각의 차를 계산할 수 있다.
const start = new Date(); // 시작
function solution(value) {
// 내용
}
// 함수 실행
console.log(solution(value));
const end = new Date(); // 끝
const executionTime = end - start;
console.log("Execution time: " + executionTime + " milliseconds"); // 출력
한편 일반적인 사칙 연산을 사용하면 Date 객체는 숫자로 자동으로 변환되어 연산되는 것을 알 수 있다.
// 현재 일시
let date1 = new Date();
console.log(`date1, ${date1}`);
console.log(typeof(date1)) // date1의 데이터타입
// 1초 후에 date2 생성
setTimeout(() => {
let date2 = new Date();
console.log(`date2, ${date2}`);
console.log(`date2 - date1, ${date2 - date1}`) // 경과시간
console.log(typeof(date2 - date1)) // (date2 - date1)의 데이터타입
}, 1000);
하지만 MDN의 문서를 살펴보면 자바스크립트로 경과시간을 계산하는 방식으로는 Date.now()와 getTime() 메소드를 사용하는 것을 알 수 있다. 두 가지 메소드 모두 숫자값을 리턴한다.
- Date.now() : UTC 기준으로 1970년 1월 1일 0시 0분 0초부터 현재까지 경과된 밀리초(숫자)를 반환하는 메서드
- Date.prototype.getTime() : 표준시에 따라 지정된 날짜의 시간에 해당하는 숫자 값을 반환하는 메서드
Date.now()
Date.now()는 UTC 기준으로 1970년 1월 1일 0시 0분 0초부터 현재까지 경과된 밀리초(숫자)를 반환한다.
// Date.now()
// 현재 일시
let start = Date.now();
console.log(`start, ${start}`);
console.log(typeof(start)) // start의 데이터타입
// 1초 후에 end 생성
setTimeout(() => {
let end = Date.now();
console.log(`end, ${end}`);
console.log(`end - start, ${end - start}`) // 경과시간
console.log(typeof(end - start)) // (end - start)의 데이터타입
}, 1000);
Date.prototype.getTime()
getTime() 메서드는 표준시에 따라 지정된 날짜의 시간에 해당하는 숫자 값을 반환한다.
// getTime
// 현재 일시
let start = new Date();
console.log(`start, ${start}`);
console.log(typeof(start)) // start의 데이터타입
// 1초 후에 end 생성
setTimeout(() => {
let end = new Date();
console.log(`end, ${end}`);
console.log(`end - start, ${end.getTime() - start.getTime()}`) // 경과시간
console.log(typeof(end - start)) // (end - start)의 데이터타입
}, 1000);
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Date
Date - JavaScript | MDN
JavaScript Date 객체는 시간의 한 점을 플랫폼에 종속되지 않는 형태로 나타냅니다. Date 객체는 1970년 1월 1일 UTC(협정 세계시) 자정과의 시간 차이를 밀리초로 나타내는 정수 값을 담습니다.
developer.mozilla.org
https://developer.mozilla.org/ko/docs/Web/API/setTimeout
setTimeout() - Web API | MDN
전역 setTimeout() 메서드는 만료된 후 함수나 지정한 코드 조각을 실행하는 타이머를 설정합니다.
developer.mozilla.org
console.time(), console.timeEnd()
console.time()
주어진 이름의 타이머를 실행한다.
하나의 페이지에서는 최대 10,000개의 타이머를 동시에 실행할 수 있다.
console.time(label); // label 안에 타이머 이름이 들어감
console.timeEnd()
지정한 타이머를 멈추고, 소요시간을 출력한다.
변수 선언 없이 출력만 하면 된다.
console.time('executionTime'); // 시작
function solution(value) {
// 내용
}
// 함수 실행
console.log(solution(value));
console.timeEnd('executionTime'); // 끝
// console.time()
console.time('Timer') // 현재 시각
// 1초 후에 end 생성
setTimeout( () => {
console.timeEnd('Timer') // 소요 시간
}, 1000);
time과 timeEnd 안에 있는 타이머 이름이 같아야만 정상적으로 출력된다.
// console.time()
// 타이머 이름을 다르게 지정한 경우
console.time('good') // 현재 시각
// 1초 후에 end 생성
setTimeout( () => {
console.timeEnd('Timer') // 소요 시간
}, 1000);
https://developer.mozilla.org/ko/docs/Web/API/console
console - Web API | MDN
console 객체는 브라우저의 디버깅 콘솔(Firefox 웹 콘솔 등)에 접근할 수 있는 메서드를 제공합니다. 동작 방식은 브라우저마다 다르지만, 사실상 표준으로 여겨지는 기능도 여럿 있습니다.
developer.mozilla.org
performance.now()
브라우저에서 제공하는 성능 측정을 위한 메서드 중 하나이다.
현재 시각을 나타내는 타임스탬프를 반환한다.
기본 단위는 밀리초(1/1000 초)이며, 부동 소수점 숫자로 나타낸다.
https://developer.mozilla.org/en-US/docs/Web/API/Performance
Performance - Web APIs | MDN
The Performance interface provides access to performance-related information for the current page.
developer.mozilla.org
const start = performance.now(); // 시작
function solution(value) {
// 내용
}
// 함수 실행
console.log(solution(value));
const end = performance.now(); // 끝
console.log("Execution time: " + (end - start) + " milliseconds"); // 출력
밀리초의 단위가 정밀하게 나오는 걸 확인할 수 있다.
// performance.now()
const start = performance.now() // 현재 시각
// 1초 후에 end 생성
setTimeout( () => {
const end = performance.now()
const elapsed = end - start
console.log(elapsed) // 소요 시간
}, 1000);
Math.round를 활용하여 소수점 둘째자리까지 출력하도록 하였다.
// console.time()
const start = performance.now() // 현재 시각
// 1초 후에 end 생성
setTimeout( () => {
const end = performance.now()
const elapsed = end - start
console.log(Math.round(elapsed * 100) / 100) // 소요 시간 (둘째자리까지)
}, 1000);
함수 실행시간이 반영된 코드
평균 20ms가 나온다.
함수 실행시간이 반영되지 않은 코드
평균 0.02ms가 나온다.
0.02 밀리 초와 20 밀리 초(0.02초)는 1000배 차이가 난다.
프로그래머스에서 함수 실행 시간 측정
const start = performance.now(); // 시작
function solution(my_string) {
const vowels = ["a", "e", "i", "o", "u"]
var answer = '';
// 문자열 split('')으로 배열로 만들기
// 모음에 해당하는 원소는 넣지 않기
answer = my_string.split('').filter(a => !vowels.includes(a)).join('');
return answer;
}
const end = performance.now(); // 끝
console.log("Execution time: " + (end - start) + " milliseconds"); // 출력
함수 실행하는 코드 밑에 end 변수와 출력 코드가 나와야 한다.
실행 순서가 바뀐 코드(0.023ms)와 프로그래머스의 코드 실행 시간(0.002ms)이 비슷하다.
→ 프로그래머스에서 출력을 할 때 실행 코드가 가장 밑부분에 있다는 것을 알 수 있다.
그러므로 위와 같은 방식으로 함수 실행을 측정하는 것이 불가능하다.
좋은 방법이 있는지 알아봐야겠다.