http://dhna.tistory.com/44 출처



#define PATHNAME "/Movie/Action"

#define MOVIEDATA           PATHNAME##"/Data"



#, ##, #@

## 연산자
  ## 연산자를 사용해서 토큰을 합성해서 만들어 낼 수 있다. ##은 합치기 연산자 이다.
  ex) #define MACRO_APPEND(str1, str2) printf("%s\n", str1##str2)

# 연산자
  # 연산자는 전달된 인자를 문자열로 변환시킨다.
  ex) #define MACRO_STRING(str) printf("%s\n", #str);

#@ 연산자
  #@ 연산자는 전달된 인자를 문자로 변환시킨다.



미리 정의된 매크로

__STDC__ : 컴파일러가 ANSI C 표준을 따를 경우 1로 정의되며 그렇지 않을 경우
                 정의되지 않는다. C++로 컴파일할 때는 이 매크로가 없다.
__FILE__ : 현재 소스 파일의 완전 경로이다.
__LINE__ : 파일명
__DATE__  : 컴파일될 때의 날짜를 나타내는 문자열이다.
__TIME__ : 현재 소스가 최후로 수정된 날짜와 시간을 나타낸다. 
__TIMESTAMP__ : 현재 소스가 최후 컴파일된 시간을 나타내는 문자열이다.
__func__ : 함수명 (컴파일러가 처리, c99 표준) 
__FUNCTION__  : 함수명 (컴파일러가 처리, 컴파일러마다 다름)



Visual C++에서 미리 정의된 매크로

_DEBUG : 디버그 모드로 컴파일중일 때만 정의된다.
__cplusplus : C++ 모드로 컴파일중일 때만 정의된다.
_DLL : DLL 프로젝트일 때만 정의된다.
_MSC_VER : 비주얼 C++의 컴파일러 버전을 나타낸다. 6.0은 1200으로 정의되며 7.0(닷넷)은 1300으로 정의된다.
_MFC_VER : MFC 라이브러리의 버전값
_ATL_VER : ATL의 버전값
_WIN32 : Win32 환경일 때 정의된다.
_WIN64 : Win64 환경일 때 정의된다.
__COUNTER__ : 참조될 때마다 1씩 증가하는 정수값이다. 유일한 이름을 만들고자 할 때 이 매크로를 사용한다.
                        7.0 이상에서만 제공된다.
_M_ALPHA, _M_IX86, _M_IA64, _M_MPPC : CPU의 종류이다. 플랫폼에 따라 약간씩 코드가 달려져야 할 때 이 매크로를 참조한다. 


http://dhna.tistory.com/44 출처
Posted by 패스맨

댓글을 달아 주세요


출처:http://process3.blog.me/20021963684?Redirect=Log


[STL & MFC Collection 사용상 주의]
-여러 스레드에서 읽는 것은 안전하다.
-여러 스레드에서 각각 다른 컨테이너(컬렉션)에 쓰는것은 안전하다


[위 두 가지 경우 이외에는 전부 안전하지 않다. (모두 동기화(lock)을 걸어주어야 함) ]
-삽입 ,삭제, 조회를 하는 모든 경우에 동기화
-반복자를 수행하는 전부 동기화

[연속 메모리 기반, 노드 메모리기반 STL 컨테이너 차이점을 확실히 알고 사용한다]
Posted by 패스맨

댓글을 달아 주세요

출처 http://minjang.egloos.com/2254472

물론 고수님들에겐 쉬운 문제지만 다음 구조체에서 char data[1]의 역할이 무엇인지 생각 해봅시다.

typedef struct tagWHATTHE {
int data1;
int data2;
char data[1];
} WHATTHE;

모르시는 분들은 최소 1분 정도 생각을 해봅시다.



그래도 잘 모르겠으면 약간의 힌트:

typedef struct tagWHATTHE {
int size;
int type;
char data[1];
} WHATTHE;



char data[1]의 역할은

난생 처음 이런 구조체를 보면 data[1] 변수가 도대체 어떤 의미인지 감을 잡기 힘들다. 왜 이런 변수가 쓰이는지는 직접 예제 코드를 보는 것이 가장 좋을 것 같다.

typedef struct tagHEADER {
int size;
int type;
char data[1];
} HEADER;

// int data_length, int* data;
HEADER* hd = (HEADER*)malloc(sizeof(HEADER) + data_length);
hd->size = sizeof(HEADER) + data_length;
hd->type = 0;
memcpy(hd->data, data, data_length);
fwrite(hd, 1, hd->size, file_handle);

한 마디로 char data[1]의 의미는 길이가 정해지지 않은 데이터를 담기 위한 일종의 더미 변수라고 보면 된다. 예에서도 있듯이 이런 코딩 테크닉은 어떤 데이터의 헤더를 표현할 때 많이 등장한다. 메모리 덩어리를 할당 받고 그것을 이 헤더 타입으로 캐스팅을 하면 앞 부분은 헤더가 놓이고 바로 뒤에 갖고 싶은 가변 길이 데이터를 쉽게 이을 수 있다. 윈도우 프로그래밍을 해보신 분이라면 아마 이런 것을 자주 봤을 것이다. 예를 들면:

typedef struct _RGNDATAHEADER {
DWORD dwSize;
DWORD iType;
DWORD nCount;
DWORD nRgnSize;
RECT rcBound;
} RGNDATAHEADER;

typedef struct _RGNDATA {
RGNDATAHEADER rdh;
char Buffer[1];
} RGNDATA;

RGN이라는 그래픽에서 그리는 영역을 지정하는 클리핑 객체를 담는 자료구조다. RGNDATA에 채워질 데이터가 몇 개나 올지 알 수 없으므로 이렇게 하였다. 또, 대표적인 비트맵 파일 관련 구조체도 빼놓을 수 없다.

typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFO;

배열 크기가 여기는 [1]인데 [0]으로 둬도 사실 문제 없다. 그리고 소켓 프로그래밍할 때 보게 되는 hostent에도 이제는 과거 호환성 때문에만 남았지만 크기가 0인 배열을 볼 수 있다. 그런데 보통 크기 0인 배열을 선언하면 컴파일러가 워닝을 띄운다. 그래서 C99 표준에는 flexible array member라고 해서 맨 마지막 구조체 변수의 선언이 char data[] 처럼 될 수 있도록 하기도 한다.

도대체 왜?

그렇다면 왜 이렇게 했을까? 보다 직관적으로 코드를 만든다면 아래처럼 쓸 수도 있다.

typedef struct tagHEADER {
int size;
int type;
char* data;
} HEADER;

HEADER* hd = (HEADER*)malloc(sizeof(HEADER));
hd->size = 1024;
hd->type = 0;
hd->data = (char*)malloc(hd.size);
...

그러나 이 접근은 단점이 있다. 위에서 예를 들었듯이 이 자료구조를 파일에 쓴다고 하면 헤더 부분 따로 그리고 data 영역을 따로 두 번에 걸쳐 파일 쓰기를 해야 한다. 결국 이 말은 이 자료구조에 접근하려면 헤더 한번, 실제 한번, 즉 두 번의 참조가 필요하다는 이야기다.

여기서 쪼잔하게 따지면 위 코드는 데이터 참조의 지역성(locality)이 줄어들어 캐시 미스를 한번 더 유발할 수 있는 단점도 있다. 요즘 프로세서들 캐시가 수 메가 바이트니 이 정도 괜찮다라는 생각을 함부로 하지 말자. 정말 성능이 중요한 프로그램은 이런 사소한 지역성 차이에서 오는 차이를 결코 무시할 수 없다. 비슷한 예로 “구조체의 배열(Array of Structure)” 이냐 “배열의 구조체(Structure of Array)”라는 문제도 있다 (우리말과 영어의 어순이 반대라 이거 이름이 참 헷갈린다). 간단한 예를 보면..

구조체의 배열(Array of Structure, AoS):

struct {
double x;
double y;
double z;
} vector[4];

배열의 구조체(Structure of Array, SoA):

struct {
double x[4];
double y[4];
double z[4];
} vector_set;

각각 상황에 따라 적절히 선택해서 골라야 한다. 사소해 보이지만 경우에 따라 큰 성능 차이가 나타날 수 있다.

AoS 같은 접근은 루프 한 순회에서 모든 원소들이 접근될 때 유리하다. vector[i]을 읽으면 일단 i번 째 x, y, z는 모두 캐시에 올라오기 때문이다. 반면 원소는 3개인데 루프에서 고작 x원소만 접근 된다면? 이 vector 배열이 매우 크다면 손실은 심각하다. 그럴 때는 SoA 구조가 바람직하다. 그 외에도 사소한 영향을 더 생각할 수 있지만 생각보다 글이 길어져서 이쯤에서 그만..

한줄요약: char data[1]; 같은 것이 보여도 쫄지 맙시다.

 

Posted by 패스맨

댓글을 달아 주세요


출처 :

http://www.sqlworld.pe.kr



1. 테스트를 위한 임시 테이블 만들기와 데이터 추가하기

예전의 테스트 처럼 sqlworld 데이터베이스를 이용하여 실제 상황을 재현해 보도록 하겠습니다. 현재 sqlworld 데이터베이스의 옵션은 다음과 같습니다.

o 데이터베이스 복구모델 : 최대
o 자동 축소기능 : 사용안함

다음 [그림 1]은 현재 sqlworld의 데이터베이스와 로그 사이즈를 보여줍니다.


[그림 1]

우선 현재의 sqlworld 데이터베이스를 백업 받도록 하겠습니다.(모든 백업의 기본은 전체 백업입니다)

USE Master
GO

BACKUP DATABASE sqlworld TO DISK = 'E:\Data\sqlworld.bak'

1) 테이블 만들기

다음과 같이 테스트 테이블 Test_Log를 만들도록 하겠습니다.

USE sqlworld
GO

CREATE TABLE Test_Log
(
col1 int PRIMARY KEY,
col2 char(1000)
)

다음과 같이 스크립트를 이용해서 레코드를 추가하도록 하겠습니다.

SET NOCOUNT ON
GO

DECLARE @num int
SET @num = 1
WHILE @num < 5001
BEGIN
INSERT INTO Test_Log VALUES(@num, REPLICATE('A',1000))
SET @num = @num + 1
END

위 작업을 통해서 오천개 정도의 레코드가 Test_Log 테이블에 추가되었습니다. 이로 인하여 sqlworld 데이터 사이즈와 로그 사이즈가 증가했습니다. 아래 [그림 2]가 그 내용을 확인해주고 있습니다.


[그림2]

만일 sqlworld 데이터베이스 복구 모델이 '단순' 이었다면 위와 같은 작업이 완료가 되면 로그가 자동으로 제거되어 [그림 2] 처럼 로그 사이즈가 증가하지 않을 것입니다.(이 내용이 잘 이해되지 않으면 바로 이전의 강좌를 다시한번 읽어보시기 바랍니다)

2) 데이터를 변경하여 데이터와 로그 사이즈 증가시키기

다음과 같이 데이터를 변경하고 삭제하여 로그 사이즈를 증가시켜 보겠습니다.

UPDATE Test_Log Set col2 = REPLICATE('B',1000) WHERE col1 < 1000
GO
DELETE FROM Test_Log WHERE col1 < 2000
GO
DELETE FROM Test_Log WHERE col1 < 4000

위 작업을 수행하니 Test_Log 테이블의 데이터 변경에 대한 로그와삭제에 대한 로그가 증가함에 따라 sqlworld 데이터베이스의 사이즈는 다음 [그림 3]과 같이 변하였습니다.


[그림3]

로그 파일은 0.99 MB에서 6.74 MB 로 사이즈가 증가함을 알 수 있습니다.

이처럼 트랜잭션이 발생함에 따라 로그가 계속 쌓이면서 로그 파일의 사이즈가 계속 증가함을 알 수 있습니다. 이제 확인할 내용은 로그 백업을 하면 로그가 줄어드는지, 그리고 로그 파일의 사이즈는 어떻게 되는지 하는 것입니다.

2. 트랜잭션 로그 백업을 통한 로그 줄이기

로그 백업은 예전에 배운 데이터베이스 백업과 비슷한 방법으로 이루어 집니다. EM을 통해서 할 수도 있고 QA에서 직접 BACKUP LOG 문을 이용하여 백업 받을 수도 있습니다. 이 테스트에서는 QA를 이용하여 현재 sqlworld 데이터베이스의 로그를 백업받도록 하겠습니다.

USE Master
GO

BACKUP LOG sqlworld TO DISK = 'E:\Data\sqlworld_log.bak'

