반응형

블로킹

디바이스에 처리 요청을 걸어 놓고 응답을 대기하는 함수를 호출할 때 스레드에서 발생하는 대기 현상을 블로킹이라고 한다.

소켓뿐만 아니라 파일 핸들에 대한 함수를 호출했을 때도 이러한 대기 현상이 발생하는 것을 모두 블로킹이라고 한다.

블로킹이 발생하는 스레드에서는 CPU 연산을 하지 않는다. 따라서 CPU 사용량이 0%가 된다. 즉, 스레드는 waitable state인 상태이다.

블로킹 소켓

송신 버퍼는 사용자가 데이터를 넣고 운영체제가 뺀다.

수신 버퍼는 운영체제가 데이터를 넣고 사용자가 뺀다.

 

수신 버퍼가 완전히 비어 있으면 데이터를 수신하는 함수는 블로킹이 일어난다.

송신 버퍼가 완전히 차면 데이터를 송신하는 함수는 블로킹이 일어난다.

 

TCP 통신에서 수신측 수신 버퍼가 꽉 차면, 송신측 송신 함수가 블로킹 상태가 되며, TCP 연결은 끊어지지 않는다.

또한 송신자와 수신자 사이의 다른 네트워킹이 경쟁에서 밀리지 않는다.

 

UDP 통신에서 수신측 수신 버퍼가 꽉 차면, 다음 데이터그램은 버려지며(데이터그램 유실), TCP와 달리 송신측 송신 버퍼가 꽉 차지 않으면, 송신 함수에 블로킹이 발생하지 않는다.

또한 UDP를 속도 제한 없이 마구 송신하면 주변의 네트워킹이 경쟁에서 밀립니다. 이 때문에 주변의 네트워킹이 두절되기도 하고, 혼잡 현상이 발생한다.

 

반응형
반응형

1. 인덱스의 정의

  • 인덱스(Index)는 테이블의 특정 컬럼(column)에 대해 검색 속도를 높이기 위해 추가로 만든 자료 구조
  • 책의 목차처럼, 원하는 데이터가 테이블 전체를 뒤지지 않고도 바로 위치를 찾을 수 있게 해주는 구조

2. 인덱스의 종류

1) B-Tree 인덱스 (가장 흔함)

  • 균형 이진 트리(B+Tree) 구조 사용
  • 장점:
    • 특정 값 검색: O(log n)
    • 범위 검색: 효율적 (e.g., WHERE age BETWEEN 20 AND 30)
  • 사용 예시: PRIMARY KEY, UNIQUE 인덱스

2) Hash 인덱스

  • 해시 테이블 기반
  • 장점:
    • 정확한 값 검색: O(1) 평균
  • 단점:
    • 범위 검색에는 부적합
  • 사용 예시: MySQL MEMORY 엔진

3) 기타

  • Full-text 인덱스: 문자열 검색 최적화
  • Spatial 인덱스: 지리정보 데이터 최적화
  • Composite(복합) 인덱스: 여러 컬럼 조합 검색에 사용

B-Tree 와 Hash Index 시간 복잡도 비교

연산 종류 B-Tree (또는 B+Tree) Hash 설명
정확한 값 검색 (Equality lookup) O(log N) O(1) 평균O(N) 최악 Hash는 정확 검색에 특화된 순간이동 느낌. B-Tree는 계층을 타고 내려가는 구조.
범위 검색 (Range query) O(log N + K) 불가능 Hash는 키→버킷 맵핑이라 순서를 모름. B-Tree는 정렬된 상태라 범위 탐색 가능.
정렬된 순회 (Ordered scan) O(N) 불가능 Hash는 정렬 상태를 유지하지 않음.
삽입 (Insert) O(log N) O(1) 평균O(N) 재해시 발생 시 Hash는 공간 부족 시 전체 테이블 재정비가 필요해 최악이 무겁다.
삭제 (Delete) O(log N) O(1) 평균 Hash는 버킷만 정리하면 OK.
메모리 사용량 중간 Hash는 충돌 방지를 위해 여분 메모리를 더 들고 다닌다.

 

반응형

'DataBase > MySQL' 카테고리의 다른 글

[MySQL] 행, 열 변환 작업  (0) 2021.08.04
[MySQL] AUTO_INCREMENT 초기화  (0) 2021.02.01
[MySQL] WITH 재귀(RECURSIVE) 쿼리 계층구조  (0) 2020.07.20
[MySQL] CASE 문  (0) 2020.07.20
[MySQL] DATE_FORMAT 날짜데이터 형식 변환  (0) 2020.07.20
반응형

1. 인라인 함수

1) ODR(One Definition Rule) 완화 → 헤더에 함수를 정의할 수 있게 함

