2021-11-26 21:00 작성
트래픽 구하기
정의
로그 데이터를 분석해 초당 최대 처리량을 계산하는 문제를 계산해 보자. 초당 최대 처리량은 요청의 응답 완료 여부에 관계없이 임의 시간부터 1초(=1,000밀리초)간 처리하는 요청의 최대 개수를 의미한다.
예시
- 입력:
["2016-09-15 01:00:04.002 2.0s", "2016-09-15 01:00:07.000 2s"]
- 출력:
2
- 설명: 처리시간은 시작시간과 끝시간을 포함하므로 첫 번째 로그는 01:00:02.003 ~ 01:00:04.002에서 2초 동안 처리되었으며, 두 번째 로그는 01:00:05.001 ~ 01:00:07.000에서 2초 동안 처리된다. 따라서, 첫 번째 로그가 끝나는 시점과 두 번째 로그가 시작하는 시점의 구간인 01:00:04.002 ~ 01:00:05.001 1초 동안 최대 2개가 된다.
테스트
["2016-09-15 00:00:00.000 3s"]
기댓값:1
["2016-09-15 23:59:59.999 0.001s"]
기댓값:1
["2016-09-15 01:00:04.001 2.0s", "2016-09-15 01:00:07.000 2s"]
기댓값:1
["2016-09-15 01:00:04.002 2.0s", "2016-09-15 01:00:07.000 2s"]
기댓값:2
["2016-09-15 20:59:57.421 0.351s", "2016-09-15 20:59:58.233 1.181s", "2016-09-15 20:59:58.299 0.8s", "2016-09-15 20:59:58.688 1.041s", "2016-09-15 20:59:59.591 1.412s", "2016-09-15 21:00:00.464 1.466s", "2016-09-15 21:00:00.741 1.581s", "2016-09-15 21:00:00.748 2.31s", "2016-09-15 21:00:00.966 0.381s", "2016-09-15 21:00:02.066 2.62s"]
기댓값:7
["2016-09-15 00:00:00.000 2.3s", "2016-09-15 23:59:59.999 0.1s"]
기댓값:1
설계
기준점을 어떻게 잡을 것인가?
- 시간 단위로 쪼갤 수 있다면 시간이나 데이터 순서 관계 없이 추려낼 수 있을 듯 함. (기준 시간 값을 정하기 어려움, 매 시간마다 n의 데이터 값을 검사해야 함)
- 정확한 데이터를 얻기 위해서는 각 로그의 시작점과 끝점에서 1초 기간의 간격 동안 얼마나 많은 데이터가 겹치는지 확인하는 방법이 있음. 예를 들어 시작점 + 1s, 끝점 + 1s 간격에서 겹치는 수를 확인
function solution(lines) {
var answer = throughput_per_second(lines);
return answer;
}
function throughput_per_second(lines) {
// 초당 최대 처리량
let tps = 1;
if (lines.length === 1) {
tps = 1;
return tps;
} else if (lines.length === 0) {
tps = 0;
return tps;
}
for (let i = 0; i < lines.length; i++) {
// 기준별 초당 최대 처리량
let sub_tps = 1;
let start_tps = 1;
let end_tps = 1;
// 응답완료시간 구간 (시작점, 끝점)
const { start, end } = find_log_section(lines[i]);
let i_start = start;
let i_end = end;
for (let k = i + 1; k < lines.length; k++) {
// 응답완료시간 구간 (시작점, 끝점)
const k_log_section = find_log_section(lines[k]);
let k_start = k_log_section.start;
let k_end = k_log_section.end;
// console.log("is+1: ", i_start + 1, "ie+1: ", i_end + 1);
// 1. 시작점과 같거나 +1의 범위(0~1)에서 시작되는 경우 - 끝점도 동일
// 2. 더 앞쪽에서 시작되어 비교값의 끝점이 시작점에서 끝나는 경우 (같거나) - 끝점도 동일
// 3. 더 앞쪽에서 시작되어 시작점 +1보다 같거나 작은 범위에서 끝나는 경우 (클 경우) - 끝점도 동일
// 4. 더 앞쪽에서 시작되어 시작점 +1보다 큰 범위에서 끝나는 경우 (클 경우) - 끝점도 동일
if (k_start >= i_start && k_start <= i_start + 0.998) {
// console.log("start 구간 들어옴.");
start_tps++;
} else if (k_start < i_start && k_end >= i_start) {
// console.log("start 구간 들어옴.");
start_tps++;
}
//console.log("t or f? ", i_end + 1, k_end);
if (k_start >= i_end && k_start <= i_end + 0.998) {
// console.log("end 구간 들어옴.");
end_tps++;
} else if (k_start < i_end && k_end >= i_end) {
// console.log("end 구간 들어옴.");
end_tps++;
}
}
// 구간 tps 최대값이 기존의 tps 값을 초과할 경우 저장
sub_tps = start_tps > end_tps ? start_tps : end_tps;
tps = tps > sub_tps ? tps : sub_tps;
}
return tps;
}
function find_log_section(log) {
// Log 시작점, 끝점
let start_point = 0;
let end_point = 0;
// 정규표현식
const regex = /[0-9]+:(.*)/;
const regex2 = /:/;
const regex3 = /(.*)[^s]/;
// 응답완료시간 S, 처리시간 T 분리
const str = regex.exec(log)[0];
const arr = str.split(" ");
// 응답완료시간 S
const s = arr[0].split(regex2);
const hours = parseFloat(s[0]);
const minutes = parseFloat(s[1]);
const seconds = parseFloat(s[2]);
end_point = hours * 60 * 60 + minutes * 60 + seconds;
// 처리시간 T
const t = parseFloat(regex3.exec(arr[1])[0]);
// 응답완료시간 시작 구간 계산
start_point =
end_point - t < 0 ? 0 : parseFloat((end_point - t).toFixed(3));
return { start: start_point, end: end_point };
}