'Technical Note/SERVER PERFORMANCE'에 해당되는 글 14건

Technical Note/SERVER PERFORMANCE

- Facebook은 메모리 할당자를 jemalloc 을 써서 속도 향상을 얻었다.

- FreeBSD 운영체제 표준으로 도입


malloc의 중요성에 대한 재조명

- 최근 멀티 코어, 멀티 스레드 환경에서 동작하는 서버 프로그램에서 속도, 공간 효율성 측면이 더 중요해 지고 있다.

- 속도 : 리눅스에 기본으로 들어있는 glibc malloc의 경우 스레드 8개 이상을 돌리기 시작하면 최고 성능의 60% 수준으로 떨어져 버린다. 

- 공간 효율성 : 오랜 시간 영역을 할당 받고 해제하더라고 큰 면적을 잘 보존하는  malloc 이 더욱 중요해 졌음


jemalloc 기술적 특성

- arena : 

- thread cache

Technical Note/SERVER PERFORMANCE

보통 swap 파티션은 물리적 메모리 크기의 2배로 잡습니다.

swap 파티션은 물리적 메모리를 보조해 주는 역할을 합니다.

프로그램을 수행할 때는 프로그램이 메모리에 적재되어 실행이 됩니다.

메모리에 적재된 프로그램을 프로세스라고 하구요 ^^

프로그램을 많이 돌리면 프로세스의 양이 많아지게 되고

프로세스의 양이 많아지면 메모리 사용가능 용량은 점점 작아지게 됩니다.

사용가능한 메모리 양이 줄면 새로운 프로그램을 실행시키고 싶어도

메모리 부족으로 실행이 되지 않습니다.

그렇기 때문에 기존에 실행한 프로세스를 kill해야하는 경우가 발생합니다.

리눅스에서는 메모리가 부족한 상황에서도 기존의 프로세스를 kill하지 않고 새 프로세스를 띄울 수가 있는데, 바로 swap 파티션이 있기 때문에 가능합니다.

swap파티션은 메모리에서 현재 사용중이지 않은 프로세스를
하드디스크의  swap  파티션에 저장을 하고
swap파티션에 저장한 공간 만큼 메모리에 사용가능한 용량을 확보 할 수가 있게 됩니다.

swap파티션에 기록된 프로세스가 다시 필요하게 되면
swap파티션에서 메모리로 프로세스 정보가 다시 올라가게 되고
대신 사용 안하는 또 다른 프로세스가 swap파티션으로 내려오게 되는 것입니다.
하드디스크를 읽는 속도는 메모리를 읽는 속도에 비해 상당히 느리기 때문에
swap파티션을 많이 access하게 되면 리눅스 시스템의 전반적인 성능이 많이 저하됩니다.
 

 

SWAP이란?

 

◎ 리눅스의 가상메모리를 사용하기위한 파일SYSTEM

 

◎ 역할 (스와핑(Swaping)이란?)  

    - 물리적인 메모리가 부족할 때 우선 하드디스크공간을 이용하고,

       메모리 사용이 가능해지면 하드디스크에서 메모리로 옮겨오는 방법을 사용한 방법.

     cf) RAM용량의 2-3배

 

◎ 쓰는 이유 

-이렇게 하면 실제 보유하고 있는 메모리보다 훨씬 많은 양의 메모리를 사용할 수 있으므로  

 (→ 더욱 많은 작업을 진행할 수 있다.)

  

◎ 스와핑을 사용하려면..

    - 하드디스크의 공간을 할당해야 한다. 두 가지 방법이 사용

 

cf) 두가지 방식

SWAP 파티션 방식 : 나누어진 파티션 중 하나를 스와핑 영역으로 사용하는 방법

SWAP 파일방식 : 일반적인 파일 시스템에 존재하는 파일을 스와핑 영역으로 사용하는 방법

Technical Note/SERVER PERFORMANCE
L2 스위치: Mac Address
L3 스위치: IP Address 128.25.31.xxx
L2 L3 스위치 : Address를 인식하여 해당장비로 Packet 전송

L4 스위치 : TCP port 80
L5 ~ L7 스위치 : Packet 내용 => "GET/image/xxx.jpg HTTP/1.1"
L4 ~ L7 스위치 : Port Number 또는 Packet 내용을 인식/판단하여 Packet 의 경로 설정, 변환, 필터링 동작을 수행 -> 다계층 스위치

