확장팩 FFF 모음 정리 링크



오늘은 최적화 관련된 기술적인 이야기

= 내가 기반지식이 좆도 없어서 번역이 부정확할 수 있음



https://www.factorio.com/blog/post/fff-415



FFF #415 - 수정, 개선, 최적화

게시자 Rseding

2024-06-14



안녕하세요,

2.0 개발 기간 동안 새로운 기능과 삶의 질 향상에 많은 시간을 할애했지만, 여전히 작은 세부 사항과 기술적인 개선에도 신경을 쓰고 있습니다.




결정론적인(deterministic) 멀티스레딩은 어렵습니다


최근 모딩 API와 여러 대의 Windows 및 Linux 컴퓨터를 사용중인 플레이어와 관련된 비동기화 버그가 신고되었습니다. 처음에는 모드 개발자가 뭔가 실수했다고 생각하고 무시하고 싶었지만, 수년 동안 버그 신고를 충분히 봐왔기 때문에 조사도 하지 않고 무시하는 것은 나쁜 생각이며 명백한 잘못이라는 것을 알고 있습니다.


저는 비동기화를 재현할 수 없었지만 해당 플레이어는 쉽게 재현할 수 있었습니다. 처음에는 Windows와 Linux 간의 문제라고 생각했지만(이런 문제가 많이 발생했거든요), 플레이어는 두 컴퓨터 모두에서 Linux를 세팅하고도 버그를 재현할 수 있었습니다. 그 다음에는 하드웨어 문제라고 생각했습니다. 제대로 작동하지 않는 문제가 있는 컴퓨터를 많이 보았기 때문입니다. 하드웨어가 고장났다고 설득하는 것은 최상의 시나리오에서도 어렵고 시간이 많이 걸리는 일입니다.


제 컴퓨터 한 대에서 문제를 재현하려고 여러 번 시도했지만 실패한 후, Boskid는 여러 대의 컴퓨터를 사용하여 문제를 재현하는 데 성공했습니다. 로컬에서 버그를 재현할 수 있다는 것은 보고된 버그를 수정하는 데 소요되는 시간의 약 90~95%를 차지한다고 생각합니다. Boskid는 필요에 따라 문제를 재현하면서 컴퓨터의 CPU 코어 수가 다르다는 사실로 문제를 좁힐 수 있었습니다. 새로 알게 된 지식을 바탕으로 그는 제 컴퓨터 한 대에서 실행할 수 있는 테스트를 만들어 인위적으로 CPU 코어 수가 적은 것처럼 꾸며서 비동기화 버그를 재현할 수 있었습니다.


결국 이 문제는 2017년 7월 22일에 추가한 이래로 게임에 존재해 온 결정론적 멀티스레딩 문제를 드러내기 위해 4개의 서로 다른 단서가 모두 합쳐져야 했습니다.


- 모드는 청크 생성 이벤트를 수신하고 청크가 생성되면 청크의 타일을 변경해야 합니다.

- 여러 개의 청크 생성을 요청하려면 모드가 필요합니다.

- 요청된 모든 청크가 지금 바로 생성되도록 강제하는 모드가 필요합니다.

- 이 게임은 CPU 코어 수가 다른 두 대의 컴퓨터에서 실행해야 했습니다.

- 청크를 '지금 바로' 생성하는 로직은 사용 가능한 모든 CPU 코어를 사용하려고 시도하지만, 코어 수가 다른 조각과 결합되면 청크 생성 결과가 약간 달라지는 방식으로 수행되었습니다.


이 수정 사항은 구현하기가 그리 복잡하지 않았고 2.0에 포함될 예정이지만, 멀티스레딩이 어렵고 결정론적 멀티스레딩은 더욱 어렵다는 것을 잘 보여줍니다.







멀티플레이어 게임 자동 일시정지


데디케이티드 서버에는 마지막 플레이어가 연결을 끊으면 서버가 자동으로 일시정지되는 기능이 있습니다. 이 기능은 훌륭하게 작동하며, 플레이어가 자리를 비웠을 때 바이터들이 기지를 먹어버릴 걱정 없이 데디케이티드 서버를 켜둘 수 있습니다. 단, 지금까지 처리하지 못한 몇 가지 특이한 경우가 있습니다.


사례 1: 자동 일시 중지된 서버에 접속하면 게임이 완전히 로딩되지 않았더라도 즉시 플레이가 재개됩니다. 이 문제는 수년 동안 어떤 이유에서인지 방치되었지만, 해결은 매우 간단했습니다. 2.0에서는 자동으로 일시중지된 서버는 최소 1명의 플레이어가 게임에 완전히 로딩될 때까지 일시중지된 상태로 유지됩니다.


