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

설계

기준점을 어떻게 잡을 것인가?

  1. 시간 단위로 쪼갤 수 있다면 시간이나 데이터 순서 관계 없이 추려낼 수 있을 듯 함. (기준 시간 값을 정하기 어려움, 매 시간마다 n의 데이터 값을 검사해야 함)
  2. 정확한 데이터를 얻기 위해서는 각 로그의 시작점과 끝점에서 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 };
}