수행하는 방법은 BACKUP DATABASE 문과 비슷합니다.

만일 로그를 백업 받지는 않고 단지 현재의 로그만 지우고 싶으면 다름과 같이 TRUNCATE_ONLY 옵션을 사용하면 됩니다.

USE Master
GO

BACKUP LOG WITH TRUNCATE_ONLY

이렇게 로그를 백업 받은 후의 sqlworld 데이터베이스의 사이즈를 보니 다음 [그림 4]와 같이 변한 것을 볼 수 있습니다.


[그림4]

로그 사이즈가 3.64 MB 에서 1.84 MB로 줄어 들었습니다. 하지만 로그 파일의 사이즈는 아직도 6.74 MB로서 원래 사이즈를 그대로 유지하고 있습니다. 결국 4.9 MB의 빈 공간이 놀고(?) 있게 됩니다.

3. DBCC SHRINKDATABASE을 이용한 로그파일 사이즈 줄이기

DBCC SHRINKDATABASE 을 이용해서 수작업으로 비어있는 로그 사이즈를 없애서 로그 파일의 사이즈를 축소해 보도록 하겠습니다.

USE Master
GO

DBCC SHRINKDATABASE(Sqlworld)

결과는 다음 [그림 5]와 같이 변한것을 알 수 있습니다.


[그림5]

로그 파일의 사이즈가 [그림 4]와 비교 할 때 6.74 MB에서 2.49 MB로 줄어든 것을 알 수 있습니다. DBCC SHRINKDATABASE에 의해 줄어드는 로그 파일의 사이즈는 실제 데이터 파일의 빈 공간이 많을 수록 효과가 좋습니다. DBCC SHRINKDATABASE 또는 DBCC SHRINKFILE에 대한 내용은 이전의 데이터베이스에 대한 강좌를 참고해 주시기 바랍니다.

4. 정리

로그 파일 사이즈 문제를 가지고 질문을 하시는 경우가 상당히 많습니다. 지금까지 설명드린 내용이 도움이 되었으면 합니다. 데이터베이스 관리자는 항상 로그 파일에 대한 관심을 가지고 모니터링을 해야 합니다. 하드디스크의 여유 공간은 충분한지도 수시로 확인하셔야 합니다. 그렇지 않으면 TempDB가 꽉 찼다는 등의 오류가 발생하게 됩니다.



exec sp_helpdb dbname
backup log dbname with truncate_only
DBCC shrinkfile(dbname_log  ,5)???????????

'Programing > DB' 카테고리의 다른 글

