현재 서버는 일정 시간 간격마다 Room.Flush()를 실행하는 구조
while (true)
{
Room.Push(() => Room.Flush());
Thread.Sleep(250);
}
✅ 기존 방식의 특징
Room.Flush() 실행 Thread.Sleep()을 사용하여 일정 간격 유지 ❌ 일정 주기 실행의 비효율성
❌ 비효율적인 시간 체크
while 문 안에서 모든 작업을 체크해야 함 if 문 체크가 증가하여 성능 저하 ❌ 우선순위 없는 실행 방식
✅ 기대 효과
JobTimerElem은 실행할 작업과 실행 시간을 포함하는 구조체
using System;
using System.Collections.Generic;
using ServerCore;
namespace Server
{
struct JobTimerElem : IComparable<JobTimerElem>
{
public int execTick; // 실행 시간
public Action action; // 실행할 작업
public int CompareTo(JobTimerElem other)
{
// 실행 시간이 빠른 순서로 정렬
return other.execTick - execTick;
}
}
}
✅ 핵심 개선 사항
execTick: 실행될 시간 action: 실행할 작업 CompareTo(): 작업을 실행 시간이 빠른 순서대로 정렬 using System;
using System.Collections.Generic;
using System.Text;
using ServerCore;
namespace Server
{
class JobTimer
{
PriorityQueue<JobTimerElem> _pq = new PriorityQueue<JobTimerElem>();
object _lock = new object();
public static JobTimer Instance { get; } = new JobTimer();
public void Push(Action action, int tickAfter = 0)
{
JobTimerElem job;
job.execTick = System.Environment.TickCount + tickAfter;
job.action = action;
lock (_lock)
{
_pq.Push(job);
}
}
public void Flush()
{
while (true)
{
int now = System.Environment.TickCount;
JobTimerElem job;
lock (_lock)
{
if (_pq.Count == 0)
break;
job = _pq.Peek();
if (job.execTick > now)
break;
_pq.Pop();
}
job.action.Invoke();
}
}
}
}
✅ 핵심 개선 사항
Push(): 실행할 작업을 execTick 시간에 맞게 예약 Flush(): 실행 시간이 된 작업을 실행 while 문을 통해 실행 시간이 가장 임박한 작업을 먼저 실행 using System.Net;
using System.Threading;
using ServerCore;
namespace Server
{
class ServerProgram
{
static Listener _listener = new Listener();
public static GameRoom Room = new GameRoom();
static void FlushRoom()
{
Room.Push(() => Room.Flush());
JobTimer.Instance.Push(FlushRoom, 250);
}
static void Main(string[] args)
{
string host = Dns.GetHostName();
IPHostEntry ipHost = Dns.GetHostEntry(host);
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint endPoint = new IPEndPoint(ipAddr, 1111);
_listener.Init(endPoint, () => { return SessionManager.Instance.Generate(); });
System.Console.WriteLine("Listening...");
JobTimer.Instance.Push(FlushRoom);
while (true)
{
JobTimer.Instance.Flush();
}
}
}
}
✅ 핵심 개선 사항
FlushRoom() 함수로 Room.Flush() 실행을 JobTimer에 예약 JobTimer.Instance.Push(FlushRoom, 250) → 0.25초마다 실행 예약 JobTimer.Flush() 실행하여 예약된 작업 실행 using System;
using System.Collections.Generic;
using System.Text;
namespace ServerCore
{
public class PriorityQueue<T> where T : IComparable<T>
{
List<T> _heap = new List<T>();
public int Count { get { return _heap.Count; } }
public void Push(T data)
{
_heap.Add(data);
int now = _heap.Count - 1;
while (now > 0)
{
int next = (now - 1) / 2;
if (_heap[now].CompareTo(_heap[next]) < 0)
break;
T temp = _heap[now];
_heap[now] = _heap[next];
_heap[next] = temp;
now = next;
}
}
public T Pop()
{
T ret = _heap[0];
int lastIndex = _heap.Count - 1;
_heap[0] = _heap[lastIndex];
_heap.RemoveAt(lastIndex);
lastIndex--;
int now = 0;
while (true)
{
int left = 2 * now + 1;
int right = 2 * now + 2;
int next = now;
if (left <= lastIndex && _heap[next].CompareTo(_heap[left]) < 0)
next = left;
if (right <= lastIndex && _heap[next].CompareTo(_heap[right]) < 0)
next = right;
if (next == now)
break;
T temp = _heap[now];
_heap[now] = _heap[next];
_heap[next] = temp;
now = next;
}
return ret;
}
public T Peek()
{
if (_heap.Count == 0)
return default(T);
return _heap[0];
}
}
}
✅ 핵심 개선 사항
Push(): 새로운 작업을 추가하며 Heap 정렬 Pop(): 실행할 작업을 꺼내면서 Heap 유지 Peek(): 가장 빠른 실행 시간을 가진 작업 조회