2014년 5월 6일 화요일

한줄 코딩 잘못이 1000배 느려진다.



한 줄 코딩 잘못이 1000배 느려진다. 무어의 법칙이라는 게 있다. 1965년 미국의 과학자 고든 무어는 '반도체 칩의 정보 기억량은 18~24개월 단위로 2배씩 증가하지만 가격은 변하지 않는다'라는 이론을 내 놓았다. 인텔 CPU의 경우 대충 맞아 떨어졌다. 우리는 PC가 구매후 2-3년 지나면 느리다고 새 PC로 교체한다. 약 두배 정도의 성능차이일 것이다. 내가 1980년 초에 IBM PC가 처음에 나왔을 때 64K 메모리에 하드디스크도 없고 360K 용량 플로피디스크로 사용하곤 했었다. 지금 보면 장난감이다. 지금까지 보면 무어의 법칙이 대충 맞아 떨어진다. 하드웨어에서는 성능상 큰 변화를 찾아보기 힘들다. 일년 사이에 열배가 변하겠는가? 백배가 변하겠는가 ?



DB에 관한 프로젝트를 하고 있었다. 큰 데이터를 로드시키는 프로그램을 팀원이 개발 했는데 너무 느린 것이었다. 조그만 데이터는 별 차이가 없는데 데이터가 커지면서 기하급수적으로 느려지는 것이었다. 한번 로드하고 테스트하는데 거의 하루가 걸리게 생겼다. 중간에 한번 잘못하면 그냥 하루를 손해본다. 한사람의 하루가 아니라 프로젝트종료가 하루가 지연되는 것이다. 컴퓨터가 성능이 안 좋으니 CPU빠르고 메모리 큰 것을 사용해야 하지 않겠느냐고 한다. 그러면 두세배는 향상될 것이다. 그러나 해결책은 아니었다. 그래서 내가 일단 소스코드를 분석해 보기로 했다. 자바코드였는데 다음과 같은 부분이 있었다. 자바를 모르더라도 프로그래밍을 해본 사람들은 금방 이해할 수 있을 것이다.
String str = “”;
while (…) {
   ...
   String message = getMessage();
   str = str + message;
   ...
}
return str;

이 보다는 훨씬 긴 프로그램이지만 관계 없는 부분은 생략했다. “while” 은 수만번정도 구동된다. 무엇이 문제이었을까? 운영체제나 컴파일러 같은 이론적인 배경이 없는 사람이면 찾기 힘든 문제일 수도 있다. 문제는 str + message 를 실행하기 위해서 str을 memory에 복사하게 되는데 수만번 도는 while 루프에서 str이 점점 길어지면서 memory에 복사하는데 많은 시간이 걸리는 것이었다. 이 문제를 해결하기 위해 다음과 같이 바꾸었다.
StringBuffer str = “”;

while (…) {
   ...
   String message = getMessage();
   str = str.append(message);
   ...
}
return str.toString;

여기서는 str.append(message)는 것을 사용하는데 이것은 memory에 복사를 하는 것이 아니라 기존의 String 뒤에 message를 붙이게 된다. 복사하는 과정이 없는 것이다. 이 한 줄을 이해 못함으로써 기하급수적으로 성능이 저하되는 것이다.



지금 경우처럼 심각하게 현상이 나타나면 문제점을 발견하고 해결책을 찾겠지만 만약 10배정도만 성능저하가 되었더라도 그런가 보다 하고 무시하고 넘어갔을 것이다. 컴퓨터 좋은 것 사달라고 할 것이다. 바보는 항상 남의 탓만 한다는 말도 있다. 잘못은 자기한테 있는데 엉뚱한데서 잘못을 찾는다. 이러한 무시되어서는 안 되는 문제가 수도 없이 존재하는 것이 현실이다. 내가 다른 사람이 쓴 소스코드를 보면 수많은 문제점을 즉시 찾아 낼 수 있다.

댓글 없음: