2022-10-31-TIL
2022-10-31-TIL
Today I Learned
JVM
JVM 명세(JVMS)의 첫 장을 읽었다. 명세는 JVM을 실제 컴퓨터처럼 명령어 집합을 갖고 실행 중에 여러 메모리 영역을 다루는 추상 기계라고 정의한다. 그리고 JVM은 자바 언어를 전혀 모르고 class 파일이라는 바이너리 형식만 안다고 강조한다.
“The Java Virtual Machine knows nothing of the Java programming language, only of a particular binary format, the class file format.”
그래서 Kotlin이나 Scala처럼 자바가 아닌 언어도 class 파일만 만들어 내면 JVM 위에서 돌아간다(JVMS 8, Chapter 1).
2장의 런타임 데이터 영역은 스레드마다 따로 생기는 영역과 모든 스레드가 공유하는 영역으로 나뉜다(JVMS 8, 2.5).
| 영역 | 범위 | 내용 |
|---|---|---|
| pc 레지스터 | 스레드별 | 현재 실행 중인 명령의 주소 |
| JVM 스택 | 스레드별 | 메서드 호출마다 쌓이는 프레임(지역 변수, 피연산자 스택) |
| 네이티브 메서드 스택 | 스레드별 | 네이티브 메서드 실행용 |
| 힙 | 공유 | 모든 클래스 인스턴스와 배열이 할당되는 곳 |
| 메서드 영역 | 공유 | 클래스별 구조(런타임 상수 풀, 필드, 메서드 코드) |
이 구분을 알면 에러 메시지를 읽기 쉬워진다. 명세에 따르면 스레드의 계산이 허용된 것보다 큰 스택을 요구하면 StackOverflowError가 나고(깊은 재귀가 대표적이다), 자동 메모리 관리가 확보할 수 있는 것보다 많은 힙을 요구하면 OutOfMemoryError가 난다. 멀티스레드에서 동기화가 필요한 대상이 힙의 객체라는 점도 같은 표에서 나온다.
- https://docs.oracle.com/javase/specs/jvms/se8/html/index.html
- https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-1.html
- https://medium.com/@ervinitraj/all-about-jvm-java-virtual-machine-bdeecd6eaa1d
MongoDB Schema Design Best Practices
MongoDB 스키마 설계의 기본 원칙은 함께 조회되는 데이터는 함께 저장하라는 것이다. 테이블을 먼저 정규화하는 RDB와 달리, 애플리케이션이 데이터를 어떻게 읽고 쓰는지를 기준으로 문서 구조를 정한다(MongoDB: Data Modeling).
가장 먼저 고민하는 것은 임베딩(문서 안에 하위 문서로 넣기)과 참조(다른 컬렉션의 _id를 저장하기) 중 무엇을 고를지다(Embedded Data Versus References).
- 임베딩이 맞는 경우: 부모에 속한 데이터(has-a 관계)이고, 늘 함께 조회되고 함께 수정되며, 한 번의 원자적 쓰기로 다뤄야 할 때
- 참조가 맞는 경우: 자식 수가 많거나 끝없이 늘어날 때, 자식이 독립적으로 존재할 때, 서로 다른 시점에 따로 쓰이는 일이 잦을 때
임베딩이 끝없이 늘어나면 안 되는 이유는 문서 크기에 상한이 있기 때문이다. BSON 문서 하나의 최대 크기는 16MiB다(MongoDB Limits and Thresholds). 링크한 글이 관계를 one-to-few, one-to-many, one-to-squillions처럼 자식의 수로 나눠 설명하는 것도 같은 이유다. 자식이 적으면 임베딩하고, 많아질수록 참조로 옮겨 가며, 아주 많으면 부모가 자식 목록을 들고 있지 않고 자식 쪽에 부모 참조를 둔다.
- https://www.mongodb.com/developer/products/mongodb/mongodb-schema-design-best-practices/
댓글
아직 댓글이 없습니다