추석 트래픽

문제

이번 추석에도 시스템 장애가 없는 명절을 보내고 싶은 어피치는 서버를 증설해야 할지 고민이다. 장애 대비용 서버 증설 여부를 결정하기 위해 작년 추석 기간인 9월 15일 로그 데이터를 분석한 후 초당 최대 처리량을 계산해보기로 했다. 초당 최대 처리량은 요청의 응답 완료 여부에 관계없이 임의 시간부터 1초(=1,000밀리초)간 처리하는 요청의 최대 개수를 의미한다.

1차답안

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import java.util.*;
import java.text.*;

class Solution {
public int solution(String[] lines) {

HashMap<Integer,Integer> seconds = new HashMap<Integer,Integer>();
String[] tmp = new String[3];
SimpleDateFormat transFormat = new SimpleDateFormat("HH:mm:ss.SSS");

try{
for(String line : lines){
tmp = line.split(" ");

String tmpDateStr = tmp[1];
String tmpDur = tmp[2].replace("s", "");
int tmpDurInt = (int) Double.parseDouble(tmpDur) * 1000;

// Str > Date
Date tmpDate = transFormat.parse(tmpDateStr);

// Date + Duration
int plusTmpInt = (int)tmpDate.getTime() + tmpDurInt;

//초는 getTime을 한값의 1000으로 나눈 수이기 떄문에 계산
int StarTime = (int) tmpDate.getTime()/1000;
int EndTime = plusTmpInt/1000;

for(int i = StarTime; i <= EndTime ; i++){
// 해당 Duration(기간 초단위) + 1 씩 해줘야함
seconds.put(i, seconds.getOrDefault(i, 0) + 1);
}
}
} catch(Exception e){
System.out.println(e.getMessage());
}

int max = 0;

for(int key : seconds.keySet()){
if(max < seconds.get(key)){
max = seconds.get(key);
}
}

return max;
}
}

1차시도 후 많은 테스트 케이스에서 실패하였다.

테스트 1 〉 실패 (39.45ms, 87.9MB)
테스트 2 〉 실패 (80.26ms, 88.2MB)
테스트 3 〉 실패 (59.44ms, 91.4MB)
테스트 7 〉 실패 (80.47ms, 90.7MB)
테스트 10 〉 실패 (31.42ms, 79.5MB)
테스트 12 〉 실패 (61.48ms, 84.5MB)
테스트 15 〉 실패 (23.44ms, 81.6MB)
테스트 18 〉 실패 (53.90ms, 101MB)

1초 단위로 끊는게 아니고 1초에 범위에서 가장많은 요청이 있는 내역을 찾는거니
해당 Duration내의 요청을 lines 개수만큼 반복해서 Max 값을 구하는 방식으로 바꿔야하는 것을 파악했다.
HashMap -> line 배열로 변경

2차 답안

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import java.util.*;
import java.text.*;

class Solution {
public int solution(String[] lines) {
String[] tmp = new String[3];
SimpleDateFormat transFormat = new SimpleDateFormat("HH:mm:ss.SSS");
Date[] endDate = new Date[lines.length];
Date[] startDate = new Date[lines.length];
int max = 0;

try{
for(int i = 0; i < lines.length ;i++){
tmp = lines[i].split(" ");

String tmpDateStr = tmp[1];
String tmpDur = tmp[2].replace("s", "");
int tmpDurInt = (int) (Double.parseDouble(tmpDur) * -1000);

endDate[i] = transFormat.parse(tmpDateStr);
startDate[i] = addTime(endDate[i], tmpDurInt + 1);
}
} catch(Exception e){
System.out.println(e.getMessage());
}

for(int i = 0; i < endDate.length; i++) {
int maxTemp = 0;
long endTimeMilliI = endDate[i].getTime();
long finTimeMilli = addTime(endDate[i], 1000).getTime();

for(int j = 0; j < startDate.length; j++) {
long startTimeMilli = startDate[j].getTime();
long endTimeMilliJ = endDate[j].getTime();
if((finTimeMilli - startTimeMilli) <= 0) {
continue;
}
if(((endTimeMilliI - startTimeMilli) <= 0 && (finTimeMilli - startTimeMilli) > 0)
|| ((endTimeMilliI - endTimeMilliJ) <= 0 && (finTimeMilli - endTimeMilliJ) > 0)
|| ((endTimeMilliI - startTimeMilli) > 0 && (endTimeMilliI - endTimeMilliJ) <= 0)) {
maxTemp++;
}
}
max = Math.max(max, maxTemp);
}

return max;
}

public Date addTime(Date date, int tmpDurInt) {
Calendar c = Calendar.getInstance();
c.setTime(date);
c.add(Calendar.MILLISECOND, tmpDurInt);
return c.getTime();
}
}