Flutter 렌더링 관련 두가지 주요한 명제가 있다. Everything's a Widget. A widget is an immutable description of part of a user interface Flutter 는 성능상의 이유로 widget 을 immutable 하게 관리한다. 만약 mutable 하다면, 위젯의 상태가 변했을 때 업데이트를 위해선 모든 위젯 내부의 상태를 비교해야 한다. 이를 immutable 하게 관리하고, 위젯의 상태가 변하면 새로운 위젯을 생성하는 방식을 사용하면, 업데이트를 위해서 단순히 같은 인스턴스인지만 확인하면 된다. Flutter 는 어떻게 UI 의 상태를 관리할까? 이를 이해하려면 Flutter 가 관리하는 3가지 트리에 대하여 알아야 한다. Tree ..
Dart 의 Event Loop 이란 무엇인가? 프로그램 수행중에 mouse click, file I/O 완료 등과 같은 다양한 이벤트가 비동기적으로 일어나는데, Dart 에선 이를 적절히 처리하기 위해 각 isolate 별로 event loop 를 유지한다. 어플리케이션이 실행되면 event loop 에선 매번 루프를 돌며 evenet queue 에 새롭게 쌓인 이벤트를 처리한다. 위 이미지에선 event loop 가 event queue 에서만 이벤트를 꺼내오만, event queue 외에도 microtask queue 가 존재하며, event loop 에서는 microtask 를 event 보다 우선적으로 처리한다. (이벤트 큐가 쌓여있을 때 새롭게 microtask 가 들어오면, 다시 micro..
Isolate 가 뭘까? Dart 는 많은 다른 프로그래밍 언어와 마찬가지로 스레드를 사용하여 여러개의 작업을 동시에 처리한다. 그러나, 일반적인 많은 언어들과 달리 Dart 의 스레드는 메모리를 공유하지 않는다. Dart 에선 이러한 특별한 방식의 수행 스레드를 Isolate 라고 정의한다. 각각의 isolate 는 다른 힙 영역을 사용하기 때문에 멀티 스레딩의 비교적 복잡한 문제인 동기화에 대하여 고려할 필요가 없다. 즉, race conditions 같은 문제가 기본적으로 발생하지 않는다. 왜 Isolate 를 사용하는가? 간단한 답변으로 코드를 병렬적으로 수행하기 위함이다. 특히 멀티코어를 사용할 경우엔 물리적으로 병렬적인 코드가 수행되어 훨씬 빠른 속도를 퍼포먼스를 보일 것이다. 그러나 이 답변..
왜 필요한가? 싱글코어 환경에 CPU에서 여러개의 태스크를 병렬적으로 처리하는 것 처럼 보이려면 스케쥴링은 필수적이다. 싱글코어가 아니더라도, 멀티코어에서 실제 병렬적으로 처리되는 태스크는 코어 개수만큼에 불과하기 때문에 마찬가지로 스케쥴링이 요구된다. 그 뿐만 아니라, 태스크간에 우선순위도 분명 존재하기 때문에 이를 적절히 조절하여 사용성을 높이기 위해선 스케쥴링은 필수적이다. 간단하게 어떤 태스크가 수행중이라고 마우스 입력을 처리하는 태스크가 무시되선 안되는 상황을 생각해 볼 수 있다. -> 마우스 입력을 처리하는 것은 인터럽트이기 때문에 위 예시는 적절하지 않다. 다른 예시로, 웹 브라우저와 바이러스 스캐너, 워드 프로세서 3가지 프로그램이 동작하고 있다고 가정해보자. OS는 세가지 프로그램 중 ..
Overview 전송계층은 물리적인 연결, 인접 스테이션간의 신뢰성 있는 데이터 전송부터 네트워크 간의 연결 보장과 같은 1~3 계층까지의 구현에 문제가 없음을 가정하고, end-to-end 간의 신뢰성있는 데이터 전송을 보장하는 것을 목표로 한다. 전송계층에선 보내고자하는 메세지를 세그먼트 단위로 쪼개며, 각 세그먼트의 헤더에 시작지와 도착지의 포트 번호를 적어 이를 3계층에 내려준다. 즉, 응용계층에서는 데이터의 크기에 대한 큰 고려 없이 이를 전송계층에 전달하며, 전송계층에서 이를 적절하게 쪼개어 목적지로 보내고, 수신측에서는 반대로 이를 합쳐서 다시 응용계층으로 올려준다. 여기서 end-to-end 간의 데이터 전송이란 호스트상에 존재하는 여러개의 어플리케이션간의 전송을 의미한다. 쉬운 예시로, ..
OS에서 프로세스는 자원 소유권의 단위이다. 여기서 말하는 자원에는 여러 종류가 존재하는데, 프로그램 실행을 위한 명령어 집합이 포함될 코드 영역, 프로그램 수행 중 여러 값을 저장하는데 사용될 힙 영역, Last-In-First-Out 방식으로 함수 호출과 지역변수를 저장하는데 활용될 스택 영역, 초기화된 글로벌 변수와 정적 변수가 저장될 데이터 영역, 초기화 되지 않은 글로벌 변수와 정적 변수가 저장될 BSS 영역 이 모두 프로세스가 소유하는 자원에 해당한다. 초기화 여부로 데이터 영역과 BSS 영역 영역을 구분하는 이유가 뭘까? 가장 큰 이유는 BSS 영역을 구분하여 프로그램 바이너리 파일(실행파일)의 크기를 줄일 수 있다는 것이다. 바이너리 파일은 기본적으로 코드 영역, 데이터 영역, BSS 영역..
인터럽트 핸들러는 빠르게 실행되어야 하면서도 동시에 많은 양의 작업을 처리해야 한다. 이 2가지 목표는 서로 충돌하기 때문에, 리눅스 커널에서는 인터럽트 핸들러의 동작을 각각의 목표를 위한 2가지 파트, halves 로 분리하여 구현한다. 즉, 인터럽트 핸들러는 top half 와 bottom half 로 구분되는데, top half 에선 빠르게 처리되어야 하는 작업이 수행되며, bottom half 에서는 비교적 느리게 수행되어도 괜찮은 작업들이 지연되어 처리된다. 어떤 작업이 top half, bottom half 에서 처리되는지 감을 잡기 위해 NIC에 패킷이 수신된 상황을 예시로 들어보자. 먼저 NIC에 패킷이 수신되면 그에 따라 네트워크 디바이스 드라이버에 의하여 인터럽트가 생성될 것이다. 이와..
IPC는 프로세스 간의 통신을 의미하며, 관련하여 OS에서 제공하는 여러가지 기술과 메커니즘이 존재한다. 왜 필요한가? 우선 프로세스는 자신만의 가상 메모리를 가지며 자신만의 작업을 수행한다. 프로세스별 자원을 분리시키는 것에는 시스템을 보호하기 위해서, 여러가지 작업을 병렬적으로 수행하기 위해서, 효율성을 위해서와 같이 다양한 이유가 존재한다. 하지만, 분명히 프로세스간에도 통신이 필요한 상황이 존재한다. 아주 단순하게 생각하면 모든 프로세스끼리 자원을 공유하게 하는 방법으로도 프로세스간 통신이 가능하겠지만, 상당히 비효율적이고 시스템 또한 전혀 보호되지 않아 많은 문제가 발생할 것이다. 그렇기 때문에, OS는 다양한 IPC 메커니즘을 제공하여 프로세스간 통신을 원할하게 한다. 어떤 방법이 있는지 하나..