사례 2: 참가하는 플레이어가 진행 중인 게임을 따라잡아야 하는 경우. 이 방법은 "일반적인" 게임에서는 잘 작동하며 기존 플레이어가 참가하는 플레이어를 기다릴 필요 없이 게임을 계속할 수 있습니다. 하지만 맵이 너무 크거나 인터넷 연결이 느린 경우에는 플레이어가 문제를 겪을 수 있습니다. 참여하는 플레이어 없이 게임을 계속 진행하면 서버를 완전히 다운로드하고 로드하고 따라잡는 데 1분, 2분 또는 몇 분이 걸릴 수 있습니다. 2.0에서는 '플레이어가 참여할 때 자동 일시 중지' 옵션을 추가했으며, 이 옵션은 이름 그대로 작동합니다.








더 빠른 건설 로봇 작업


1~2주 마다 누군가 "왜 내 건설 로봇이 작동하지 않나요?"라고 질문하고, 그들이 제공하는 스크린샷에는 "600개의 작업에 재료/로봇이 누락됨"이라는 작은 경고가 표시되어 있는 것 같습니다. 이 문제는 로봇이 개발된 이래로 계속되어 왔으며, 오늘날에도 여전히 좋은 해결책을 찾지 못하고 있습니다.


문제는 로봇이 수행해야 하는 작업이 주어지면 게임에서 해당 작업을 수행할 수 있는 범위 내에 있는 물류 네트워크에서 가장 적합한 로봇을 찾아야 한다는 것입니다. "이 물류 네트워크가 엔티티의 범위 내에 있는가"에 대한 검사는 O(Roboport-Count)입니다. 플레이어가 로보포트 1개를 만들든, 10만 개를 만들든, 컴퓨터가 감당할 수 있는 만큼 만들 수 있기 때문에 속도가 얼마나 느려질지는 우리가 제어할 수 없습니다. 따라서 게임이 실행되는 동안 작업이 중단되지 않도록 해야 합니다. 이를 위해 매 틱마다 몇 개의 건설 로봇 작업만 처리합니다.


1.1에서는 게임이 업데이트될 때마다 건설 작업을 3번 확인합니다. 로봇을 찾지 못하면 현재 업데이트가 중지됩니다. 실패한 시도에 대한 알림은 10초 동안 지속됩니다. 따라서 초당 60회의 업데이트와 알림당 10초를 적용하면 첫 번째 알림이 종료되기 전까지 600개의 알림이 생성된다는 뜻입니다. 이것이 바로 "600개의 작업에서 재료/로봇이 누락됨"이라는 마법의 알림 문구의 정체입니다.


제가 팩토리오에서 일한 이래로 이런 방식으로 작동해왔고 앞으로도 기본적인 수준에서 이런 방식으로 작동할 것입니다. 플레이어가 더 많은 로보포트를 만들수록 작업 속도가 느려질 수 있다는 것을 알기 때문에 업데이트할 때마다 작업 확인 횟수를 늘릴 수는 없습니다.


올해 초에 누군가(포럼 게시물)가 이 문제를 다시 발견했지만, 저희가 할 수 없다고 말한 것을 직접 '해결'하기로 결정했습니다: "업데이트당 확인된 작업 수를 업데이트당 1개에서 374개로 늘림". 또한 36,815개의 로보포트를 구축했습니다. 예상대로 게임은 무척 느렸습니다.





하지만 느린 부분을 훨씬 더 빠르게 만들 수 있다면 어떨까 하는 생각이 들었습니다. 알고리즘을 더 빠르게 변경하는 것처럼요? 게임에서 로보포트 물류 및 건설 영역을 취하고 그 결과 사각형 합을 계산하는 일련의 로직이 이미 있다는 것을 기억했을 때 영감이 떠올랐죠. 간단히 말해서 모든 로보포트의 전체 면적을 커버하는 멋진 중복 제거 직사각형 세트를 생성하는 것입니다. 이를 렌더링에 사용하여 로보포트가 서로 가까이 있을 때 지나치게 많이 그려지는 것을 방지합니다.


결과적으로 직사각형을 정렬하는 작업과 함께 간단한 이진 검색을 수행하여 주어진 작업이 네트워크 영역 내에 있는지 확인할 수 있었습니다. 결국 36,815개의 로보포트에서 O(N), 900~직사각형 결합 영역에서 O(N), 900~직사각형 결합 영역에서 O(logN)으로 확인했습니다.


"이 네트워크에 있는지"를 확인하는 데 드는 시간이 비용이 많이 들던 것에서 본질적으로 무료로 바뀌었습니다. 이 속도 향상으로 작업 확인 속도를 2.0에서는 꽤 끌어올릴 수 있었고 이 문제를 해결할 수 있을 것으로 기대합니다.



언제나 그렇듯, 평소와 같은 장소에서 여러분의 생각을 보고하세요.