Skip to content

Feat: 예열한 캐시를 디스크 읽기 없이 유지하고 중요한 데이터가 마지막에 밀려나게 함 - #181

Merged
DO0OG merged 1 commit into
mainfrom
176-feat-standby-ladder-refresh
Nov 13, 2026
Merged

DO0OG merged 1 commit into
mainfrom
176-feat-standby-ladder-refresh

Conversation

@DO0OG

@DO0OG DO0OG commented Nov 13, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • 예열한 캐시를 디스크 읽기 없이 유지하고, 메모리가 모자라 밀려날 때는 덜 중요한 데이터부터 밀려나게 하는 제어 고리(SOLAR)를 넣었습니다.
  • csharp/src/AsterCache.Windows/StandbyTouch.cs(새 파일): 캐시에 있는 범위를 주어진 순서대로 다시 읽어 대기 목록의 맨 뒤로 보냅니다. 범위마다 뷰를 따로 매핑해 ReadProcessMemory 로 읽고 바로 풉니다(고정 없음, 뷰는 64 MiB 이하). 읽기 실패는 예외가 아니라 반환값으로 옵니다.
  • csharp/src/AsterCache.Windows/SystemPageReads.cs(새 파일): 시스템 전체의 "디스크에서 읽어 들인 쪽 수" 누계를 읽습니다. 만지는 동안 이 누계가 잡음 허용치보다 늘어난 만큼을 디스크 읽기로 누적하고, 32 MiB 를 넘으면 멈춥니다. 누계를 읽을 수 없을 때만 시간 기준을 씁니다.
  • csharp/src/AsterCache.Core/Prefetch/LadderOrder.cs(새 파일): 만질 순서(읽은 순서의 역순)를 만드는 순수 함수입니다.
  • csharp/src/AsterCache.Service/Solar.cs, SolarPolicy.cs, Prewarm.Solar.cs, Rewarm.Ladder.cs(새 파일): 본체, 판정, 예열기 연결, 유지 틱입니다. 예열이 끝나면 그 게임이 캐시에 올린 전체(공통 블록 + 읽은 범위)를 역순으로 만져 공통 블록과 앞부분이 가장 나중에 밀려나게 하고, 그 뒤 캐시 재사용 누계가 "만질 때 앞에 있던 양"의 0.4 배(하한 512 MiB)에 이르면 메모리 안에서 다시 만집니다.
  • csharp/src/AsterCache.Windows/MemoryListInfo.cs: 대기 목록 조회에 캐시 대기 바이트를 더했습니다.
  • 설정 memory.standby_ladder(기본 true)로 끌 수 있습니다.

알아 둘 점

  • 같은 PC 에서 시험 파일로 잰 근거: 5분마다 다시 만진 파일은 끝까지 캐시에 남았고 한 번만 읽은 파일은 캐시 재사용 7.09.2 GiB 사이에 밀려났습니다. 캐시에 넣은 순서대로 밀려났고, 파일 하나 안에서도 범위마다 따로 매핑해 만진 순서 그대로 밀려났습니다. 페이지 읽기 누계는 캐시에 없는 256 MiB 를 만질 때 258 MiB 만큼, 캐시에 있을 때는 65128쪽만 늘었습니다.
  • 디스크에서 다시 읽을지는 지금처럼 재예열 점검만 정합니다. SOLAR 는 디스크 읽기가 필요하면 멈추고 표식을 지울 뿐 재예열을 직접 부르지 않으므로, HDD 재읽기 빈도가 늘지 않습니다.
  • 게임이 실행 중인 디스크에서는 돌지 않고, 런처 트리거가 기다리거나 읽는 동안에도 돌지 않습니다. 메모리 예비량과 캐시 예산 판정은 바뀌지 않았고, 읽는 양도 늘지 않습니다.
  • 캐시가 밀려나지 않게 보장하는 기능은 아닙니다. 메모리 압력이 크면 결국 밀려나며, 이때 밀려나는 순서를 정하는 것입니다.
  • 재사용 통계를 읽을 수 없으면 새로 고침 시점은 10분 주기로 대신합니다.
  • 설치본에서 식음 판정 비율이 실제로 줄어드는지는 아직 확인하지 않았습니다.

Test plan

  • dotnet build csharp -c Release -m:1 경고 0, 오류 0
  • dotnet test csharp/tests/AsterCache.Tests -c Release --no-build --filter "Category!=Live" 4,391건 통과
  • Live 시험 통과 (StandbyTouchLiveTests: 실제 파일 만지기, 페이지 읽기 누계 조회)
  • dotnet format csharp --verify-no-changes 통과
  • git diff --check 이상 없음
  • CI build-test 통과: https://github.com/DO0OG/AsterCache/actions/runs/43480777026/job/132076373320

Closes #176

예열한 게임 데이터는 게임을 켜기 전에 자주 식었고(재예열 점검의 47~71% 가 식음 판정),
식으면 HDD 에서 다시 읽었습니다. 또 Windows 는 캐시에 먼저 들어간 페이지부터 내보내는데
예열은 중요한 앞부분을 먼저 읽으므로, 가장 중요한 데이터가 가장 먼저 밀려났습니다.

대기 목록 통계를 신호로 삼는 제어 고리(SOLAR)를 넣었습니다.

- 예열이 끝나면 그 게임이 캐시에 올린 전체를 읽은 순서의 역순으로 다시 만져, 공통 블록과 앞부분이 가장 나중에 밀려나게 함
- 만질 때 우리보다 앞에 있던 캐시 양의 0.4 배가 재사용되면 메모리 안에서 다시 만져 유지함 (재사용이 없으면 아무 일도 하지 않음)
- 범위마다 뷰를 따로 매핑해 만지고 바로 풀며, 고정은 하지 않음
- 디스크 읽기는 시스템의 페이지 읽기 누계로 감지하고, 32 MiB 를 넘으면 멈춰 기존 재예열 점검에 맡김
- 게임이 실행 중인 디스크와 런처 트리거가 기다리는 동안에는 돌지 않음
- 설정 memory.standby_ladder (기본 켜짐) 로 끔

Issues #176
@DO0OG
DO0OG merged commit 01dc8c3 into main Nov 13, 2026
1 check passed
@DO0OG
DO0OG deleted the 176-feat-standby-ladder-refresh branch November 13, 2026 18:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feat: 예열한 캐시를 디스크 읽기 없이 유지하고 중요한 데이터가 마지막에 밀려나게 함

1 participant