애플리케이션 성능 개선
▼애플리케이션 성능 개선
★성능 측정 지표
처리량 : 주어진 시간에 처리할 수 있는 프로세스 처리수
응답 시간 : 데이터 입력 완료 시 부터 응답 출력이 개시될 떄까지의 시간
경과 시간: 입력한 시점부터 그 결과의 출력이 완료할 떄까지 걸리는 시간.
자원사용률 : 프로세스 처리 중 사용하는 CPU 사용량, 메모리 사용량, 네트워크 사용량.
★유형별 성능 분석 도구
성능/부하/스트레스 점검 도구: 측정 지표인 처리량, 응답 시간, 경과 시간 등을 점검하기위해 가상의 시스템 부하나 스트레스를 통해 성능을 분석하는 도구이다.
모니터링 도구: 성능 모니터링, 성능 저하 원인 분석, 시스템 부하량 분석, 장애 진단, 사용자 분석, 용량 산정 등의 기능을 통하여 애플리케이션 실행 시 자원 사용량을 확인하고 분석 가능한 도구이다.
★위험 감시
위험 요소 징후들에 대하여 계속적으로 인지하는 것이다.
★위험분석
프로젝트에 내재한 위험 요소를 인식하고 그 영향을 분석하여 이를 관리하는 활동으로서, 프로젝트를 성공시키기위하여 위험요소를 사전에 예측, 대비하는 모든 기술과 활동을 의미한다.
▼애플리케이션 성능 저하 원인
★데이터베이스 연결 및 쿼리 실행 시 발생되는 성능 저하 원인
DB Lock : 과도한 데이터 조회/ 업데이트/인덱스 생성시 발생한다. Lock의 해제시까지 대기하거나 처리되지못하고 종료된다.
불필요한 DB Fetch: 필요한 데이터보다 많은 대량의 데이터 요청이 들어올경우 발생한다. 결과 세트에서 마지막 위치로 커서를 옮기는 작업이 빈번한 경우 응답 시간 저하 현상이 발생한다.
연결누수: DB연결과 관련한 JDBC 객체를 사용후 종료하지 않을 경우 발생한다.
부적절한 : 커넥션 풀 크기가 너무 작거나 크게 설정한 경우 발생한다.
기타: 트렌젝션이 Commit 되지 않고 커넥션풀에 반환되거나 잘못 작성된 코드로 인해 불필요한 Commit가 자주 발생하는 경우 발생한다.
★내부 로직으로 인항 성능 저하 원인
웹 애플리케이션의 인터넷 접속 불량이나 대량의 파일로 인해 부하가 발생하는 경우이다.
정상적으로처리되지 않은 오류 처리로 인한 부하나 트랜잭션이 수행되는 동안 외부 트랜잭션(외부호출)이 장기간 수행되거나, 타입아웃이 일어나는 경우이다.
★잘못된 환경 설정이나 네트워크 문제로 인한 성능 저하 원인
환경 설정으로 인한 성능 저하: Tread Pool, Heap Memory의 크기를 너무 작게 설정하면 Heap Memory Full 현상이 발생한다.
네트워크 장비로 인한 성능 저하: 라우터, L4 스위치등 네트워크 관련 장비 간 데이터 전송 실패 또는 전송 지연에 따른 데이터 손실이 발생한다.
▼알고리즘
★알고리즘
주어진 과제를 해결하기 위한 방법과 절차를 의미한다. 알고리즘은 자연어, 의사코드, 순서도,프로그래밍 언어를 이용하여 표현가능하다.
★알고리즘 설계 기법
분할정복법(Divide & Conquer): 1805년, 나폴레옹이 오스트리아와 러시아의 동맹군을 격멸한 유명한 전투가 있다. ‘아우스터리츠 전투’라고 불리는 이 전투는, 프랑스의 병력 열세에도 불구하고, 오스트리아-러시아 동맹군을 반으로 분리시켜 각각을 정복함으로써 승리를 가져온 싸움이었다.
이러한 전술을 분할정복법(Divide & Conquer)이라고 하며, 이는 알고리즘 설계를 위해서도 유용하게 사용된다.좀 더 구체적으로 설명하면, 아래와 같다.
① 분할(Divide) : 정복이 필요한 과제를 분할이 가능한 부분까지 분할하고,
② 정복(Conquer) : ①에서 분할된 하위 과제들을 모두 해결(정복)한다.
③ 결합(Combine) : 그리고 ②에서 정복된 해답을 모두 취합(결합)한다.
이러한 설계기법을 응용하는 알고리즘은 대표적으로 퀵 정렬 알고리즘과 병합 정렬 알고리즘이 있다. 모두 분할과 정복의 응용을 통해 해법을 제시하는 알고리즘이다.
동적계획법(Dynamic Programming) : 동적계획법은 주어진 문제를 해결하기 위해 부분 문제에 대한 답을 계속적으로 활용해 나가는 기법이다.
① 부분문제로 나눈 후, ② 가장 낮은 단계의 부분문제 해답을 구하고, ③ 이 부분문제의 해답을 이용해 상위 부분문제를 해결해 나간다.
부분문제로 나누는 것에서 분할정복법(Divide & Conquer)과 비슷해 보일 수 있는데,
분할정복법이 큰 것을 잘게 잘라 다시 결합하는 Top-Down 방식이라면,
동적계획법은 작은 것의 해답을 이용하여 큰 것의 해답을 알아내는 Bottom-Up 방식이라고 할 수 있다.
동적계획법은 이전 단계의 해답을 활용하기 위해 반드시 기억할 수 있는 저장소가 필요하다.
따라서 속도는 빠르지만, 공간복잡도가 커지는 단점이 있다.
동적계획법을 사용할 수 있는 대표적인 예로 플로이드 알고리즘과 피보나치 수 알고리즘을 들 수 있으며,
플로이드 알고리즘의 경우, 모든 노드를 시작점으로 하여 모든 경우에 대해 후보해를 구하기 때문에 다익스트라와 달리 최적해를 구할 수 있다.
* 피보나치 수 알고리즘은 재귀호출(동적계획법) 뿐만 아니라, 분할정복법을 통해서도 구현 가능하다.
탐욕법(Greedy Method): 탐욕법은 동적계획법과 비슷하나, 전체를 보지 못하고 국소적인 관점에서 최적해를 구하는 기법이다.
따라서 최적해를 보장하지는 못하나, 어떤 경우에 최적해인지는 찾아낼 수 있다.
대표적인 응용 사례로 크루스칼 알고리즘과 다익스트라 알고리즘이 있으며,
배낭채우기나 선형계획법에 의해 자주 거론된다.
일반적인 경우, 목적함수와 선택집합, 제약조건 등을 사전에 고려하여야 하며,
최적해를 구하지는 못하나 동적계획법보다 효율적이라고 할 수 있다.
퇴각검색법(Backtracking): 퇴각검색법은 어떤 문제의 최적해를 구하기 위해 모든 가능성을 찾아가는 방법이다.
이름에서 알 수 있듯이 가던 길이 아니면 Back할 수 있다. 깊이우선탐색의 탐색 과정과 비슷하나,
깊이우선탐색이 모든 노드를 방문하는 것에 목적을 가지고 있다면, 퇴각검색법은 최적해를 찾는 것이 목적이기 때문에 최적해를 찾으면 더 이상 다른 노드를 방문할 필요가 없다.
대표적으로 N-Queen 문제 해결 시에 응용 되며, 동적계획법과 같이 기억할 저장소를 필요로 한다.
분기한정법(Branch & Bound): 분기한정법은 퇴각검색법과 유사하나, 임의로부터 답이 될 것 같은 부분을 먼저 탐색한다는 차이를 가지고 있다. 즉 정해진 범위(Bound)를 벗어나는 값들은 가지치기(Branch) 해가며 결과값을 추적해 나가는 것이다.
대표적인 응용 사례로 최적우선탐색(best First Search) 알고리즘과 A* 알고리즘이 있으며,
일부에서는 퇴각검색법의 개선된 형태로 분류하기도 한다.
근사해법(Approximation Algoritm): 근사해법은 일반적으로 풀 수 있는 문제가 아닌, 복잡도가 매우 높은 문제에 대해 가장 근사치의 값을 구하는 기법이다.
다항식 시간에 풀기 어렵다고 판단되는 문제를 NP-Hard 문제라고 하는데,
이 NP-Hard 문제를 해결하기 위해, 주어진 시간에 최적해에 가장 가까운 답을 찾는 결정성 알고리즘을 구현하는 기법이다. 이렇게 구현된 알고리즘을 근사 알고리즘이라고 하며, 시간복잡도, 공간복잡도, 정밀도를 척도로 평가된다.
★시간 복잡도
알고리즘의 실행시간, 즉 알고리즘을 수행하기 위해 프로세스가 수행하는 연산 횟수를 수치화 한것으로 시간이 아닌 명령어의 실행횟수를 표기한 것이다.
점진적 표기법 구성
최상의 경우 : 오메가 표기법 (Big-Ω Notation)
평균의 경우 : 세타 표기법 (Big-θ Notation)
최악의 경우 : 빅오 표기법 (Big-O Notation)
세타 표기법을 사용하면 정확하고 좋지만 평가하기가 까다롭다.
일반적으론 최악의 경우인 빅오를 사용한다. 그 이유는 최악의 경우를 판단하여 예측하기 쉽기 때문이다.
★정렬 방식별 알고리즘 복잡도
★시간 복잡도에 따른 알고리즘
시간복잡도는 알고리즘이 문제를 해결하기위한 연산의 횟수를 의미한다. 시간복잡도를 고혀하는 것은 최적화를 위해 필요하다.
알고리즘의 소요 시간에 대한 정확한 평가는 어려워 자료의 수 n이 증가할 떄 시간이 증가하는 대략적인 패던을 의미한다.
▼Mccabe 순환 복잡도
★순환 복잡도
프로그램의 이해난이도는 제어 흐름 난이도의 복잡도에 따라 결정되며, 복잡도를 싸이클로메틱 개수에 의해서 산정하는 방법이다. 싸이클로메틱의 개수와원시 프로그램 오류의 개수는 밀접한 관계가 있다. 최대 10을 넘지 않도록 하며, 넘으면 이를 분해하도록 한다.
★복잡도 계산 방식
복잡도 = 화살표 수 - 노드수 + 2(흐름 그래프를 통해 파악)
복잡도 = 영역 수(폐구간) +1(제어 흐름 그래프를 통해 파악)
복잡도 = 의사 결정수 + 조건 수 + 1(프로그램 코드상에서 파악, 제어 프름도를 그리기 어려운 경우 활용)