L4 & L7
1. 구조적 차이점 : Intellingence
L4스위치 : TCP/UDP 포트 정보를 분석해 해당 패킷이 현재 사용하는 서비스 종류 (HTTP, FTP, 텔넷, SMTP, POP3, SSL 등) 별로 Packet처리

L7스위치 : 트래픽의 내용(e-mail 제목/내용의 문자열, HTTP 컨텐츠 URL, FTP파일 제목, SSL ID, Cookie 정보, 특정 바이러스 패턴) 등을 분석해  Packet 처리 

공통 점 : 스위치로 들어온  packet을 적절한 목적지로(주로 네트워크 장비나, 클라이언트, 때로는 불필요한 Packet 을 Drop 시키기도 함) 전송해줌. 기본적인 기능과 역할은 동일하나,  Packet을 분석해 성격과 중요도를 분류하는 Intelligence 가 달라서 "적절한 목적지"를 찾아내 해당 Packet을 처리해 주는 능력에 차이가 발생함

2. 기능적 차이점
보다 높은 수준의 Intelligence를 갖춘 스위치 일수록 더 정교한 패킷의 Load Ballancing  및 Qos 기능 구현이 가능함, 
L7 스위치는 다음과 같은 기능을 통해 네트워크 시스템의 보안성 강화가 가능함
1. Dos/SYN Attack에 대한 방어
2. CodeRed/Nimda등 바이러스 감염 패킷의 필터링
3. 네트워크 자원의 독점 방지를 통한 네트워크 시스템의 보안성 강화가 가능함 


Technical Note/SERVER PERFORMANCE

용량 계획을 위해서는 임계 성능 시험이 필요


용량 계획을 통해서 얻을 수 있는 것
1. 비용 측면
- 하드웨어 투자 비용을 줄일 수 있다
2. 운영 관리 측면
- 기존 리소스 사용률을 향상시킬 수 있다.
- 어플리케이션 효율성을 향상시킬 수 있다.
- 서비스 품질을 향상시킬 수 있다.
- 서버 통합을 달성할 수 있다.


1. 비즈니스 용량 계획 : 비즈니스 확장성을 고려한 서비스와 IT 인프라스트럭처의 용량 계획
2. 서비스 용량 계획 : 고객에 의해 사용되는 서비스의 운영 측면에서의 용량 계획

3. 리소스 용량 계획 : IT 인프라스트럭처의 개별 구성요소 측면에서의 용량 계획


요구사항 분석 --> 현행 시스템 분석 (성능 기준선-Baseline 선정) --> 목표치 정의 --> Workload 예측, Application sizing --> 용량 계획 결과 보고

주요 평가 지표(KPI)
- 비즈니스 부문 : 동시 사용자 수
- 서비스 부문 : TPS , 응답시간, 가용성
- 리소스 부문 : CPU 사용율, 메모리 사용율, 큐 길이


일반적인 방법론

이후 섹션에서는 시스템에 대한 실제 분석을 수행하는 데 사용되는 반복 프로세스를 설명한다. "프로세스" 이전의 섹션까지는 프로세스를 실행하는 데 필요한 중요 개념을 정의한다.

사용자 시나리오

많은 수의 사용자를 처리할 수 있도록 WebSphere Portal 시스템을 조정하고 적정 수준의 사용자 수를 처리할 수 있는 시스템의 성능을 정확히 예측하려면 시스템의 사용자에 대한 가장 개연성 높은 시나리오를 결정하는 것이 중요하다. 그런 다음 테스트에서 부하 생성기를 사용하여 사용자 시나리오를 정확히 시뮬레이션해야 한다. 이 단계를 효과적으로 수행하는 방법 중 하나는 개연성이 높은 사용 사례를 나열한 후 각 사용 사례에 대한 스크립트를 최대한 실질적으로 작성하는 것이다. 이제 전체 사용자 중에서 해당 시나리오를 실행할 사용자의 비율을 나타내는 확률을 할당한다. 그런 다음 테스트를 실행할 때 일반적으로 예상되는 사용자 수와 동일한 비율로 사용 사례를 Vuser에 할당한다. Vuser의 수가 포화 상태가 되면 이 비율을 유지한다.

