개발을 하면서 내가 짠 코드들을 머릿속으로 온전히 이해하기가 쉽지 않다.
그리고 개발이 시작하기 전, 끝난 이후에 구현한 것에 대한 클래스 다이어그램을 직접 그리는 시간이 오래 걸리는 경우가 있다.
이런 경우 ‘IntelliJ에서 제공하는 다이어그램 기능을 쓰면 시각적인 이해 + 시간 절약
이 되지 않을까?’ 하는 마음으로 해당 포스팅을 작성하게 되었다.
다리 건너기
를 예시로 가져왔다.이 글의 사진과 내용은 공룡책 과 컴퓨터학부 수업인 운영체제 강의자료를 기반으로 작성했습니다.
멀티-레벨 큐(MLQ)
MLQ
란 준비 큐를 여러 개로 분할해 관리하는 스케줄링 기법을 말한다.
즉 프로세스들이 CPU를 기다리기 위해 한 줄로 서는 것이 아니라 여러 줄로 서는 것이다.
MLQ는 일반적으로 성격이 다른 프로세스들을 별도로 관리하고, 프로세스의 성격에 맞는 스케줄링을 적용하기 위해 ready queue를 별도로 두게 된다.
미래를 예측하기 위해 과거를 배우는 스케줄러이다.
ML(F)Q는 다수의 개별 queue를 유지한다.
Rule 1
: Run-time이 짧은 job에게 우선순위(priority)를 부여한다.
Rule 2
: 만약 우선순위가 같으면, 라운드 로빈 스케줄링(RR)을 사용한다.
MLQ는 관찰된 동작에 따라 작업의 우선순위를 변경한다.
Example 동작 :
job은 I/O를 기다리는 동안 CPU를 반복적으로 양도한다.
대화형(interative) 프로세스의 동작은 다음과 같습니다.
우선순위를 높게 유지(단시간 슬라이스 포함) -> 응답 시간 향상
job이 장시간 동안 CPU를 집중적으로 사용한다.
일괄(batch) 작업의 동작은 다음과 같습니다.
우선순위 감소(긴 시간 슬라이스 포함) -> 소요 시간 단축
이러한 방식으로 MLQ는 프로세스가 실행될 때 프로세스에 대해 학습하고, 따라서 job의 기록을 사용하여 미래의 동작을 예측합니다.
멀티레벨 피드백 큐(MLFQ)
MLFQ
는 CPU를 기다리는 프로세스를 여러 queue에 줄 세운다는 측면에서 MLQ와 동일하나, 프로세스가 하나의 queue에서 다른 queue로 이동 가능하다는 점이 다르다.이 글의 사진과 내용은 공룡책 과 컴퓨터학부 수업인 운영체제 강의자료를 기반으로 작성했습니다.
32bit CPU의 메모리 주소 레지스터의 크기는 32bit
CPU가 만들어내는(표현할 수 있는) 주소 개수 : 2^32
Stack : 지역 변수
Heap : 할당된 변수 or malloc(), calloc()
OS가 많은 가상의(논리적인) CPU가 존재하는 것처럼 환상을 조장한다.
(single-core system으로 가장한다면) 물리적인 CPU 개수는 1개이다.
Time-sharing
-> 핵심: 시간을 나눠서 사용한다
User가 원하는 만큼 동시에 프로세스를 실행할 수 있다.
Round robin 방식에 의해서 하나의 프로세스를 실행하고, 멈춘 다음에 다른 프로세스를 실행한다.
CPU Virtualization을 구현하기 위해서 필요한 2가지
OS’s low-level mechanism (How) (e.g. Context switch)
OS’s policy (Which) (e.g. Scheduling policies)
Direct execution
: CPU가 프로세스를 수행하는 동안에는 OS가 간섭하지 않는다.위의 표와 같이 한 번 실행하면 종료될 때까지 프로세스는 멈추지 않는다.
하지만 이 방법으로는 지금 구현하려고 하는 CPU 가상화를 구현할 수 없다.
한 번 실행된 프로세스에 대해 제어를 할 수 없으며 Time Sharing을 할 수 없다.
Time Sharing을 하려면 어떠한 Limit를 해줘야 CPU 가상화를 구현할 수 있다.
Direct Execution는 프로그램을 빠르게 실행하는 장점이 있다.
하지만 실행 도중에 (1)디스크에 대한 I/O 요청이 발생하거나 (2)CPU 혹은 Memory에서 더 많은 시스템 리소스에 대한 엑세스 권한을 획득하는 경우를 해결할 수 없기 때문에 사용할 수 없다.
이를 해결하기 위한 방법으로 Limited Direct Execution
을 사용한다.
What to limit?
General memory access
Disk I/O
Certain instructions
이러한 문제를 해결하기 위해 User mode와 Kernel 모드로 상태를 구분한다.
User mode
에서는 수행할 수 있는 작업에 제한을 둬서 Application이 HW 리소스에 대한 완전한 접근을 가질 수 없다.
이를 보완하기 위해Kernel mode
에서는 OS가 CPU 권한을 가지고 I/O요청과 같은 권한이 필요한 모든 작업을 수행할 수 있다.
[System call 이란]
System call은 일종의 SW적인 인터럽트로서 사용자 프로그램이 system call을 할 경우 trap이 발생해 CPU의 제어권이 OS로 넘아가게 된다.
그러면 OS는 해당 system call을 처리하기 위한 루틴으로 가서 정의된 명령을 수행한다.
테스트코드를 작성하면서 JUnit과 AssertJ 사용법을 익혀야 한다는 사실을 알게 되고 난 이후에 따로 공부를 하게 되었다.
그 중 AssertJ 개념을 정리하자.
AssertJ
: Java 테스트에서 유창하고 풍부한 어설션을 작성하는 데 사용되는 오픈 소스 커뮤니티 기반 라이브러리이다.<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.4.1</version>
<scope>test</scope>
</dependency>
이 종속성은 기본 Java 어설션에만 적용된다.
Java 7 및 이전 버전의 경우 AssertJ 코어 버전 2.xx를 사용해야 한다.
최신 버전은 AssertJ 코어 버전 3.23를 제공해주고 있다.
AssertJ는 다음을 위해 유창하고 아름다운 어설션을 쉽게 작성할 수 있도록 하는 일련의 클래스 및 유틸리티 메서드를 제공한다.
Standard Java
Java 8
Guava
Joda Time
Neo4J and
Swing components
import org.assertj.core.api.Assertions;
Assertions.assertThat()
메서드에 전달한 다음 실제 어설션을 따라야 한다.public class Dog {
private String name;
private Float weight;
// standard getters and setters
}
Dog fido = new Dog("Fido", 5.25);
Dog fidosClone = new Dog("Fido", 5.25);
복사
다음과 같이 두 object의 동등성을 비교할 수 있는 방법이 있다.
내용을 비교하려면,
isEqualToComparingFieldByFieldRecursively()
을 사용한다.
assertThat(fido).isEqualToComparingFieldByFieldRecursively(fidosClone);
진실 테스트를 위한 간단한 방법이 있다.
isTrue()
isFalse()
assertThat("".isEmpty()).isTrue();