트랜잭션 로그 줄이기 (출처:http://www.sqlworld.pe.kr)  (0) 2010.12.08
SET NOCOUNT ON  (0) 2010.12.07
Posted by 패스맨

댓글을 달아 주세요


http://studiostyl.es/schemes/wekeroad-ink
Posted by 패스맨

댓글을 달아 주세요

SET NOCOUNT ON

Programing/DB 2010.12.07 10:26 |

 SET NOCOUNT 옵션을 ON으로 설정하면

Transact-SQL 문의 영향을 받은 행 수를 나타내는 수가 반환되지 않음.

SET NOCOUNT OFF 로 설정하면 이 수가 반환됨.


SET NOCOUNT ON 으로 설정되어 있어도 @@ROWCOUNT함수는 업데이트됨.
저장 프로시저의 각 명령문에 대해 클라이언트에게 DONE_IN_PROC 메시지를 보내지 않음.
MS SQL Server 와 함께 제공된 유틸리티를 사용해 쿼리 실행시 (select, insert, update,delete등)
Transact-SQL 문 끝에 "nn개 행 적용됨" 메시지가 표시되지 않음.

실제 데이터를 많이 반환하지 않는 몇몇 명령문이 포함된 저장 프로시저의 경우 ,
이 유틸리티를 사용하면 네트워크 소통량이 크게 줄기 때문에 성능이 눈에 띄게 향상됨.

'Programing > DB' 카테고리의 다른 글

트랜잭션 로그 줄이기 (출처:http://www.sqlworld.pe.kr)  (0) 2010.12.08
SET NOCOUNT ON  (0) 2010.12.07
Posted by 패스맨

댓글을 달아 주세요

HANDLE WINAPI CreateMutex(
  __in_opt  LPSECURITY_ATTRIBUTES lpMutexAttributes,
  __in      BOOL bInitialOwner,
  __in_opt  LPCTSTR lpName
);


//중복 프로세스 실행 방지.
HANDLE hMu=CreateMutexA(NULL, FALSE,"abcde");
 if(GetLastError() == ERROR_ALREADY_EXISTS)
 {
  CloseHandle(hMu);
  MessageBoxA(NULL, "ABC","ABC",MB_OK);
  exit(1);
 }

bInitalOwner 값이 true 이면 뮤텍스를 생성한 스레드가 소유권을 가지게 되고
false 이면 가지지 않게끔 생성.

WaitForSingleObject, WaitForMultipleObjects 등의 함수 사용시
해당스레드가 소유권을 가지게 됨.
소유권은 ReleaseMutex를 호출하거나 해당 스레드가 종료 될때까지 유지됨.
이때 Wait함수 호출시 bInitalOwner가 TRUE일경우 소유권이 중첩되게 되고
ReleaseMutex를 한번 호출해서 중첩된 소유권이 모두 사라지지않는다...

그래서 bIntialOwner를 FALSE 로 생성하는게 편하다.

출처: http://sinarn.blog.me/130078038010 


Posted by 패스맨

댓글을 달아 주세요

출처 :  http://blog.naver.com/neojzs.do


1. 컴파일러의 최적화 옵션에서 '속도 최적화'대신에 '코드 크기 최소화' 설정이 캐쉬 성능을 향상시켜 좀 더 빠른 코드를 얻을 수 있게 한다.

2. 각 CPU(인텔의 SSE, SSE2 / AMD의 3DNow )의 SIMD 를 활용하는 함수를 만들어 사용해라

3. 가능한 나눗셈 연산을 최소화해라.
예)
<수정전>
b = a / m;  
c = d / m;

<수정후>
m = 1 / m;
b = a * m;
c = d * m;

4. switch문을 쓸 때 연속된 수치를 사용해라. 그러면 VC가 컴파일할 때 테이블형태로 만들어 조건분기보다 빠르게 사용된다.
예)
case 0 :  
case 1 :
case 2 :

예2)
case 10 :
case 9 :
case 8 :

잘못된 예)
case 2 :
case 4 :
case 3 :

5. 펜티움 Pro이상에서는 CMOVxx / FCMOVxx 같은 조건적 이동 명령을 이용할 수 있다. 간단한 내용은 IF문보다 다음과 같은 코드를 사용해라.

A == 0 ? choice1 : choice2;

6. 자주 사용하는 자료 구조는 32바이트의 배수로 정렬시켜 사용해라. 컴퓨터의 캐쉬라인을 최적으로 사용할 수 있기 때문에 전체 성능이 크게 좋아진다. 펜티움 4는 L1의 캐시라인크기가 64바이트이고 L2가 128바이트, AMD 애슬론은 L1, L2가 64바이트이다. 이 기법을 패딩(Padding)이라고 한다.

7. sin, cos, tan, exp, arcsin등의 수학 함수는 가급적 피하고 룩업 테이블이나 비슷한 형태로 간략하게 함수로 만들어서 사용해라.

8. 부동 소수점은 가급적 double보다 float를 사용해라. double의 나눗셈은 39사이클이 걸리지만 float은 19사이클만 걸린다. (단, 2의 제곱수로 나누면 8사이클정도만 걸린다) 그리고 float형 일때는 반드시 뒤에 f를 붙여라. float a = 1.0; 보다 float a = 1.0f; 가 더 빠르다.

9. 순서에 상관이 없다면 후연산자 보다 선연산자를 사용해라. a++; 보다 ++a;를 사용하라는 것이다.

10. 가능하다면 const를 사용해라. 컴파일러가 좀더 최적화가 잘 해줄 가능성이 생기게 된다.

11. 메모리 관리 함수는 따로 만들어서 사용하는 것이 좋다. malloc과 free는 느리기 때문에 시작할 때 메모리를 많이 잡은 뒤 관리해서 사용하는 것이 좋다. 퀘이크1 이 좋은 예이다

'Programing > 메모리 관리' 카테고리의 다른 글

코드 최적화에 대한 Tip  (0) 2010.09.21
Posted by 패스맨

댓글을 달아 주세요