참고: "Vuser"는 LoadRunner 용어로 요청이 발생하고 리턴되는 하나의 활성 채널을 의미한다.

대기 시간

대기 시간은 일반 사용자가 WebSphere Portal을 사용하는 중에 마우스를 한 번 클릭하거나 키를 한 번 누를 때 대기하게 되는 평균 시간이다. 부하 생성 도구에서 이 시간은 일반적으로 미리 정의된 범위 내의 임의 시간이 되도록 프로그래밍할 수 있다.

대기 시간이 줄어들면 초당 요청 수가 늘어나면서 시스템에 대한 부하도 높아진다. 대기 시간을 줄이면 일반적으로 WebSphere Portal 로그인 및 페이지 간 탐색의 평균 응답 시간이 늘어난다. 따라서 프로덕션 시스템을 정확히 모델링하려면 특히, 올바른 용량 계획을 마련하려면 실제 사용자의 대기 시간을 정확히 추정해야 한다.

대부분의 사용 사례에서는 숙련된 사용자가 사용하는 포털의 경우 10초를 기준으로 50%의 편차가 있는 대기 시간이 적당하다. 숙련되지 않은 사용자가 사용하는 포털의 경우에는 대기 시간이 30초에 가까울수록 좋다.

쿠키 및 세션

실제 사용자 중에서 포털에 로그인하여 필요한 작업을 수행한 후 로그아웃 단추를 사용하여 로그아웃하는 사용자는 거의 없다. 대신 해당 세션의 제한 시간에 도달할 때까지 브라우저를 유휴 상태로 두는 경우가 대부분이다. 메모리에 있는 많은 세션은 대개 제거되지 않은 채로 WebSphere Application Server 세션의 제한 시간에 도달할 때까지 유지된다. 이러한 작동 방식으로 인해 JVM(Java™ Virtual Machine) 힙 작업 세트가 늘어나며, 결과적으로 JVM의 힙이 소진될 수 있는 가능성이 높아진다. 힙 소진은 성능 병목 현상뿐 아니라 JVM 오류의 원인이 될 수 있다.

효과적인 시뮬레이션은 명시적으로 로그아웃하지 않는 사용자의 이러한 동작을 모델링해야 한다. 특정 사용 사례를 실행하는 개별 시뮬레이션에서는 로그아웃하지 않고 유휴 상태로 유지되는 사용 사례를 종료해야 한다. 스크립트 주기가 이 특정 Vuser의 새 사용자를 로그인하는 단계로 돌아오게 되면 해당 스크립트를 사용하여 다음 사용자를 로그인하기 전에 기존 세션(일반적으로 JSESSIONID) 및 LTPA(Lightweight Third-Party Authentication)에 대한 쿠키와 애플리케이션 관련 쿠키를 삭제해야 한다. 또한 이 모델에서는 테스트 ID가 WebSphere Application Server 세션의 제한 시간 동안 이전 세션의 제한 시간에 도달할 때까지 재사용되지 않고 유휴 상태로 유지될 수 있도록 충분한 개수의 테스트 ID가 있다고 가정한다.

측정 기준

측정 작업에 사용할 스크립트를 작성해야 한다. 가장 중요한 측정 기준은 초당 페이지 보기 수이다. 요청 응답 시간도 중요하다. WebSphere Portal에서는 로그인에 많은 리소스가 소요되므로 로그인 응답 시간과 페이지 간 응답 시간도 측정해야 한다. 대부분의 부하 생성기에는 종합적인 초당 페이지 보기 수(PV/s) 측정 결과를 제공하는 기능이 있다.

각 테스트가 완료된 후에는 분석 작업을 수행하기 위해 세 가지 측정 기준에 대한 Vuser의 증가율을 보여 주는 그래프가 필요하다.

부하 생성 도구에서 수집된 측정 결과와 함께 ITCAM(IBM Tivoli Composite Application Manager) for WebSphere 또는 Computer Associates Wily IntroScope 제품과 같은 시스템 모니터링 도구도 필요하다. 이러한 도구는 WebSphere Portal 인스턴스에서 실행되면서 JVM을 직접 측정한다. 이러한 도구는 시스템 병목 현상의 감지 및 해결에 모두 유용하다.

