RAM의 특징과 종류
아래 두 내용을 기억하자.
- 주기억장치, 메인 메모리의 종류에는 크게 RAM과 ROM 두 가지가 있다.
- '메모리'라는 용어는 그중 RAM을 지칭하는 경우가 많다.
'메모리'라는 용어로 지칭했던 저장 장치인 RAM에 대해 알아보자.
RAM의 특징
RAM은 휘발성 저장 장치, 보조기억장치는 비휘발성 저장 장치이다.
- CPU는 RAM, 메모리로부터 명령어와 데이터들을 갖고 와 실행한다.
- RAM에는 실행할 프로그램의 명령어와 데이터가 저장된다.
- 전원을 끄면 RAM에 저장된 명령어와 데이터가 모두 날아간다.
- 휘발성 저장 장치는 전원을 끄면 내용이 사라지는 저장 장치이다. 예시) RAM
- 비휘발성 저장 장치는 전원이 꺼져도 내용이 유지되는 저장 장치이다. 예시) SSD, CD-ROM, USB 메모리 같은 보조기억장치
- CPU는 보조기억장치에 직접 접근하지 못한다.
- 따라서 비휘발성 저장 장치인 보조기억장치에는 '보관할 대상'을 저장하고, 휘발성 저장 장치인 RAM에는 '실행할 대상'을 저장한다.
- 만약 CPU가 실행하고 싶은 프로그램이 보조기억장치에 있다면 이를 RAM으로 복사 후 저장한 뒤 실행한다.
RAM의 용량과 성능
RAM이 크면 뭐가 좋을까? RAM의 용량은 컴퓨터 성능에 어떤 영향을 미칠까?
RAM 용량이 작을 경우를 생각해 보자.
CPU가 실행하고 싶은 프로그램이 보조기억장치에 있다면 이를 RAM으로 가져와야 한다.
근데 만약 RAM 용량이 작다면 보조기억장치에서 실행할 프로그램을 가져오는 일이 잦아 실행 기간이 길어진다.
다음 예시를 보자.
RAM 용량이 작은 경우
- RAM 용량이 프로그램 하나만 저장할 수 있을 만큼 작다고 가정해 보자.
- 만약 CPU가 프로그램 A를 실행하고 싶으면 보조기억장치에서 A를 가져오고, B를 실행하고 싶으면 다시 프로그램 B를 가져와야 한다.
- 즉, 새로운 프로그램을 실행할 때마다 보조기억장치에서 프로그램을 가져와야 하는 것이다.
RAM 용량이 충분히 큰 경우를 생각해 보자.
RAM 용량이 큰 경우
- RAM 용량이 보조기억장치에 있는 프로그램 전체를 저장할 수 있을 만큼 크다고 가정해 보자.
- 보조기억장치에서 많은 데이터를 가져와 미리 RAM에 저장할 수 있다.
- 즉, 많은 프로그램을 동시에 실행하는데 유리하다.
- 보조기억장치에서 여러 번 가져오는 수고를 덜 수 있다.
- CPU가 실행할 프로그램을 책에 빗대어보자.
- 보조기억장치는 책장, RAM은 책상과 같다.
- 책상이 크다면 많은 책을 미리 책상으로 가져와 여러 권을 동시에 읽을 수 있기 때문에 책을 가져오는 시간을 절약할 수 있다.
- 책상이 작으면 자주 책장에 왔다 갔다 해야 한다. 책을 가져오는 시간을 절약할 수 없다.
- 즉, 메모리 용량이 작다면 동시에 여러 개의 프로그램들을 실행하는 데에 불리하다.
RAM 용량이 엄청 크면 프로그램 실행 속도는 그에 비례하여 빨라질까? 그렇지는 않다.
RAM 용량이 커지면 프로그램 실행 속도가 어느 정도 증가하는 것은 맞지만, 용량이 필요 이상으로 커졌을 때는 속도가 그에 비례하여 증가하지는 않는다.
RAM의 종류
RAM의 종류에는 크게 4가지가 존재한다.
- DRAM
- SRAM
- SDRAM
- DDR SDRAM
DRAM(Dynamic RAM)
- Dynamic, 동적의
- DRAM은 저장된 데이터가 동적으로 사라지는 RAM을 의미한다.
- 즉, 시간이 지나면 저장된 데이터가 점차 사라지는 RAM이다.
- 데이터 소멸을 막기 위해 주기적으로 데이터를 재활성화, 다시 저장해야 한다.
- 이러한 단점에도 불구하고 일반적으로 메모리로써 사용되는 RAM이다.
- 왜 사용될까?
- 소비 전력이 비교적 낮고, 저렴하고, 집적도가 높아 대용량으로 설계하기 용이하기 때문이다.
참고: '집적도가 높다'는 '더 작고 빽빽하게 만들 수 있다'는 말과 같다.
SRAM(Static RAM)
- Static, 정적의
- SRAM은 저장된 데이터가 변하지 않는, 사라지지 않는 RAM을 의미한다.
- 즉, 시간이 지나도 저장된 데이터가 사라지지 않는다. 주기적으로 데이터를 재활성화할 필요도 없다.
- DRAM보다 일반적으로 속도가 더 빠르다.
- 일반적으로 캐시 메모리에서 사용되는 RAM이다.
- 소비 전력이 높고, 비싸고, 집적도가 낮아 메모리가 아닌 '대용량으로 설계할 필요는 없으나 빨라야 하는 장치'인 캐시 메모리에서 사용된다.
주의!: 시간이 지나도 저장된 데이터가 사라지지 않는다고 해서 SRAM이 비휘발성 메모리인 것은 아니다.
SRAM도 전원이 공급되지 않으면 저장된 내용이 날아간다.
DRAM과 SRAM 비교
SDRAM(Synchronous DRAM)
- SDRAM은 클럭 신호와 동기화된, 발전된 형태의 DRAM이다.
- '클럭 신호와 동기화되었다'는 말은 클럭 타이밍에 맞춰 CPU와 정보를 주고받을 수 있음을 의미한다.
- 즉, SDRAM은 클럭에 맞춰 동작하며 클럭마다 CPU와 정보를 주고받을 수 있는 DRAM이다. '똑-딱-똑-딱'
DDR SDRAM(Double Data Rate SDRAM)
- DDR SDRAM은 대역폭을 넓혀 속도를 빠르게 만든, 특별한 발전된 형태의 SDRAM이다.
- 최근에 가장 대중적으로 사용하는 RAM이다.
- 대역폭은 '데이터를 주고받는 길의 너비'를 의미한다.
대역폭을 자동차 도로에 비유해 보자.
SDR SDRAM vs DDR SDRAM
- 한 클럭에 한 번씩 CPU와 데이터를 주고받을 수 있는 SDRAM과 비교했을 때 DDR SDRAM은 너비가 두 배인 도로이다.
- 즉, DDR SDRAM은 두 배의 대역폭으로 한 클럭당 두 번씩 CPU와 데이터를 주고받을 수 있다. 전송 속도가 2배가량 빠르다.
- 한 클럭당 하나씩 데이터를 주고받을 수 있는 SDRAM을 SDR SDRAM(Single Data Rate SDRAM)이라 부른다.
SDR SDRAM vs DDR2 SDRAM
- DDR2 SDRAM은 DDR SDRAM보다 대역폭이 두 배 넓은 SDRAM이다.
- 즉, SDR SDRAM보다 너비가 네 배 넓은 도로와도 같다.
DDR3 SDRAM은 DDR2 SDRAM보다 대역폭이 두 배 넓다. 즉, SDR SDRAM보다 대역폭이 여덟 배 넓다.
최근에 가장 많이 사용하는 메모리는 DDR4 SDRAM으로, SDRAM보다 열여섯 배 넓은 대역폭을 가진다.
메모리의 주소 공간
'메모리에 저장된 정보의 위치는 주소로 나타낼 수 있다'라고 했다.
사실 주소에는 물리 주소, 논리 주소 두 가지 종류가 있다.
- 물리 주소는 메모리 하드웨어가 사용하는 주소이다.
- 논리 주소는 CPU와 실행 중인 프로그램이 사용하는 주소이다.
논리주소와 물리 주소 두 종류가 존재한다.
논리 주소와 물리 주소로 주소 공간을 나눈 이유는 뭘까? 논리 주소를 물리 주소로 변환하는 방법은 뭘까?
물리 주소와 논리 주소
CPU와 실행 중인 프로그램은 현재 메모리 몇 번지에 무엇이 저장되어 있는지 다 알고 있을까? 다 알지 못한다.
CPU와 실행 중인 프로그램은 메모리 몇 번지에 무엇이 저장되어 있는지 다 알지 못한다. 왜냐하면 메모리에 저장된 값들은 시시각각 변하기 때문이다.
- 새롭게 실행되는 프로그램은 새롭게 메모리에 적재된다.
- 실행이 끝난 프로그램은 메모리에서 삭제된다.
- 같은 프로그램을 실행하더라도 실행할 때마다 적재되는 주소는 달라진다.
- 예시) 1500번지에 적재되었던 프로그램을 다시 실행하면 3000번지, 또다시 실행하면 2500번지에 적재될 수 있다.
이러한 한계를 극복하기 위해 주소 체계를 물리 주소와 논리 주소로 나누었다.
그러면 CPU와 실행 중인 프로그램이 이해하는 주소는 무엇일까?
물리 주소
- 메모리 입장에서 바라본 주소이다.
- 정보가 실제로 저장된 하드웨어상의 주소를 의미한다.
논리 주소
- CPU와 실행 중인 프로그램 입장에서 바라본 주소이다.
- 실행 중인 프로그램 각각에게 부여된 0번지부터 시작하는 주소이다.
즉, 물리 주소는 메모리 하드웨어 상의 주소이고, 논리 주소는 CPU와 실행 중인 프로그램이 사용하는 주소이다.
다음 예시를 보자. 메모리에 인터넷 브라우저, 게임, 메모장 프로그램이 적재되어 있다고 가정해 보자.
이 세 프로그램은 현재 다른 프로그램들이 메모리 몇 번지에 저장되어 있는지, 즉 다른 프로그램들의 물리 주소가 무엇인지 알 필요가 없다.
논리 주소와 물리 주소
- 인터넷 브라우저, 게임, 메모장 모두 물리 주소가 아닌 0번지부터 시작하는 자신만을 위한 주소인 논리 주소를 가지고 있다.
- 예시) 100번지 주소는 인터넷 브라우저에도, 게임에도 메모장에도 논리 주소로써 존재할 수 있다. 즉 프로그램마다 같은 논리 주소가 여러 개 있을 수 있다.
- 물리 주소는 실제 하드웨어상의 주소이기 때문에 0번지가 하나밖에 없다. 즉, 물리 주소는 겹치는 주소 번지가 없다.
CPU가 메모리와 상호작용하려면 논리 주소와 물리 주소 간의 변환이 이루어져야 한다.
그렇다면 논리 주소는 어떻게 물리 주소로 변환될까?
논리 주소와 물리 주소간의 변환이 이루어져야 한다.
논리 주소와 물리 주소 간의 변환은 CPU와 주소 버스 사이에 위치한 메모리 관리 장치, MMU라는 하드웨어에 의해 변환된다.
논리 주소를 주소 버스를 통해 메모리에 전달하거나, 메모리로부터 주소 버스를 통해 주소를 받아올 경우에는 항상 MMU를 거치게 된다.
MMU(Memory Management Unit)
MMU는 논리 주소와 베이스 레지스터(프로그램의 기준 주소) 값을 더하여 논리 주소를 물리 주소로 변환한다.
- 논리 주소는 실제로 저장되어 있는 프로그램으로부터 얼마나 떨어져 있는지에 대한 정보라고 생각하면 된다.
- 베이스 레지스터에는 물리 주소 상의 프로그램의 시작 주소가 담긴다고 생각하면 된다.
다음 예시를 보자.
- 프로그램 A는 15000번지부터 30000번지까지 실제 물리 주소 상에 저장되어 있다고 가정해 보자.
- 그러므로 베이스 레지스터, 프로그램의 기준 주소에는 15000이 저장되어 있다.
- CPU가 발생시킨 논리 주소가 100번지라는 말은 기준 주소로부터 100만큼 떨어진 곳이라고도 표현가능하다.
- 기준 주소로부터 얼마만큼 떨어져 있느냐
- 논리주소 100번지는 물리 주소 15100번지(15000+100)로 변환된다. 실제로 삭제되는 물리 주소는 15100번지
정리하자면 베이스 레지스터는 프로그램의 가장 작은 물리 주소, 즉 프로그램의 첫 물리 주소를 저장한다.
논리 주소는 프로그램의 시작점, 즉 베이스 레지스터에 담긴 값으로부터 떨어진 거리인 셈이다.
메모리 보호 기법
다른 프로그램의 영역을 침범하는 명령어를 실행하면 안 된다.
아래 예시를 보자.
- 인터넷 브라우저 프로그램은 논리 주소상 0번지부터 999번지까지 있다고 가정하자.
- 인터넷 브라우저의 실제 주소, 즉 물리 주소는 2000번지부터 2999번지까지 라고 가정하자.
- 만약 인터넷 브라우저 명령어 중 '(논리 주소) 1100번지에 데이터를 삭제해라'와 같은 명령어를 실행했다.
- 이 명령어는 실행돼도 안전할까?
- 그렇지 않다. 왜냐하면 프로그램, 즉 인터넷 브라우저의 논리 주소 영역을 벗어났기 때문이다.
- 인터넷 브라우저 프로그램 명령어는 자신과는 전혀 관련 없는 게임 프로그램 정보를 삭제한다.
- (2000 + 1100) 3100번지는 게임 프로그램에 적재되어 있기 때문이다.
전혀 관련 없는 게임 프로그램 정보를 삭제한다.
이러한 문제점 때문에 논리 주소 범위를 벗어나는 명령어 실행을 방지하고, 실행 중인 프로그램이 다른 프로그램에 영향을 받지 않도록 메모리를 보호하는 방법이 필요하게 되었다. 이를 한계 레지스터라는 레지스터가 담당한다.
한계 레지스터
- 프로그램의 영역을 침범할 수 있는 명령어의 실행을 막는다.
- 베이스 레지스터가 실행 중인 프로그램의 가장 작은 물리 주소를 저장한다면, 한계 레지스터는 논리 주소의 최대 크기를 저장한다.
- 베이스 레지스터 값 <= 프로그램의 물리 주소 범위 < 베이스 레지스터 + 한계 레지스터 값
- 즉, CPU가 접근하려는 논리 주소는 한계 레지스터가 저장한 값보다는 커서는 안 된다.
- 한계 레지스터가 저장한 값보다 높은 주소 값에 접근하는 것은 프로그램의 범위에 벗어난 메모리 공간에 접근하는 것이다.
프로그램의 물리 주소 범위
다음 예시를 보자.
- 베이스 레지스터에 100, 한계 레지스터에 150이 저장되어 있다고 가정하자.
- 즉, 물리 주소 시작점이 100번지, 프로그램의 크기, 논리 주소의 최대 크기는 150이라는 뜻이다.
- 한계 레지스터(150) 보다 큰 논리 주소(200)에 접근하려고 한다. 실행하면 안된다.
- CPU는 메모리에 접근하기 전에, 접근하고자 하는 논리 주소가 한계 레지스터보다 작은 지를 항상 검사한다.
- 한계 레지스터보다 작으면 물리 주소로 변환하여 실제 메모리에 접근한다.
- 한계 레지스터보다 크면 인터럽트를 발생시켜 명령어를 실행하지 않는다. 다른 프로그램의 주소 공간을 침범했기 때문이다.
- 이를 통해 실행 중인 프로그램의 독립적인 실행 공간을 확보하고, 하나의 프로그램이 다른 프로그램을 침범하지 못하게 보호한다.
캐시 메모리
CPU가 메모리에 접근하는 시간은 CPU 연산 속도보다 압도적으로 느리다.
메모리에 접근하는 시간이 느리면 연산 속도가 아무리 빠르다고 해도 의미가 없다.
이를 극복하기 위한 저장 장치가 캐시 메모리이다.
연산 속도에 비해 너무 느리다.
저장 장치 계층 구조
저장 장치는 일반적으로 아래와 같은 명제를 따른다.
- 일반적으로 CPU와 가까운 저장 장치는 빠르고, 멀리 있는 저장 장치는 느리다.
- 일반적으로 속도가 빠른 저장 장치는 저장 용량이 작고, 가격이 비싸다.
CPU 내의 레지스터, 메모리(RAM), USB 메모리를 비교해 보자.
- 레지스터는 일반적으로 RAM보다 용량은 작지만, 접근 시간이 압도적으로 빠르고 가격이 비싸다.
- USB 메모리보다 CPU에 가까운 RAM은 접근 시간이 훨씬 더 빠르지만, 같은 용량이어도 가격이 더 비싸다.
정리하자면 다음과 같다.
- 낮은 가격대의 대용량 저장 장치를 원한다면 느린 속도는 감수해야 한다.
- 빠른 속도의 저장 장치를 원한다면 작은 용량과 비싼 가격은 감수해야 한다.
그림으로 보면 다음과 같다.
저장 장치 계층 구조
- 저장 장치들은 'CPU에 얼마나 가까운가'를 기준으로 계층적으로 나타낼 수 있다.
- 저장 장치 계층 구조는 각기 다른 용량과 성능의 저장 장치들을 계층화하여 표현한 구조이다.
참고: 저장 장치 계층 구조를 영문으로 나타내면 memory hierarchy, 메모리 계층 구조를 의미한다.
여기서 '메모리'는 RAM이 아닌 일반적인 저장 장치를 의미한다.
캐시 메모리
- 캐시 메모리는 CPU와 메모리 사이에 위치하고, 레지스터보다 용량이 크고 메모리보다 빠른 SRAM 기반의 저장 장치이다.
- 즉, CPU의 연산 속도와 메모리 접근 속도의 차이를 조금이나마 줄이기 위해 탄생했다.
- CPU가 매번 메모리에 왔다 갔다 하는 건 시간이 오래 걸리니, 메모리에서 CPU가 사용할 일부 데이터를 미리 캐시 메모리로 가져와 쓰자는 것이다.
CPU, 캐시 메모리, 메모리
다음과 같이 비유를 할 수 있다.
- 메모리에 접근하는 것을 물건을 사러 가는 것으로 비유하자.
- 메모리는 '물건은 많지만 집과는 멀리 떨어져 있어 오래 걸리는 대형 마트'
- 캐시 메모리는 '물건이 많지는 않아도 집과 가까이 있는 편의점'
이러한 성능 향상 때문에 현대 대부분의 CPU는 캐시 메모리를 사용한다.
캐시 메모리는 CPU가 자주 사용할 법한, 메모리에 저장되어 있는 값의 일부를 갖고 와 저장하고 있다.
캐시 메모리까지 반영한 저장 장치 계층 구조
캐시 메모리는 한 개가 아니다. 다음 그림을 보자.
계층적 캐시 메모리(L1-L2-L3 캐시)
- 컴퓨터 내부에는 여러 개의 캐시 메모리가 있다.
- 캐시 메모리들은 CPU(코어)와 가까운 순서대로 계층을 구성한다.
- 계층적 캐시 메모리라고 하며, L1-L2-L3 캐시라고 부른다. Level1, Level2, Level3
- 코어와 가장 가까운 순서대로 L1 캐시, L2 캐시, L3 캐시이다.
- 일반적으로 L1 캐시와 L2 캐시는 코어 내부에, L3 캐시는 코어 외부에 위치해 있다.
- 캐시 메모리의 용량은 L1, L2, L3 순으로 커지고, 속도는 L3, L2, L1 순으로 빨라진다. 가격은 L3, L2, L1 순으로 비싸진다.
- CPU가 메모리 내에 데이터가 필요하다고 판단하면 우선 L1 캐시를 확인하고, L2 L3 캐시 순으로 데이터를 검색한다.
멀티 코어 프로세서의 캐시 메모리
- 멀티 코어 프로세서에서는 L1 캐시와 L2 캐시는 코어마다 고유한 캐시 메모리로 할당되고, L3 캐시는 여러 코어가 공유하는 형태로 사용된다.
분리형 캐시 메모리
- L1 캐시는 가장 빠른 캐시 메모리이다.
- L1 캐시를 조금이라도 빠르게 만들기 위해 다음과 같이 분리하는 경우도 있다. 이를 분리형 캐시라고 한다.
- 명령어만을 저장하는 L1 캐시인 L1I 캐시 (Instruction)
- 데이터만을 저장하는 L1 캐시인 L1D 캐시 (Data)
상위 계층과 하위 계층을 이루고 있는 저장 장치의 특징과 차이를 잘 이해하자.
계층적 캐시 메모리까지 반영한 저장 장치 계층 구조
참조 지역성 원리
캐시 메모리는 메모리보다 용량이 작다. 따라서 당연히 메모리의 모든 내용을 저장할 수는 없다.
메모리는 보조기억장치의 일부를 저장하고, 캐시 메모리는 메모리의 일부를 복사하여 저장한다.
그러면 캐시 메모리는 무엇을 저장해야 할까?
캐시 히트
- 캐시 메모리는 CPU가 자주 사용할 법한 내용을 예측하여 저장한다.
- 자주 사용될 것으로 예측한 데이터가 실제로 들어맞아 캐시 메모리 내 데이터가 CPU에서 활용된 경우를 캐시 히트라 한다.
캐시 미스, 성능이 떨어진다.
- 예측이 틀려 CPU가 메모리에 접근해 메모리에서 필요한 데이터를 직접 가져와야 하는 경우를 캐시 미스라 한다.
- 캐시 미스가 발생하면 캐시 메모리의 이점을 활용할 수가 없다. 즉 캐시 미스가 자주 발생하면 성능이 떨어진다.
- 캐시가 히트되는 비율을 캐시 적중률이라 한다.
- 캐시 적중률 = 캐시 히트 횟수 / (캐시 히트 횟수 + 캐시 미스 횟수)
- 캐시 적중률이 높으면 CPU의 메모리 접근 횟수를 줄일 수 있다.
- 요즘 컴퓨터의 캐시 적중률은 대략 85~95%이다.
즉, 우리는 캐시 적중률을 높여야 한다. 이를 위해 CPU가 사용할 법한 데이터를 잘 예측해야 한다.
캐시 메모리는 참조 지역성의 원리에 따라 메모리로부터 가져올 데이터를 결정한다.
- 참조 지역성의 원리란 CPU가 메모리에 접근할 때의 주된 경향을 바탕으로 만들어진 원리이다.
- 두 가지 경향을 바탕으로 만들어진 원리이다.
- CPU는 최근에 접근했던 메모리 공간에 다시 접근하려는 경향이 있다.
- CPU는 접근한 메모리 공간 근처를 접근하려는 경향이 있다.
CPU는 최근에 접근했던 메모리 공간에 다시 접근하려는 경향
변수 num에 다시 접근하는 경향을 확인할 수 있다.
- 변수에 값을 저장하면, 언제든 다시 변수에 접근하여 변수에 저장된 값을 사용할 수 있다.
- 즉, 'CPU는 변수가 저장된 메모리 공간을 언제든 다시 참조할 수 있다'를 의미한다.
- 변수에 저장된 값은 프로그램이 실행되는 동안 여러 번 사용된다.
- 즉, CPU는 최근에 접근했던 변수가 저장된 메모리 공간을 여러 번 다시 접근할 수 있다.
- '최근에 접근했던 메모리 공간에 다시 접근하려는 경향'을 시간 지역성이라 한다.
CPU는 접근한 메모리 공간 근처를 접근하려는 경향
관련 데이터들끼리 한데 모여 있다.
- '접근한 메모리 공간 근처를 접근하려는 경향'을 공간 지역성이라 한다.
- CPU가 실행하려는 프로그램은 보통 관련 데이터들끼리 한데 모여 있다.
- 워드 프로세서 프로그램은 워드 프로세서 관련 데이터들이 모여 저장된다.
- 하나의 프로그램 내에서도 관련 있는 데이터들은 모여서 저장된다.
- 워드 프로세서 프로그램에 자동 저장, 입력, 출력 기능 등 각각의 기능과 관련한 데이터는 모여 저장된다.
- 즉, 워드 프로세서 프로그램을 실행할 때는 워드 프로세서 프로그램이 모여 있는 공간 근처를 집중적으로 접근하고, 사용자가 입력을 할 때에는 입력 기능이 모여 있는 공간 근처를 집중적으로 접근한다는 뜻이다.
출처:
'Hardware > etc' 카테고리의 다른 글
메인보드 제조사별 USB 부팅 메뉴 진입 키 방법 (0) | 2025.04.18 |
---|---|
CPU GPU 서멀 그리스를 도포 방법 및 서멀구리스 원리 (0) | 2025.04.17 |
컴퓨터 구조 - 보조기억장치 (0) | 2025.03.15 |
컴퓨터 구조 - 컴퓨터 입출력 장치 (0) | 2025.03.15 |
컴퓨터 구조 - CPU 작동 원리 (하드웨어) (0) | 2025.03.15 |