이게 사실상 inline의 본래 의미입니다.

  • 함수 정의를 헤더 파일에 적어도 된다
  • 여러 번 포함되더라도 “복제 오류”가 나지 않도록 조절한다

즉, 링커 충돌을 막는 장치.

이 특성 덕분에 템플릿 함수는 대부분 inline 형태로 돌아다니죠.

2) 컴파일러에게 “이 함수는 인라인해도 괜찮아”라는 힌트

단, 명령이 아니라 힌트입니다.

컴파일러가 판단해서

  • 최적화 레벨
  • 함수 크기
  • 코드 중복 비용
    등을 고려한 뒤 인라인할지 말지 결정합니다.

2. 인라인 함수의 역할

함수 호출을 없애고 코드 본문을 호출 지점에 삽입해도 된다는 권한 제공

여기서 “역할”은 다음과 같아요:

  • 함수 호출 오버헤드 제거 가능
  • 작은 함수의 호출 비용을 없애 성능 개선 유도
  • 헤더 파일에 정의된 함수가 여러 번 포함될 때 링킹 오류 방지
반응형

'Programming Language > C++' 카테고리의 다른 글

Using 키워드  (0) 2025.11.06
폴드 표현식  (0) 2025.11.06
람다 표현식  (0) 2025.11.06
범위 기반 for 문  (0) 2025.11.06
L-Value 와 R-Value  (0) 2025.11.06
반응형

ECS(Entity-Component-System)

ECS는 게임엔진, 시뮬레이션, 고성능 서버 등에서 자주 쓰이는 아키텍처입니다. 목적은 데이터 중심 설계(Data-Oriented Design) 으로 캐시 친화적이고 병렬화하기 쉬운 구조를 만드는 것에 있다.

 


핵심 개념

 

  • Entity (엔티티): 고유 ID. 아무런 데이터 자체는 없음. (예: Entity { id: 123 })
  • Component (컴포넌트): 순수 데이터 구조체(POCO). 예: Position { float x,y }, Velocity { float vx, vy }. 로직 없음(또는 최소).
  • System (시스템): 특정 컴포넌트 집합을 읽고 쓰며 동작을 수행하는 코드. 예: 물리 시스템은 Position+Velocity를 업데이트.

장점

  • 캐시 친화성(SoA 스타일): 같은 타입의 컴포넌트를 연속 배열로 보관하면 반복 접근이 빠름.
  • 유연성: 엔티티에 컴포넌트를 조합하여 다양한 오브젝트 표현 가능(상속 필요 없음).
  • 병렬화 쉬움: 시스템을 컴포넌트 접근 패턴에 따라 병렬 실행할 수 있음(읽기/쓰기 분리).
  • 런타임 구성 가능: 게임 객체를 런타임에 쉽게 변경(컴포넌트 추가/삭제).
  • 테스트/유지보수: 데이터와 로직 분리로 모듈화가 용이.

단점

  • 설계 복잡성(특히 복잡한 관계 표현)
  • 컴포넌트 간 의존성 관리 필요
  • 작은 객체 고빈도 생성/파괴 비용

주요 구현 전략(아키텍처)

1. Sparse Set (component-per-type storage)

  • 각 컴포넌트 타입이 std::vector<Component> 같은 연속 배열을 가짐.
  • 엔티티→인덱스 맵(예: sparse array)으로 빠른 조회.
  • 장점: 간단하고 컴포넌트 추가/삭제 성능 좋음, 캐시 좋음.
  • 단점: 여러 컴포넌트 조합으로 반복 조회할 때 교차 캐시 미스 가능.

2. Archetype (데이터-지향, 행 기반)

  • 엔티티가 가진 컴포넌트 조합(아키타입)에 따라 콜렉션(테이블/청크)에 묶음 저장.
  • 같은 아키타입엔 모든 컴포넌트 배열들이 함께 배치되어 있어 특정 조합 쿼리 빠름.
  • 장점: 특정 조합을 자주 쓴다면 매우 빠름(데이터 로컬리티).
  • 단점: 엔티티의 컴포넌트가 바뀌면 아키타입 이동(복사 비용). 복잡도↑.
  • 대표: Unity DOTS(엔티티 컴포넌트 아키텍처) 스타일.

3. Hybrid

  • 상황에 따라 sparse set + 일부 아키타입 최적화 등 혼합.

컴포넌트 저장 방식: AoS vs SoA

  • AoS (Array of Structures): struct Entity { Position p; Velocity v; ... } — 객체 단위로 메모리에 있음.
  • SoA (Structure of Arrays): positions[], velocities[] 각각 연속 배열 — 반복 작업 시 캐시 효율 우수.
    ECS는 보통 SoA 성향(컴포넌트 타입별 연속 저장)을 취함.

Archetype(청크) 기반 간단 설명

  • 엔티티가 가진 컴포넌트 조합(예: [Position, Velocity, Sprite])마다 하나의 청크(table) 를 가짐.
  • 각 청크는 컴포넌트별 SoA 배열을 내부에 갖고 있어, 같은 조합에 있는 엔티티들을 한 번에 빠르게 처리할 수 있음.
  • 쿼리(예: Position+Velocity)는 해당 조합이 있는 모든 청크를 순회.
  • 엔티티가 컴포넌트를 추가/삭제하면 청크 간 복사가 발생(이동).
  • 장점은 특정 조합이 매우 빈번하면 최고 성능. Unity ECS, Flecs 같은 라이브러리가 이 방식.

자주 하는 실수 / 피해야 할 것

  • 컴포넌트를 너무 큰 덩어리로 만들기(데이터 로컬리티 악화).
  • 시스템이 서로 너무 많이 의존하게 만드는 것(테스트/병렬화 어려움).
  • 아키타입 이동 비용을 무시하고 매 프레임 컴포넌트 추가/삭제 다발 발생시키는 것.

 

 

반응형

'Computer Science' 카테고리의 다른 글

Network 개념 정리  (0) 2025.10.28
개념 정리  (0) 2025.10.27
반응형

트랜잭션(Transaction)

데이터베이스의 상태를 변경하는 하나의 논리적 작업 단위입니다. 이 작업들은 모두 성공하거나 모두 실패하며, 오류 복구를 단순화하고 데이터의 일관성과 신뢰성을 보장합니다. 또한, 웹에서는 클라이언트와 서버가 데이터를 주고받는 일련의 과정을 의미하기도 합니다. 

트랜잭션의 ACID 속성

속성 설명
원자성(Atomicity) 트랜잭션 내의 모든 작업이 성공하거나 실패해야 합니다.

작업 묶음이 쪼개지지 않고 하나처럼 움직여야 한다는 원리.
실패하면 전체가 롤백되고, 성공하면 전체가 커밋됩니다.
일관성(Consistency) 트랜잭션이 수행되는 동안 데이터베이스의 일관성이 유지됩니다.

트랜잭션 전후로 데이터 규칙, 제약조건, 도메인 법칙이 깨지지 않는 것.
예: 재고가 음수가 되면 안 된다는 규칙 같은 것들.
고립성(Isolation) 다른 트랜잭션의 영향을 받지 않고 독립적으로 실행됩니다.


동시에 여러 트랜잭션이 실행되더라도
서로 방해하지 않고 독립적으로 보이게 해야 한다는 원칙.
바로 여기서 격리 수준이 등장합니다.
Isolation은 하나의 철학이고, Isolation Level은 그 철학을 얼마나 강하게 적용할지 정한 옵션입니다.
지속성(Durability) 성공적으로 완료된 트랜잭션의 결과는 영구적으로 반영됩니다.

트랜잭션이 커밋되면
정전, 서버 고장, 시스템 재부팅 등에도 데이터는 살아남는다는 보장.
스토리지 단까지 안전히 기록되는 것을 의미합니다.

트랜잭션 격리 수준

격리 수준 Dirty Read Non-Repeatable Read Phantom Read 특징 요약 
Read Uncommitted 허용 허용 허용 거의 격리 없음. 읽기 성능 최우선 환경에서만 사용
Read Committed 방지 허용 허용 대부분의 DB 기본값. 커밋된 데이터만 읽는다
Repeatable Read 방지 방지 DB마다 다름 (MySQL은 방지) 같은 행을 항상 동일하게 본다
Serializable 방지 방지 방지 완전한 직렬화. 가장 안전하지만 가장 비용 높음

트랜잭션 격리 수준별 예시

1) Read Uncommitted

마치 창고 문이 열려 있는데, 안에서 아직 포장 중인 상품을 미리 들여다보는 느낌.

✅ T2가 커밋하지 않은 값도 읽을 수 있음 (Dirty Read)

예시

  • T2: 잔액을 100에서 0으로 변경 중(아직 커밋 안됨)
  • T1: 잔액 조회 -> 0 으로 보임
  • T2: 롤백
  • T1: "어? 방금 0이었는데 왜 다시 100이지?"

혼란이 생기는 환경.

2) Read Committed

남이 박스를 닫고 테이핑 완료해야만 볼 수 있는 상태.

✅ Dirty Read 방지
❌ Non-Repeatable Read 발생

예시

  • T1: 잔액 조회 -> 100
  • T2: 잔액을 150으로 변경 후 커밋
  • T1: 다시 잔액 조회 -> 150
  • T1이 같은 트랜잭션 안에서 두 번 읽었는데 값이 바뀜

3) Repeatable Read

일단 문을 닫아 잠그면, 그 안의 물건은 내가 보는 동안 바뀌지 않는 느낌.

✅ Dirty Read 방지
✅ Non-Repeatable Read 방지
❌ Phantom Read 가능(DB 종류에 따라 다름)

예시(고전적인 버전)

  • T1: “잔액이 100인 계좌 조회”
  • T2: 그 계좌 수정 → 커밋
  • T1: 같은 계좌 다시 조회 → 여전히 100으로 보인다 (스냅샷 유지)

하지만
T1이 “잔액이 100 이상인 모든 계좌 목록”을 읽을 때는:

  • T1: 목록 읽기 → 5개
  • T2: 새 계좌 추가 → 커밋
  • T1: 목록 다시 읽기 → 6개 (행이 “훅” 나타남)

이 새롭게 나타난 행이 Phantom(유령) 현상.

참고: MySQL(InnoDB)
Repeatable Read에서 Gap Lock을 사용해 Phantom Read도 방지함.

4) Serializable

모든 트랜잭션을 “차례대로 줄 세워서” 처리하는 느낌.

✅ Dirty Read 방지
✅ Non-Repeatable Read 방지
✅ Phantom Read 방지
✅ 가장 안전
❌ 성능 부담 가장 큼 (대기시간 증가)

예시

  • T1: “잔액 100 이상 계좌 목록 조회 시작”
  • T2: 새로운 계좌 추가 시도 → T1이 끝날 때까지 대기
  • T1이 끝난 뒤에야 T2가 실행됨

DB가 트랜잭션을 하나씩 순차적으로 실행하는 것처럼 보이게 만든다.

트랜잭션 예시

BEGIN
   여러 개의 SQL 실행
COMMIT 또는 ROLLBACK

 

반응형
반응형

using 키워드

1. 상속 멤버의 접근 지정자 변경 가능(protected -> public 으로 변경할 때만 사용 가능)

#include <iostream>

using namespace std;

class character {
public:
  character() : hp(100), power(100) {};

protected:
  int hp;
  int power;
};

//character 클래스를 상속 받은 player 클래스
class player : public character {
public:
  player() {};
};

//기본 Monster 클래스
class monster {
public:
  monster() {};

protected:
  void get_damage(int _damage) {};
  void attack(player target_player) {};
  void attack_special(player target_player);
};

void monster::attack_special(player target_player) {
  cout << "기본 공격 : 데미지 - 10 hp" << endl;
}

//몬스터 A는 기본 Monster 클래스로부터 상속
class monster_a : public monster, character {
public:
  // 부모 클래스에서 protected로 선언된 get_damage 함수 접근 범위 변경
  using monster::get_damage;
private:
  //상속받은 함수 오버라이딩 
  void attack_special(player target_player);
};

void monster_a::attack_special(player target_player) {
  cout << "인텡글 공격 : 데미지 - 15 hp" << endl;
}

//몬스터 A는 기본 Monster 클래스로부터 상속
class monster_b : public monster, character {
private:
  //상속받은 함수 오버라이딩 
  void attack_special(player target_player);
};

void monster_b::attack_special(player target_player) {
  cout << "가상 공격 : 데미지 - 0 hp" << endl;
}

int main() {
  monster_a mon_1;
  monster_b mon_2;

  mon_1.get_damage(100);
  // 아래 코드는 오류가 발생합니다.
  // mon_2.get_damage(100);

  return 0;
}

2. 열거형 사용 선언(구조체 내부에 정의된 열거형처럼 사용할 수 있게 된다.)

#include <iostream>

using namespace std;

enum class weapon : int { gun, arrow, machine_gun };

class monster {
public:
  weapon weapon_type;
};

struct weapon_class {
  using enum weapon;
};

int main() {
  monster monster_obj;
  weapon_class weapon_obj;

  monster_obj.weapon_type = weapon::gun;
  monster_obj.weapon_type = weapon_obj.arrow;
  monster_obj.weapon_type = weapon_class::machine_gun;
 
  return 0;
}

3. 별칭 만들기

using MapType = std::map<int, std::string>;

template<typename T>
using Vec = std::vector<T>;
반응형

'Programming Language > C++' 카테고리의 다른 글

인라인(inline)  (0) 2025.11.10
폴드 표현식  (0) 2025.11.06
람다 표현식  (0) 2025.11.06
범위 기반 for 문  (0) 2025.11.06
L-Value 와 R-Value  (0) 2025.11.06

+ Recent posts