대기 시간과 대조되는 vUser

대기 시간이 짧은 요청을 생성하는 소수의 사용자만으로도 일정한 속도로 요청을 생성하는 많은 수의 사용자를 정확히 시뮬레이션할 수 있다고 오해하는 사람들이 많이 있다.

하지만 대기 시간이 짧은 상태에서 소수의 사용자만으로 실행하게 되면 캐시 적중 비율이 비현실적으로 높게 나온다는 것을 알아야 한다. 이는 생성되는 세션 또한 소수에 불과하다는 것을 의미한다. 세션 크기가 많은 포틀릿 애플리케이션에서 심각한 문제이기도 하므로 이러한 방식으로 테스트를 수행하게 되면 시스템 성능이 비현실적으로 아주 좋게 나오기 마련이지만 프로덕션 환경에서는 황당한 결과가 발생하게 된다는 점을 염두에 두어야 한다.

대기 시간 없이 소수의 vUser 세트를 실행하는 경우도 현실을 고려하지 않은 방법 중 하나이다.

반복 가능성 원칙

사용자 수가 많은 경우 사용자가 포털을 탐색할 때 대부분의 사용자 동작이 특별한 규칙 없이 무작위로 나타날 것이라고 가정하기 쉽다. 하지만 경험이 많은 사용자는 대개 동일한 패턴을 사용하는 경향이 있다. 또한 테스트 엔지니어링 관점에서 보면 사용자 시나리오가 어느 정도 고정되어 있어야만 각 실행 사이의 시스템 변경 사항을 효과적으로 측정할 수 있다.

따라서 반복 가능성 원칙은 실행이 충분히 긴 경우 특정 시나리오의 모든 실행에서 산출된 측정 결과(평균 응답 시간, PV/s, 포화점 등)가 동일한 결과로 수렴되는 것이라고 정의할 수 있다. 테스트 스크립트에 추가 변형(즉, 고유 시나리오)이 있는 경우에는 횟수가 늘어날수록 평균에 수렴하게 된다.

성능 테스트를 위해 작성된 시뮬레이션 스크립트는 반복 가능성 원칙을 따라야 한다.

포화 상태로 만들기

포화점은 Vuser를 추가하더라도 PV/s 값이 증가하지 않는 상태에 도달한 시점에 존재하는 활성 Vuser의 수로 정의된다. 이 포화점은 지정된 시뮬레이션에만 적용되며 각 시뮬레이션에는 각기 다른 포화점이 적용된다. 포화점은 사용 패턴에 따라 달라진다.

시스템을 효과적으로 포화 상태에 도달하게 만들려면 한 번에 소수의 Vuser를 추가한 후 시스템이 안정화될 때까지 기다리면서 PV/s가 증가하는지 확인한 후 Vuser를 다시 추가하는 것이 좋다. (여기에서 "안정화"는 응답 시간이 수 분 동안 일정한 수준으로 유지되는 것을 의미한다.) LoadRunner의 경우 Vuser를 처리 속도(PV/s)에 대해 구성하면 PV/s는 처음에 Vuser의 수에 따라 선형으로 높아지다가 최대값에 도달하게 되면 그때부터 조금씩 낮아진다. 포화점은 PV/s가 최대값에 도달했을 때의 Vuser의 수이다.


Technical Note/SERVER PERFORMANCE

JVM Memory 운용 모델

 

1. System Memory Model
java Test이 발생하고나서의 상황
---------------------------------------------
- 구획별 메모리는 64KB단위로 구분되어 있습니다.

┌────────────┐CS: Code Segment
│[코드 영역]                    │ 
│Test Class의 Source가    │ 
│등록되는 영역                 │ 
├────────────┤DS: Data Segment
│[Data 영역]                    │
│static변수,                     │
│static 메소드 저장           │
│main()                           │ 
│객체를 만들지 않아도       │
│이영역의 요소 사용가능    │
├────────────┤SS: Stack Segment
│[Stack 영역]                  │
│메소드가 사용하는 영역    │
│메소드 안에서 선언되는    │ 
│지역변수가 선언,             │
│메소드 처리가 끝나면       │ 
│메모리가 자동으로           │ 
│회수됨                           │ 
├────────────┤
│[Heap 영역]                   │
│객체가 생성되면              │
│존재하는 영역,                │
│RAM의 양에 따라 무한대  │
│GC의 대상이 되는 영역    │
└────────────┘

 

 

 

