1. https://nodejs.org/ko/download/ 사이트에서 Windows Binary (.zip) 파일다운로드
2. 다운로드한 파일을 원하는 위치에 압축 해제 ex) K:\node-v12.16.3-win-x64
3. 압축 해제한 폴더를 환경 변수(Path)에 추가
4. cmd 실행하여 버전 정보가 표시되는 확인
Android - 가비지 컬렉션의 특징
1. 가비지 컬렉션이 발생하는 시점에 대해서 제어할 수 없다.
System.gc() 를 호출하여 안드로이드에 명령을 할 수는 있지만, 최종적으로는 달빅 가상머신이 언제 실행할지를 결정한다.
2. 가비지 컬렉션이 실행되는 상황
- GC_FOR_MALLOC : 힙이 가득차서 메모리를 할당하지 못하고, 할당이 계속 이루어질 수 있도록 메모리가 리클레임되어야 할 때 발생
- GC_CONCURRENT : 컬렉션이 시작되는, 보통은 리클레임할 충분한 오브젝트들이 있을 때 발생.
- GC_EXPLICT : system.gc()를 호출해서 가비지 컬렉션을 명백하게 요청할 때 발생
- GC_EXTERNAL_ALLOC : External native memory alloc이 발생하여 메모리가 full인 경우.
- GC_HPROF_DUMP_HEAP : HPROF 파일을 생성할 때 발생
3. 참고
안드로이드 2.3 이후 버전에서는 가비지 컬렉션 작업이 분리된 스레드에서 실행되므로 이전처럼 모든 앱이 정지되는 현상이 발생되지는 않는다.
하지만 가비지 컬렉션이 일어나면 메인 스레드는 여전히 영향을 받는다. (5ms)
System.gc() 를 호출하여 안드로이드에 명령을 할 수는 있지만, 최종적으로는 달빅 가상머신이 언제 실행할지를 결정한다.
2. 가비지 컬렉션이 실행되는 상황
- GC_FOR_MALLOC : 힙이 가득차서 메모리를 할당하지 못하고, 할당이 계속 이루어질 수 있도록 메모리가 리클레임되어야 할 때 발생
- GC_CONCURRENT : 컬렉션이 시작되는, 보통은 리클레임할 충분한 오브젝트들이 있을 때 발생.
- GC_EXPLICT : system.gc()를 호출해서 가비지 컬렉션을 명백하게 요청할 때 발생
- GC_EXTERNAL_ALLOC : External native memory alloc이 발생하여 메모리가 full인 경우.
- GC_HPROF_DUMP_HEAP : HPROF 파일을 생성할 때 발생
3. 참고
안드로이드 2.3 이후 버전에서는 가비지 컬렉션 작업이 분리된 스레드에서 실행되므로 이전처럼 모든 앱이 정지되는 현상이 발생되지는 않는다.
하지만 가비지 컬렉션이 일어나면 메인 스레드는 여전히 영향을 받는다. (5ms)
Android - 응답성 강화하기
1. 응답성 강화하기
- 일반적으로 100ms에서 200ms가 사용자가 애플리케이션에서 지연을 느낄 수 있는 경계 지점임
- 벡그라운드에서 뭔가 하고 있으면 ProgressBar와 ProgressDialog를 쓸 것
- 특히 게임에서는, 자식 쓰레드에서 움직임에 대한 계산을 할 것
- 멈춘 것 처럼 인식 하지 않도록 할 것
2. 어떻게 ANR을 피할 것인가?
- 메인 쓰레드에서 실행하는 메소드는 최소한의 일을 해야 함
- 특히 onCreate(), onResume()과 같은 핵심 생명주기 메소드 최소한 작은 일을 수행해야 함
- 네트워크, 데이터베이스 오퍼레이션 같은 잠재적으로 긴 것들은 자식 쓰레드에서 수행
- Thread.wait(), Thread.sleep()는 호출 하지 말 것
- 자식 쓰레드가 완료될 때 알려주기 위한 핸들러를 제공해야 함
- 노티피케이션 매니저를 사용할 것
- 일반적으로 100ms에서 200ms가 사용자가 애플리케이션에서 지연을 느낄 수 있는 경계 지점임
- 벡그라운드에서 뭔가 하고 있으면 ProgressBar와 ProgressDialog를 쓸 것
- 특히 게임에서는, 자식 쓰레드에서 움직임에 대한 계산을 할 것
- 멈춘 것 처럼 인식 하지 않도록 할 것
2. 어떻게 ANR을 피할 것인가?
- 메인 쓰레드에서 실행하는 메소드는 최소한의 일을 해야 함
- 특히 onCreate(), onResume()과 같은 핵심 생명주기 메소드 최소한 작은 일을 수행해야 함
- 네트워크, 데이터베이스 오퍼레이션 같은 잠재적으로 긴 것들은 자식 쓰레드에서 수행
- Thread.wait(), Thread.sleep()는 호출 하지 말 것
- 자식 쓰레드가 완료될 때 알려주기 위한 핸들러를 제공해야 함
- 노티피케이션 매니저를 사용할 것
Android - ANR 이란?
1. ANR이란 무엇인가?
Application Not Responding의 약자이다.
어플리케이션이 응답하지 않는 경우 안드로이드 시스템에서 보여주는 에러이다.
메인 스레드(일명, UI 스레드)가 일정시간 동안 잡혀 있으면 발생한다.
2. 언제 ANR이 발생하는가?
- 터치를 통한 사용자 입력이 5초 내에 처리되지 않았을 때
- 브로드캐스트가 10초 내에 처리되지 않았을 때
- 서비스가 20초 내로 처리되지 않을 때
3. 왜 ANR이 발생하는가?
앱이 무한 루프에 빠지거나 OOM(Out Of Memory)가 나야 ANR이 발생하는 것이 아니다.
시간이 좀 걸리는 처리를 해도 ANR이 충분히 발생할 수 있다.
4. ANR을 피하려면?
- 시간이 오래걸리는 작업은 스레드를 통해 처리하도록 권장한다.
- 사용자에게는 프로그레스바 등을 이용해 진행 과정을 안내해 기다리도록 한다.
- 이를 위해, 안드로이드에서 상속받아 사용할 수 있는 다양한 방법을 제공하고 있다.
Application Not Responding의 약자이다.
어플리케이션이 응답하지 않는 경우 안드로이드 시스템에서 보여주는 에러이다.
메인 스레드(일명, UI 스레드)가 일정시간 동안 잡혀 있으면 발생한다.
2. 언제 ANR이 발생하는가?
- 터치를 통한 사용자 입력이 5초 내에 처리되지 않았을 때
- 브로드캐스트가 10초 내에 처리되지 않았을 때
- 서비스가 20초 내로 처리되지 않을 때
3. 왜 ANR이 발생하는가?
앱이 무한 루프에 빠지거나 OOM(Out Of Memory)가 나야 ANR이 발생하는 것이 아니다.
시간이 좀 걸리는 처리를 해도 ANR이 충분히 발생할 수 있다.
4. ANR을 피하려면?
- 시간이 오래걸리는 작업은 스레드를 통해 처리하도록 권장한다.
- 사용자에게는 프로그레스바 등을 이용해 진행 과정을 안내해 기다리도록 한다.
- 이를 위해, 안드로이드에서 상속받아 사용할 수 있는 다양한 방법을 제공하고 있다.
Java - 파일 쓰기 성능 비교
1. 자바에서 파일 쓰기 구현시 어떤 방법이 빠른지 테스트.
- FileWriter fw = new FileWriter(LOG_HOME+"writer.log");
- BufferedWriter bw = new BufferedWriter(new FileWriter(LOG_HOME+"writer.log"));
- FileOutputStream fos = new FileOutputStream(LOG_HOME+"outputstream.log");
- BufferedOutputStream fos = new BufferedOutputStream(
new FileOutputStream(LOG_HOME+"bufferedoutputstream.log"));
- FileChannel fc =
(new FileOutputStream(new File(LOG_HOME+"filechannel.log"))).getChannel();
// Byte Buffer 매번 생성
- FileChannel fc =
(new FileOutputStream(new File(LOG_HOME+"filechannel.log"))).getChannel();
// ByteBuffer 재사용
2. 테스트 결과
1K 2K 5K 10K 50K
FileWriter 31 32 94 203 1281
FileWriter + BufferedWriter 15 31 94 188 1000
FileOutputStream 32 47 109 188 1063
FileOutputStream + BufferedOutputStream 31 47 109 203 1578
FileChannel 47 63 109 219 2906
FileChannel + Byte Buffer 재사용 31 47 188 250 2766
FileWriter와 FileOutputStream의 성능이 높게 나옴.
BufferedWriter 등의 경우 GC를 유발하는 문제가 있기 때문에 성능 저하 요인이 될 수 있으나, 테스트 결과로는 FileWriter + BufferedWriter의 경우가 성능이 제일 좋음.
- FileWriter fw = new FileWriter(LOG_HOME+"writer.log");
- BufferedWriter bw = new BufferedWriter(new FileWriter(LOG_HOME+"writer.log"));
- FileOutputStream fos = new FileOutputStream(LOG_HOME+"outputstream.log");
- BufferedOutputStream fos = new BufferedOutputStream(
new FileOutputStream(LOG_HOME+"bufferedoutputstream.log"));
- FileChannel fc =
(new FileOutputStream(new File(LOG_HOME+"filechannel.log"))).getChannel();
// Byte Buffer 매번 생성
- FileChannel fc =
(new FileOutputStream(new File(LOG_HOME+"filechannel.log"))).getChannel();
// ByteBuffer 재사용
2. 테스트 결과
1K 2K 5K 10K 50K
FileWriter 31 32 94 203 1281
FileWriter + BufferedWriter 15 31 94 188 1000
FileOutputStream 32 47 109 188 1063
FileOutputStream + BufferedOutputStream 31 47 109 203 1578
FileChannel 47 63 109 219 2906
FileChannel + Byte Buffer 재사용 31 47 188 250 2766
FileWriter와 FileOutputStream의 성능이 높게 나옴.
BufferedWriter 등의 경우 GC를 유발하는 문제가 있기 때문에 성능 저하 요인이 될 수 있으나, 테스트 결과로는 FileWriter + BufferedWriter의 경우가 성능이 제일 좋음.
Android - 웹뷰 성능 향상
1. 캐쉬 사용하지 않기
webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);로 브라우져 캐쉬를 끈다.
2. 하드웨어 가속 기능 사용하기
렌더링에 대해서 하드웨어 가속 기능을 사용할지 여부인데, 3.0 부터 지원.
default는 false이며, 4.0부터는 default가 true.
AndroidManifest.xml에서 android:hardwareAccelrated를 true로 설정
3. 렌더링 우선 순위 높이기
강제적으로 렌더링 기능에 대한 우선 순위를 높이는 방법이다.
webView.getSettings().setRenderPriority(RenderPriority.HIGH)로 설정
API Level 18부터는 deprecated.
webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);로 브라우져 캐쉬를 끈다.
2. 하드웨어 가속 기능 사용하기
렌더링에 대해서 하드웨어 가속 기능을 사용할지 여부인데, 3.0 부터 지원.
default는 false이며, 4.0부터는 default가 true.
AndroidManifest.xml에서 android:hardwareAccelrated를 true로 설정
3. 렌더링 우선 순위 높이기
강제적으로 렌더링 기능에 대한 우선 순위를 높이는 방법이다.
webView.getSettings().setRenderPriority(RenderPriority.HIGH)로 설정
API Level 18부터는 deprecated.
Android - 효율적인 코드 작성하기2
1. Constants 를 final로 선언하라
컴파일러는 <clinit>라고 불리는 class initializer method 생성하며 이는 클래스가 처음 생성될 때 실행된다.
final로 설정되지 않은 값들은 reference될 때 field lookup을 사용해서 접근하여 속도가 조금 느린 편이다.
그러나 final로 설정하면 field lookup을 거치지 않고 바로 사용할 수 있어 빠른 편이다.
class와 function도 final로 설정함으로서 약간의 성능 향상을 노릴 수 있다.
2. Enhanced For Loop 문법을 주의하여 사용
반복문을 여러 번 사용할 경우에는 특히 object 생성에 주의해야 한다.
횟수가 기하학적으로 증가할 수 있고, 발견이 어려울 수 있기 때문이다.
3. Enums를 피하라
Enums의 접속 속도가 느리기 때문에 자주 사용하면 성능이 저하될 수 있다.
따라서 Enums를 지속적으로 사용하는 경우에는 local변수로 만들어 사용하는 것이 좋다.
4. 부동소수점(float)을 가능한 피하라
5. 곱셈 연산을 사용하라.
나누기 연산보다는 곱셈 연산을 사용하는 것이 성능에 더 좋다.
컴파일러는 <clinit>라고 불리는 class initializer method 생성하며 이는 클래스가 처음 생성될 때 실행된다.
final로 설정되지 않은 값들은 reference될 때 field lookup을 사용해서 접근하여 속도가 조금 느린 편이다.
그러나 final로 설정하면 field lookup을 거치지 않고 바로 사용할 수 있어 빠른 편이다.
class와 function도 final로 설정함으로서 약간의 성능 향상을 노릴 수 있다.
2. Enhanced For Loop 문법을 주의하여 사용
반복문을 여러 번 사용할 경우에는 특히 object 생성에 주의해야 한다.
횟수가 기하학적으로 증가할 수 있고, 발견이 어려울 수 있기 때문이다.
3. Enums를 피하라
Enums의 접속 속도가 느리기 때문에 자주 사용하면 성능이 저하될 수 있다.
따라서 Enums를 지속적으로 사용하는 경우에는 local변수로 만들어 사용하는 것이 좋다.
4. 부동소수점(float)을 가능한 피하라
5. 곱셈 연산을 사용하라.
나누기 연산보다는 곱셈 연산을 사용하는 것이 성능에 더 좋다.
Android - 효율적인 코드 작성하기1
1. 오브젝트 생성을 피하라
오브젝트 생성은 메모리를 할당하는 작업으로, 일반 작업에 비해 load가 큰 편.
Java의 GC는 매우 큰 작업으로 구분되는데, 쓸데없는 메모리 할당으로 GC를 초래하게 되면 성능저하를 유발.
반복문에서의 오브젝트 생성은 오버헤드가 크므로 피함.
2. Native Method를 사용하라.
Native Method들은 C/C++ 등으로 구현되어 있어 Java 코드보다 약 10~100배 빨리 실행된다.
따라서 Native Method들을 이용하여 구현하는 것이 성능에 좋다.
3. 내부적인 getters/setters를 피하라
일반적인 OOP개념의 getter/setter는 합리적이나 클래스 내부에서의 변수 접근에도 getter/setter를 사용하는 것은 비효율적이다.
4. Cache Field Loop ups
맴버변수에 접근하는 것은 지역 변수에 접근하는 것보다 훨씬 속도가 느리다.
따라서 맴버변수를 여러 번 사용하는 함수에서는 맴버변수를 지역변수에 할당하여 처리하는 것이 효율적이다.
오브젝트 생성은 메모리를 할당하는 작업으로, 일반 작업에 비해 load가 큰 편.
Java의 GC는 매우 큰 작업으로 구분되는데, 쓸데없는 메모리 할당으로 GC를 초래하게 되면 성능저하를 유발.
반복문에서의 오브젝트 생성은 오버헤드가 크므로 피함.
2. Native Method를 사용하라.
Native Method들은 C/C++ 등으로 구현되어 있어 Java 코드보다 약 10~100배 빨리 실행된다.
따라서 Native Method들을 이용하여 구현하는 것이 성능에 좋다.
3. 내부적인 getters/setters를 피하라
일반적인 OOP개념의 getter/setter는 합리적이나 클래스 내부에서의 변수 접근에도 getter/setter를 사용하는 것은 비효율적이다.
4. Cache Field Loop ups
맴버변수에 접근하는 것은 지역 변수에 접근하는 것보다 훨씬 속도가 느리다.
따라서 맴버변수를 여러 번 사용하는 함수에서는 맴버변수를 지역변수에 할당하여 처리하는 것이 효율적이다.
JavaScript - 성능 향상 (오브젝트)
* 오브젝트 생성
객체를 생성하는 방법으로 리터럴을 사용하는 방법과 생성자를 사용하는 방법이 있음
var obj = {}; // 리터럴
var obj = new Object(); // 생성자
큰 차이는 없으나 리터럴을 사용하는 방법이 조금 더 나은 성능을 보임
* 오브젝트 초기화
객체를 초기화하는 방법으로 .연산자를 사용하는 방법과 []연산자를 사용하는 방법이 있음.
obj.a = 1; // .연산자
obj["a"] = 1; // []연산자
사파리를 제외한 대부분의 브라우저에서 비슷한 성능을 보임. 사파리는 .연산자를 사용하는 방법이 더 좋은 성능을보임.
* 코드 최적화
어느 방법을 사용하더라도 비슷한 성능을 보임
객체를 생성하는 방법으로 리터럴을 사용하는 방법과 생성자를 사용하는 방법이 있음
var obj = {}; // 리터럴
var obj = new Object(); // 생성자
큰 차이는 없으나 리터럴을 사용하는 방법이 조금 더 나은 성능을 보임
* 오브젝트 초기화
객체를 초기화하는 방법으로 .연산자를 사용하는 방법과 []연산자를 사용하는 방법이 있음.
obj.a = 1; // .연산자
obj["a"] = 1; // []연산자
사파리를 제외한 대부분의 브라우저에서 비슷한 성능을 보임. 사파리는 .연산자를 사용하는 방법이 더 좋은 성능을보임.
* 코드 최적화
어느 방법을 사용하더라도 비슷한 성능을 보임
JavaScript - 성능 향상 (배열)
* 배열 생성, 초기화
배열은 생성자 혹은 리터럴 형식을 사용해 객체를 생성할 수 있다.
var arr = new Array(); // 생성자
var arr = []; // 리터럴 형식
리터럴 형식을 사용한 경우 여러 브라우저에서 좀 더 좋은 성능을 보임.
* 배열 데이터 할당
배열에 데이터를 할당하는 방법에는 접근자 []를 사용하는 방법과 push() 메소드를 사용하는 방법이 있다.
arr[i] = 10; // 접근자
arr.push(10); // push 메소드
크롬을 제외한 대부분의 브라우저에서 접근자를 사용한 경우 좀 더 좋은 성능을 보임.
* 코드 최적화
배열 생성시 리터럴 형식을 사용하고, 접근자[]를 사용하여 데이터를 할당하는 것이 최적화된 방법으로 보임
배열은 생성자 혹은 리터럴 형식을 사용해 객체를 생성할 수 있다.
var arr = new Array(); // 생성자
var arr = []; // 리터럴 형식
리터럴 형식을 사용한 경우 여러 브라우저에서 좀 더 좋은 성능을 보임.
* 배열 데이터 할당
배열에 데이터를 할당하는 방법에는 접근자 []를 사용하는 방법과 push() 메소드를 사용하는 방법이 있다.
arr[i] = 10; // 접근자
arr.push(10); // push 메소드
크롬을 제외한 대부분의 브라우저에서 접근자를 사용한 경우 좀 더 좋은 성능을 보임.
* 코드 최적화
배열 생성시 리터럴 형식을 사용하고, 접근자[]를 사용하여 데이터를 할당하는 것이 최적화된 방법으로 보임
MySql - 논리연산자
* SQL에서 모든 논리 연산자는 TRUE, FALSE 또는 NULL(UNKNOWN)로 계산된다.
MySQL에서는 1 (TRUE), 0 (FALSE) 그리고 NULL로 계산된다.
* NOT, !
논리 NOT. 피연산자가 0이면 1을, 피연산자가 0이 아니면 0을, NOT NULL 일 경우에는 NULL을 리턴.
사용예)
SELECT NOT 10; -> 0
SELECT NOT 0; -> 1
SELECT NOT NULL; -> NULL
* AND, &&
논리 AND. 모든 피연산자가 0이 아니고 NULL도 아니면 1을, 한 개 또는 그 이상의 피연산자가 0이라면 0을, 그렇
지 않을 경우에는 NULL을 리턴.
사용예)
SELECT 1 && 1; -> 1
SELECT 1 && 0; -> 0
SELECT 1 && NULL; -> NULL
* OR, ||
논리 OR. 양쪽의 피연산자가 NULL이 아닌 경우 양쪽의 피연산자가 0이 아니면 1을, 그렇지 않으면 0을 리턴.
NULL 피연산자를 사용하면, 다른 피연산자가 0이 아니면 1을, 그렇지 않으면 NULL을 리턴. 만일 양쪽의 피연산자가 모두 NULL이라면, 결과는 NULL.
사용예)
SELECT 1 || 1; -> 1
SELECT 1 || 0; -> 1
SELECT 0 || 0; -> 0
* XOR
논리 XOR. 피연산자 중의 하나가 NULL이면 NULL을 리턴. NULL이 아닌 피연산자의 경우, 피연산자의 홀수 개수가 0이 아니면 1을, 그렇지 않으면 0을 리턴.
사용예)
SELECT 1 XOR 1; -> 0
SELECT 1 XOR 0; -> 1
SELECT 1 XOR NULL; -> NULL
MySQL에서는 1 (TRUE), 0 (FALSE) 그리고 NULL로 계산된다.
* NOT, !
논리 NOT. 피연산자가 0이면 1을, 피연산자가 0이 아니면 0을, NOT NULL 일 경우에는 NULL을 리턴.
사용예)
SELECT NOT 10; -> 0
SELECT NOT 0; -> 1
SELECT NOT NULL; -> NULL
* AND, &&
논리 AND. 모든 피연산자가 0이 아니고 NULL도 아니면 1을, 한 개 또는 그 이상의 피연산자가 0이라면 0을, 그렇
지 않을 경우에는 NULL을 리턴.
사용예)
SELECT 1 && 1; -> 1
SELECT 1 && 0; -> 0
SELECT 1 && NULL; -> NULL
* OR, ||
논리 OR. 양쪽의 피연산자가 NULL이 아닌 경우 양쪽의 피연산자가 0이 아니면 1을, 그렇지 않으면 0을 리턴.
NULL 피연산자를 사용하면, 다른 피연산자가 0이 아니면 1을, 그렇지 않으면 NULL을 리턴. 만일 양쪽의 피연산자가 모두 NULL이라면, 결과는 NULL.
사용예)
SELECT 1 || 1; -> 1
SELECT 1 || 0; -> 1
SELECT 0 || 0; -> 0
* XOR
논리 XOR. 피연산자 중의 하나가 NULL이면 NULL을 리턴. NULL이 아닌 피연산자의 경우, 피연산자의 홀수 개수가 0이 아니면 1을, 그렇지 않으면 0을 리턴.
사용예)
SELECT 1 XOR 1; -> 0
SELECT 1 XOR 0; -> 1
SELECT 1 XOR NULL; -> NULL
MySql - 연산자 우선순위
* 연산자 우선순위는 아래와 같으며, 낮은 것 -> 높은 것 순서.
동일한 라인은 같은 우선순위.
:=
||, OR, XOR
&&, AND
NOT
BETWEEN, CASE, WHEN, THEN, ELSE
=, <=>, >=, >, <=, <, <>, !=, IS, LIKE, REGEXP, IN
|
&
<<, >>
-, +
*, /, DIV, %, MOD
^
- (unary minus), ~ (unary bit inversion)
!
BINARY, COLLATE
* NOT에 대한 우선순위는 MySQL 5.0.2 이후에 존재.
이전 버전, 또는 HIGH_NOT_PRECEDENCE SQL 모드가 활성화 되어 있는 경우의 5.0.2 까지는, NOT의 우선 순위는 ! 연산자의 우선순위와 같다.
* 연산자의 우선순위는 수식에 있는 항의 계산 순서를 결정.
우선순위를 무시하고 그룹 항을 명확하게 지정하고자 한다면, 괄호를 사용
사용예)
SELECT 1+2*3; => 7
SELECT (1+2)*3; => 9
동일한 라인은 같은 우선순위.
:=
||, OR, XOR
&&, AND
NOT
BETWEEN, CASE, WHEN, THEN, ELSE
=, <=>, >=, >, <=, <, <>, !=, IS, LIKE, REGEXP, IN
|
&
<<, >>
-, +
*, /, DIV, %, MOD
^
- (unary minus), ~ (unary bit inversion)
!
BINARY, COLLATE
* NOT에 대한 우선순위는 MySQL 5.0.2 이후에 존재.
이전 버전, 또는 HIGH_NOT_PRECEDENCE SQL 모드가 활성화 되어 있는 경우의 5.0.2 까지는, NOT의 우선 순위는 ! 연산자의 우선순위와 같다.
* 연산자의 우선순위는 수식에 있는 항의 계산 순서를 결정.
우선순위를 무시하고 그룹 항을 명확하게 지정하고자 한다면, 괄호를 사용
사용예)
SELECT 1+2*3; => 7
SELECT (1+2)*3; => 9
MySql - 리플리케이션이란
* MySQL은 단 방향, 즉 비동기 리플리케이션을 지원.
하나의 서버는 마스터로 동작하고, 나머지 한 개 이상의 다른 서버들은 슬레이브로 동작.
* 싱글-마스터 리플리케이션에서, 마스터 서버는 업데이트를 자신의 바이너리 로그 파일에 작성하고 로그 로테이션의 트레이스를 유지하기 위해 이 파일의 인덱스를 유지 관리한다. 바이너리 로그 파일은 다른 슬레이브 서버에 전달되는 업데이트 레코드 역할을 한다. 슬레이브가 자신의 마스터에 연결이 될 때, 마스터 정보를 자신이 마지막으로 업데이트가 성공했을 때 읽었던 로그에 전달한다. 슬레이브는 그 시간 이후에 발생한 모든 사항에 대한 업데이트를 전달 받고, 블록 (block)을 한 후에 마스터가 새로운 업데이트를 알려 주기를 기다리게 된다.
* 슬레이브 서버를 체인드 리플리케이션 서버로 설정하면, 자신이 마스터 역할을 하게 된다.
* 다중-마스터 리플리케이션은 가능하기는 하지만, 싱글-마스터 리플리케이션에서는 발생하지 않는 문제들이 나타나게 된다.
* 리플리케이션을 사용하는 경우, 복제된 테이블에 대한 모든 업데이트는 마스터 서버에서 실행되어야 한다. 그렇지않으면, 사용자가 마스터에 있는 테이블에서 행하는 업데이트와 슬레이브에서 행하는 업데이트간의 충돌을 피하도록 항상 주의해야만 한다.
* 리플리케이션은 견고성, 속도, 그리고 시스템 관리에 많은 혜택을 제공.
- 견고성은 마스터/슬레이브 설정을 가지고 증가된다. 마스터에서 문제가 발생하면, 백업 형태의 슬레이브로 전환할 수 있다.
- 마스터와 슬레이브 서버 간에 클라이언트 쿼리 처리를 분산함으로써 클라이언트에 대해 보다 개선된 응답 시간을 제공해 줄 수 있다. 슬레이브에 SELECT 쿼리를 전달해서 마스터의 쿼리 처리 업무를 줄여 줄 수 있다. 마스터와 슬레이브의 동기화가 끊어지지 않도록 하기 위해 데이터를 수정하는 명령문들은 여전히 마스터에 전달된다. 이러한 로드 밸런싱 전략은 업데이트 하지 않는 쿼리가 압도적으로 많은 경우에 효과적이다.
- 마스터의 방해 없이 슬레이브 서버를 사용해서 데이터베이스 백업을 실행할 수 있다. 마스터는 백업이 진행되는 동안에도 업데이트 프로세스를 지속할 수 있다.
하나의 서버는 마스터로 동작하고, 나머지 한 개 이상의 다른 서버들은 슬레이브로 동작.
* 싱글-마스터 리플리케이션에서, 마스터 서버는 업데이트를 자신의 바이너리 로그 파일에 작성하고 로그 로테이션의 트레이스를 유지하기 위해 이 파일의 인덱스를 유지 관리한다. 바이너리 로그 파일은 다른 슬레이브 서버에 전달되는 업데이트 레코드 역할을 한다. 슬레이브가 자신의 마스터에 연결이 될 때, 마스터 정보를 자신이 마지막으로 업데이트가 성공했을 때 읽었던 로그에 전달한다. 슬레이브는 그 시간 이후에 발생한 모든 사항에 대한 업데이트를 전달 받고, 블록 (block)을 한 후에 마스터가 새로운 업데이트를 알려 주기를 기다리게 된다.
* 슬레이브 서버를 체인드 리플리케이션 서버로 설정하면, 자신이 마스터 역할을 하게 된다.
* 다중-마스터 리플리케이션은 가능하기는 하지만, 싱글-마스터 리플리케이션에서는 발생하지 않는 문제들이 나타나게 된다.
* 리플리케이션을 사용하는 경우, 복제된 테이블에 대한 모든 업데이트는 마스터 서버에서 실행되어야 한다. 그렇지않으면, 사용자가 마스터에 있는 테이블에서 행하는 업데이트와 슬레이브에서 행하는 업데이트간의 충돌을 피하도록 항상 주의해야만 한다.
* 리플리케이션은 견고성, 속도, 그리고 시스템 관리에 많은 혜택을 제공.
- 견고성은 마스터/슬레이브 설정을 가지고 증가된다. 마스터에서 문제가 발생하면, 백업 형태의 슬레이브로 전환할 수 있다.
- 마스터와 슬레이브 서버 간에 클라이언트 쿼리 처리를 분산함으로써 클라이언트에 대해 보다 개선된 응답 시간을 제공해 줄 수 있다. 슬레이브에 SELECT 쿼리를 전달해서 마스터의 쿼리 처리 업무를 줄여 줄 수 있다. 마스터와 슬레이브의 동기화가 끊어지지 않도록 하기 위해 데이터를 수정하는 명령문들은 여전히 마스터에 전달된다. 이러한 로드 밸런싱 전략은 업데이트 하지 않는 쿼리가 압도적으로 많은 경우에 효과적이다.
- 마스터의 방해 없이 슬레이브 서버를 사용해서 데이터베이스 백업을 실행할 수 있다. 마스터는 백업이 진행되는 동안에도 업데이트 프로세스를 지속할 수 있다.
MySql - 테이블 스캔 피하기
* EXPLAIN을 실행하면 MySQL이 쿼리를 해석하기 위해 테이블을 스캔할 때 type 컬럼에 ALL을 보여줌.
이것은 일반적으로 아래 조건 아래에서 발생.
- 테이블이 너무 작아서 키 룩업 (lookup)을 실행하는 것보다 테이블 스캔을 하는 것이 더 빠름. 일반적으로 10개 미만의 짧은 길이의 행을 가진 테이블이 여기에 해당.
- 인덱스된 컬럼에 대해서 사용할 수 있는 제약 사항이 ON 또는 WHERE 구문에 존재하지 않음.
- 인덱스된 컬럼을 상수 값과 비교할 수 있고, MySQL이 테이블 대부분을 커버하고 있는 상수를 계산해서 테이블 스캔이 빠르게 진행되도록 만드는 경우.
- 다른 컬럼을 통해서 낮은 기수 (cardinality)를 가지고 있는 (많은 열이 키 값과 매치가 됨) 행을 사용할 수 있는 경우, MySQL은 많은 키 룩업 (lookup)이 진행이 되고 이에 따라서 테이블 스캔이 보다 빠를 것이라고 가정.
* 작은 테이블의 경우에는 테이블 스캔이 적절할 수도 있을 것이나 대형 테이블의 경우 옵티마이저가 올바르지 않은 테이블 스캔을 선택하지 못하도록 하기 위해서 아래 기법을 사용.
- 스캔이 된 테이블에 대한 키 배포 업데이트 작업은 ANALYZE TABLE tbl_name를 사용.
- 주어진 인덱스를 사용하는 것 보다 테이블 스캔을 하는 것이 보다 비효율적이라고 MySQL에게 지시하기 위해서, 스캔이 된 테이블에 대해서 FORCE INDEX를 사용.
SELECT * FROM t1, t2 FORCE INDEX (index_for_column)
WHERE t1.col_name=t2.col_name;
- 어떠한 키 스캔도 1,000개 이상의 키 검색이 발생하지 않는다고 가정하게끔 옵티마이저를 만들기 위해서, mysqld를 --max-seeks-for-key=1000 옵션과 함께 시작하거나 또는 SET max_seeks_for_key=1000를 사용.
이것은 일반적으로 아래 조건 아래에서 발생.
- 테이블이 너무 작아서 키 룩업 (lookup)을 실행하는 것보다 테이블 스캔을 하는 것이 더 빠름. 일반적으로 10개 미만의 짧은 길이의 행을 가진 테이블이 여기에 해당.
- 인덱스된 컬럼에 대해서 사용할 수 있는 제약 사항이 ON 또는 WHERE 구문에 존재하지 않음.
- 인덱스된 컬럼을 상수 값과 비교할 수 있고, MySQL이 테이블 대부분을 커버하고 있는 상수를 계산해서 테이블 스캔이 빠르게 진행되도록 만드는 경우.
- 다른 컬럼을 통해서 낮은 기수 (cardinality)를 가지고 있는 (많은 열이 키 값과 매치가 됨) 행을 사용할 수 있는 경우, MySQL은 많은 키 룩업 (lookup)이 진행이 되고 이에 따라서 테이블 스캔이 보다 빠를 것이라고 가정.
* 작은 테이블의 경우에는 테이블 스캔이 적절할 수도 있을 것이나 대형 테이블의 경우 옵티마이저가 올바르지 않은 테이블 스캔을 선택하지 못하도록 하기 위해서 아래 기법을 사용.
- 스캔이 된 테이블에 대한 키 배포 업데이트 작업은 ANALYZE TABLE tbl_name를 사용.
- 주어진 인덱스를 사용하는 것 보다 테이블 스캔을 하는 것이 보다 비효율적이라고 MySQL에게 지시하기 위해서, 스캔이 된 테이블에 대해서 FORCE INDEX를 사용.
SELECT * FROM t1, t2 FORCE INDEX (index_for_column)
WHERE t1.col_name=t2.col_name;
- 어떠한 키 스캔도 1,000개 이상의 키 검색이 발생하지 않는다고 가정하게끔 옵티마이저를 만들기 위해서, mysqld를 --max-seeks-for-key=1000 옵션과 함께 시작하거나 또는 SET max_seeks_for_key=1000를 사용.
MySql - 인덱스 병합 결합 접근 알고리즘
* 이 알고리즘에 대한 표준은 인덱스 병합 방식 교차 알고리즘과 유사.
* 이 알고리즘은 OR과 결합된 서로 다른 키에서 테이블의 WHERE 구문이 여러 개의 범위 조건으로 변환될 때 적용될 수 있으며, 각 조건은 다음 중에 하나가 된다.
- 아래 형태에서는, 인덱스가 정확히 N 개의 부분을 가짐. (즉, 모든 인덱스 부분 커버)
key_part1=const1 and key_part2=const2 ... and key_partN=constN
- InnoDB 테이블의 주요 키 (primary key)에 걸친 모든 범위 조건.
- 인덱스 병합 방식 교차 알고리즘을 적용할 수 있는 조건.
예)
SELECT * FROM t1
WHERE key1=1 OR key2=2 OR key3=3;
SELECT * FROM innodb_table
WHERE (key1=1 and key2=2) OR (key3='foo' and key4='bar') and key5=5;
* 이 알고리즘은 OR과 결합된 서로 다른 키에서 테이블의 WHERE 구문이 여러 개의 범위 조건으로 변환될 때 적용될 수 있으며, 각 조건은 다음 중에 하나가 된다.
- 아래 형태에서는, 인덱스가 정확히 N 개의 부분을 가짐. (즉, 모든 인덱스 부분 커버)
key_part1=const1 and key_part2=const2 ... and key_partN=constN
- InnoDB 테이블의 주요 키 (primary key)에 걸친 모든 범위 조건.
- 인덱스 병합 방식 교차 알고리즘을 적용할 수 있는 조건.
예)
SELECT * FROM t1
WHERE key1=1 OR key2=2 OR key3=3;
SELECT * FROM innodb_table
WHERE (key1=1 and key2=2) OR (key3='foo' and key4='bar') and key5=5;
MySql - 인덱스 병합 교차 접근 알고리즘
* 이 접근 알고리즘은 WHERE 구문이 AND와 결합된 서로 다른 키에 있는 여러 개의 범위 조건으로 변환될 때 사용될 수 있으며, 각각의 조건은 아래의 것 중에 하나가 된다.
아래의 형태에서는, 인덱스가 정확히 N 개의 부분을 가진다 (즉, 모든 인덱스 부분이 커버된다)
key_part1=const1 and key_part2=const2 ... and key_partN=constN
InnoDB 테이블의 주요 키 (primary key)에 걸친 모든 범위 조건.
예)
SELECT * FROM innodb_table WHERE prime_key < 10 and key_col1=20;
SELECT * FROM tbl_name WHERE (key1_part1=1 and key1_part2=2) and key2=2;
인덱스 병합 교차 알고리즘은 사용된 모든 인덱스에서 동시에 스캔을 실행하고, 병합된 인덱스 스캔으로부터 전달받는 열 시퀀스에 대해 교차를 만들어 낸다.
만일 사용된 인덱스가 쿼리에서 사용된 모든 컬럼을 커버한다면, 전체 테이블 열은 추출되지 않는다.
이 경우 EXPLAIN 결과는 Extra 필드 (field)에 있는 Using index를 가진다.
예)
SELECT COUNT(*) FROM t1 WHERE key1=1 and key2=1;
만일 사용된 인덱스가 쿼리에서 사용된 모든 컬럼을 커버하지 못한다면, 사용된 모든 키에 대한 범위 조건이 만족스러울 때에만 전체 열이 추출된다.
만일 병합된 조건 중의 하나가 InnoDB 테이블의 주요 키 (primary key)에 걸쳐지는 조건이라면, 이 조건은 열 추출용으로 사용되지는 않지만, 다른 조건을 사용해서 추출된 열을 걸러 낼 때 사용된다.
아래의 형태에서는, 인덱스가 정확히 N 개의 부분을 가진다 (즉, 모든 인덱스 부분이 커버된다)
key_part1=const1 and key_part2=const2 ... and key_partN=constN
InnoDB 테이블의 주요 키 (primary key)에 걸친 모든 범위 조건.
예)
SELECT * FROM innodb_table WHERE prime_key < 10 and key_col1=20;
SELECT * FROM tbl_name WHERE (key1_part1=1 and key1_part2=2) and key2=2;
인덱스 병합 교차 알고리즘은 사용된 모든 인덱스에서 동시에 스캔을 실행하고, 병합된 인덱스 스캔으로부터 전달받는 열 시퀀스에 대해 교차를 만들어 낸다.
만일 사용된 인덱스가 쿼리에서 사용된 모든 컬럼을 커버한다면, 전체 테이블 열은 추출되지 않는다.
이 경우 EXPLAIN 결과는 Extra 필드 (field)에 있는 Using index를 가진다.
예)
SELECT COUNT(*) FROM t1 WHERE key1=1 and key2=1;
만일 사용된 인덱스가 쿼리에서 사용된 모든 컬럼을 커버하지 못한다면, 사용된 모든 키에 대한 범위 조건이 만족스러울 때에만 전체 열이 추출된다.
만일 병합된 조건 중의 하나가 InnoDB 테이블의 주요 키 (primary key)에 걸쳐지는 조건이라면, 이 조건은 열 추출용으로 사용되지는 않지만, 다른 조건을 사용해서 추출된 열을 걸러 낼 때 사용된다.
Java - 성능 향상 (프로그래밍)
* 자바에 적합한 프로그래밍 방법을 사용하여 성능 향상 효과를 얻을 수 있음.
* final 사용
final 클래스는 컴파일러에 의해 하위 클래스에 의해서 오버라이딩이 불가능한 클래스로 인식되어 컴파일시 동적 메소드 호출 기능을 제거하여 메소드 호출을 최적화. 따라서 일반 메소드 호출보다 훨씬 빠름.
클래스 전체를 final로 사용하는 것은 문제가 발생할 가능성이 많으므로 꼭 필요한 경우가 아니라면 피하는 것이 좋음.
메소드 단위로 final을 사용하는 것이 효율적.
* String 대신 StringBuffer 사용
String은 자바가상머신에 의해 StringBuffer 로 변환되어 처리됨.
String 결합(concat) 연산은 내부적으로 StringBuffer로 변환되어 결합 후 다시 String으로 변환되기에 많은 자원이 소모됨.
따라서 String보다는 StringBuffer 혹은 char 배열을 사용하는 것이 빠름.
* 임시 객체 생성 자제
반복문이나 자주 사용하는 메소드 내에서 생성하는 임시 객체들은 가비지 컬렉터에게 부하를 줌.
따라서 반복문이나 자주 사용하는 메소드 내에서 임시 객체 생성을 피하는 것이 좋음.
* final 사용
final 클래스는 컴파일러에 의해 하위 클래스에 의해서 오버라이딩이 불가능한 클래스로 인식되어 컴파일시 동적 메소드 호출 기능을 제거하여 메소드 호출을 최적화. 따라서 일반 메소드 호출보다 훨씬 빠름.
클래스 전체를 final로 사용하는 것은 문제가 발생할 가능성이 많으므로 꼭 필요한 경우가 아니라면 피하는 것이 좋음.
메소드 단위로 final을 사용하는 것이 효율적.
* String 대신 StringBuffer 사용
String은 자바가상머신에 의해 StringBuffer 로 변환되어 처리됨.
String 결합(concat) 연산은 내부적으로 StringBuffer로 변환되어 결합 후 다시 String으로 변환되기에 많은 자원이 소모됨.
따라서 String보다는 StringBuffer 혹은 char 배열을 사용하는 것이 빠름.
* 임시 객체 생성 자제
반복문이나 자주 사용하는 메소드 내에서 생성하는 임시 객체들은 가비지 컬렉터에게 부하를 줌.
따라서 반복문이나 자주 사용하는 메소드 내에서 임시 객체 생성을 피하는 것이 좋음.
Java - 성능 저하 원인
* 멀티스레드, 가비지컬렉션, 런타임 바인딩 등은 자바에서 제공하는 편리한 기능이나 프로그램 실행 속도를 느리게하는 원인이 된다. 이러한 기능을 지원하기 위해 보다 많은 자원과 계산이 필요하기 때문.
* 동적 바인딩 / 동적 클래스 로딩
자바는 런타임시 필요한 클래스들을 바인딩. C는 컴파일시 처리. 상대적으로 자바가 함수 호출이 느림.
동적 클래스 로딩은 실행중에 자바 가상 머신에 의해 안전한지 검사하고 초기화하기 때문에 성능 저하를 유발.
* 가비지 컬렉션
사용되지 않는 객체의 메모리를 자동으로 가용 자원으로 돌려주는 유용한 기능이나, 백그라운드에서 스레드로 수행되어야 하기 때문에 성능 저하를 유발.
* 멀티스레드
멀티스레드 사용에 있어 중요한 부분이 스레드간 충돌을 방지하고, 공유 자원에 대한 일관성을 유지하는 것으로 이를 동기화라고 한다.
동기화를 위해 synchronized 키워드를 사용하는데, 스레드 모니터에서는 모든 스레드를 관리하며 synchronized 설정된 스레드가 한 순간에 한 번만 사용되도록 해야한다.
JDK에서 제공되는 많은 메소드들이 synchronized 선언되어 있으며, 백그라운드에서 스레드모니터가 항상 스레드 관리 작업을 수행하는데 많은 자원이 소모되어 성능 저하를 유발
* 동적 바인딩 / 동적 클래스 로딩
자바는 런타임시 필요한 클래스들을 바인딩. C는 컴파일시 처리. 상대적으로 자바가 함수 호출이 느림.
동적 클래스 로딩은 실행중에 자바 가상 머신에 의해 안전한지 검사하고 초기화하기 때문에 성능 저하를 유발.
* 가비지 컬렉션
사용되지 않는 객체의 메모리를 자동으로 가용 자원으로 돌려주는 유용한 기능이나, 백그라운드에서 스레드로 수행되어야 하기 때문에 성능 저하를 유발.
* 멀티스레드
멀티스레드 사용에 있어 중요한 부분이 스레드간 충돌을 방지하고, 공유 자원에 대한 일관성을 유지하는 것으로 이를 동기화라고 한다.
동기화를 위해 synchronized 키워드를 사용하는데, 스레드 모니터에서는 모든 스레드를 관리하며 synchronized 설정된 스레드가 한 순간에 한 번만 사용되도록 해야한다.
JDK에서 제공되는 많은 메소드들이 synchronized 선언되어 있으며, 백그라운드에서 스레드모니터가 항상 스레드 관리 작업을 수행하는데 많은 자원이 소모되어 성능 저하를 유발
JavaScript - 성능 향상 (반복문)
* for-in
반복문 중 가장 느리므로 사용하지 말 것.
for-in외의 반복문은 주어진 배열 객체를 배열의 특성에 맞게 순차적으로 모든 요소를 탐색.
for-in구문은 배열을 배열이 아닌 일반 객체로 취급, 반복 시점마다 객체의 모든 속성을 무작위로 탐색.
* Array.length
반복문 안에서 직접 사용하지 말 것. 변수 선언 후 사용하는 것이 더 빠름.
반복문 안에서 length를 구하게되면 반복횟수만큼 length를 구하는 작업을 반복.
사용예)
var arr = [1, 2, 3];
for (var i=0; i<arr.length; i++) {
// ...
}
==>
var len = arr.length;
for (var i=0; i<len; i++) {
// ...
}
반복문 중 가장 느리므로 사용하지 말 것.
for-in외의 반복문은 주어진 배열 객체를 배열의 특성에 맞게 순차적으로 모든 요소를 탐색.
for-in구문은 배열을 배열이 아닌 일반 객체로 취급, 반복 시점마다 객체의 모든 속성을 무작위로 탐색.
* Array.length
반복문 안에서 직접 사용하지 말 것. 변수 선언 후 사용하는 것이 더 빠름.
반복문 안에서 length를 구하게되면 반복횟수만큼 length를 구하는 작업을 반복.
사용예)
var arr = [1, 2, 3];
for (var i=0; i<arr.length; i++) {
// ...
}
==>
var len = arr.length;
for (var i=0; i<len; i++) {
// ...
}
JavaScript - 성능 향상 (스코프 체인 탐색 줄이기)
* 스코프 체인
탐색 성능을 높이는 것이 본질.
자바스크립트 실행성능 저하는 변수, 객체, 함수의 메모리상 위치 탐색 작업.
* 스코프 체인 구성
활성화 객체(Activate Object) + 전역 객체(Global Object)
* 활성화 객체
함수 내부 접근시 생성. (지역변수, this, arguments 객체)
함수 빠져 나오면 활성화 객체 제거됨 .
* 실행 문맥 (Execution Context) > 스코프 체인 (1, 2) > 활성화 객체 (1) > 전역 객체 (2) 순으로 실행.
* 함수가 전역 속성 참조 순서
실행문맥 > 스코프 체인 > 활성화 객체 (함수) > 스코프 체인 > 전역 객체 순으로 속성 참조
* 활성화 객체에서 전역 변수 사용시
함수 내부에 var LocalVariable = GlobalVariable; 식으로 지역변수화하여 전역속성 탐색을 제거.
탐색 성능을 높이는 것이 본질.
자바스크립트 실행성능 저하는 변수, 객체, 함수의 메모리상 위치 탐색 작업.
* 스코프 체인 구성
활성화 객체(Activate Object) + 전역 객체(Global Object)
* 활성화 객체
함수 내부 접근시 생성. (지역변수, this, arguments 객체)
함수 빠져 나오면 활성화 객체 제거됨 .
* 실행 문맥 (Execution Context) > 스코프 체인 (1, 2) > 활성화 객체 (1) > 전역 객체 (2) 순으로 실행.
* 함수가 전역 속성 참조 순서
실행문맥 > 스코프 체인 > 활성화 객체 (함수) > 스코프 체인 > 전역 객체 순으로 속성 참조
* 활성화 객체에서 전역 변수 사용시
함수 내부에 var LocalVariable = GlobalVariable; 식으로 지역변수화하여 전역속성 탐색을 제거.
피드 구독하기:
글 (Atom)