2. JVM Memory Model

Code Area ----- Data  ---- Stack --------------------- Index Table ----- Heap
                        Area                                                   Hash Table
----------------------------------------------------------------------------------------
Source              Static        메소드가 사용하는 영역          레퍼런스 값          주소
                        변수
                        메소드
----------------------------------------------------------------------------------------
메소드(공유)                      객체 변수1                            this, super       멤버변수  
int k=0;                              지역 변수                                                  인스턴스 변수
int m = 0;                           객체 변수2
int tot = 0;                          Test obj = new Test()  ---->  1000 0xFF00      0xFF00 int k...
int Total(){}                       Test obj2 = new Test()  --->  1001 0xFF08      0xFF08 int k...
                                       obj2 = obj;

                                

                                       Test obj3 = new Test()
                                       obj.tot = obj.Total(); 
                                       obj3.tot = obj3.Total();          

 


▩ static 변수(정적 변수, 클래스 변수), static method(클래스 메소드)
   - 자바 JVM으로 소스가 적재될시에 자동으로 Data Area에 메모리 할당을 받습니다.


   - new를 이용해 객체를 만들지 않고 사용 가능합니다.


   - 색상 정보등 단순한 값을 참조할 경우와 값을 편집하는 경우에 사용합니다.


   - static 변수는 객체 생성시에 오로지 하나만 생성됩니다.


   - static 변수는 객체 생성시에 오로지 하나만 생성됨으로 클래스 변수라고 합니다.


   - static변수는 DS(Data Segment) 데이터 영역을 사용합니다.

 

1. Hash Code의 출력
   - 객체의 Hash Code는 SUN에서 지정한 JVM의 해시알고리즘에 의해 해시코드가 산출됩니다.

   - String은 객체변수의 값이 같을 경우 즉 같은 문자열을 가지고 있으면 Hash code를 공유합니다.


     String str1 = "왕눈이";
     String str2 = "왕눈이";
     
     str1.hashCode() = str2.hashCode();


>>>>> HashCodeTestMain.java
class HashCodeTest {
    //멤버 변수, instance 변수, heap, 객체 사이트 8바이트
    int kuk=100;
    int eng=100;
}

public class HashCodeTestMain {
    //Data Area
    public static void main(String[] args) {
        //Stack: hct1       Heap
        //객체 변수: Hash Code값을 가지고 있습니다.
        HashCodeTest hct1 = new HashCodeTest();

        System.out.println("hct1.hashcode:" + hct1.hashCode());
    }
}

 


출력 결과
---------
hct1.hashcode:7699183

 


2. static 변수는 객체를 만들지 않아도 접근할 수 있습니다.

>>>>> Scjp.java
class ScjpPass{
    //멤버 변수, Heap
    int t1=0;
    int t2=0;
    int t3=0;
    int t4=0;
    
    //클래스 변수, Data area
    static int BONUS=100; 
    
    //생성자, Source area
    public ScjpPass(){
    }
    
    //생성자, this = sp객체가 가지고 있는 hash code
    //sp객체의 heap메모리를 공유하게됩니다.
    //int t1, int t2, int t3, int t4: Stack
    public ScjpPass(int t1, int t2, int t3, int t4){
        //Heap = Stack
        this.t1 = t1;
        this.t2 = t2;
        this.t3 = t3;
        this.t4 = t4;        
    }
    
}


public class Scjp {
    public static void main(String[] args) {
        System.out.println("ScjpPass.BONUS: " + ScjpPass.BONUS);  
        
        //t1은 static이 아님으로 클래스명으로 접근 할 수 없습니다.
        //System.out.println(ScjpPass.t1);
        //heap memory 할당
        ScjpPass sp = new ScjpPass(85, 90, 80, 70);
        System.out.println("sp.t1: " + sp.t1);
        //static변수는 클래스명으로 접근을 권장합니다.
        //System.out.println("sp.BONUS: " + sp.BONUS);
    }
}

 


3. static 메소드는 객체를 만들지 않고도 호출할 수 있습니다.
   - wrapper 클래스에서 많이 사용되며 단순 기능만을 사용할 경우 구현합니다.

 

>>>>> SCWCDmain.java
//하나의 java 파일안에 클래스가 2개이상 존재하는 경우
//main()메소드가 있는 오직 하나의 클래스만 public을 선업합니다.
//일반적으로 main()가 있으면 무조건 public을 선언하며
//파일명은 public 클래스명과 일치해야 합니다.

class SCWCD{
    int t1=0;
    int t2=0;
    int t3=0;
    int t4=0;
    static int BONUS=100; 
        
    public SCWCD(){
    }
    
    public SCWCD(int t1, int t2, int t3, int t4){
        this.t1 = t1;
        this.t2 = t2;
        this.t3 = t3;
        this.t4 = t4;        
    }
    
    public String pass(){
        String msg=null;
        if (t1 >= 65 && t2 >=65 && t3 >=65 && t4>=65){
            msg="축하합니다. 합격입니다.";
        }else{
            msg="축하합니다. 불합격입니다.";
        }
        return msg;
    }

    //클래스 메소드 
    public static void prLine(){
        System.out.println("****************");
        System.out.println("   ITWILL       ");
        System.out.println("         JAVA   ");
        System.out.println("****************");
    }
}

 

public class SCWCDmain {
    public static void main(String[] args) {
        //객체를 만들지 않고도 호출가능합니다.
        SCWCD sc = new SCWCD();
        //객체명.멤버변수, 멤버 메소드
        sc.t1 = 100;
        //sc.prLine();
        
        //클래스.static 메소드명
        SCWCD.prLine(); 
    }
}

 


4. 객체를 생성하면 멤버변수는 전부 기본값이나 생성자에서 지정한 값으로 초기화됩니다. 
   하지만 static변수는 프로그램을 실행시 최초 한번만 특정값으로 초기화되고

   (여기서는 0으로 초기화) 더 이상 초기화가 되지않습니다. 
   따라서 한번 만들어진 static변수는 계속적으로 값이 증가 및 감소됩니다.
   - static 변수는 객체를 여러번 생성해도 한번만 생성이 됩니다.
   - static 변수는 멤버 메소드에 선언할 수 없습니다.

 

>>>>> StaticDemo.java
class Box {
  //인스턴스 변수, 전역변수(객체를 생성시마다 초기화됩니다.)   
  int         cnt   = 0;
  
  //단 1회만 초기화 됩니다. 소스 로딩시에 메모리를 
  //한번만 할당 받습니다.
  static long boxID = 0;
  
  public Box() {
    long count=0;  
    boxID = boxID + 1; //static variable
    cnt = cnt + 1;    //member variable
    System.out.println("cnt: " + cnt);
    System.out.println("BoxID: "+ boxID );
    
  }
  
  //멤버 메소드에서는 static변수를 선언할수 없습니다.
  /*
  public void staticTest(){
      static long count=0;
      count=count+1;
      
  }
  */
  
  //static(class) 메소드에 static 변수를 선언할 수 없습니다.
  /*
  public static void staticTest2(){
      static long count=0;
      count=count+1;
      
  }
  */
  
}
  
public class StaticDemo {
    public static void main(String args[]) {
        //객체 생성  
        Box mybox1 = new Box();
        Box mybox2 = new Box();
        Box mybox3 = new Box();
    }
}

 

 


▩ 값을 변경할 수 없는 final 변수(상수 선언)
   - 값을 변경할 수가 없습니다.

   - 값을 고정할 필요가 있는 코드와 같은 형태의 데이터에 사용합니다.
      예)1년 12달, 요일, 주7일


>>>>> Finalmain.java
class Final{
    int money=10000;
    final int day=7;    //1주
    final int week = 4; //한달
    
    //상수 선언
    final static int month=12; //1년
    
    //생성자가 존재 하지만 아무런 처리를 하지 않습니다.
    public Final(){}     
}

public class Finalmain {

    public static void main(String[] args) {
        Final fi = new Final();
        fi.money = 15000;
        //final변수는 값을 변경(대입)할 수 없습니다. 
        //fi.day = 10;
        System.out.println("1주일 용돈:" + fi.money * fi.day);
        System.out.println("1년" + Final.month + "달");
        //Final.month = 20000;
    }
}

1 2 3
블로그 이미지

zzikjh