서버 공부

[서버 공부]2.컴파일 최적화 + 캐시

myjeongjun 2025. 1. 1. 01:27

만약 이런 식으로 코드를 작성하고 실행해보자

using System;
using System.Threading;
using System.Threading.Tasks;

namespace ServerCore
{
    internal class Program
    {
        static bool _stop = false;
        
        static void ThreadMain()
        {
            Console.WriteLine("쓰레드 시작");
            while (_stop == false)
            {
                //STOP 신호를 해주기를 기다린다.
            }
            Console.WriteLine("쓰레드 종료!");
        }
        static void Main(string[] args)
        {

            Task t = new Task(ThreadMain);
            t.Start();

            Thread.Sleep(1000);//밀리세컨드 단위라 1초임

            _stop = true;

            Console.WriteLine("stop호출");
            Console.WriteLine("종료 대기중");
            t.Wait();
            Console.WriteLine("종료 성공");

            }
        }
    }

 

 

의도한대로 잘 출력할 것이다.

 

하지만 나중에 실제 게임 배포시 debug모드가 아닌 release모드로 하게되는데 release모드는 온갖 최적화가 들어가기때문에 더 좋은 성능을 낼수 있는 장점이있다.

여기서 문제가 발생하는데 release모드로하고 실행시 

 

무슨 일인지 종료 대기중에서 멈춰버렸다.

스레드에 무슨 문제가 발생한것으로 보이기에 브레이크 포인트를 찍고

상단의 디버그 -> 창 -> 디스어셈블러로  어셈블러를 까보자

test를 통해 ecx에있는 레지스터값이 0인지를 확인후 0이면 다시 je를 실행해서 다시 test로 가게 만들어놨다.

 

이건 이코드를

            while (_stop == false)
            {

            }

 

이런식으로 바꿔놓았다고 생각하면 된다.


            if (_stop == false) 
            {
                while (true) 
                {

                }
            }

 

이 문제는 컴파일러의 버전에따라 발생안할수도있다.

 

뭐 이런 문제를 해결하려고 volatille라는 키워듣 존재 하긴 하지만 중요한 포인트는 release 모드 때문에 멀티스레드를 사용하면서 문제가 비일비재하게 발생한다는 점이다.

 

캐시강의 부분 컴퓨터구조론에서도 다뤘듯 시간적,공간적 지역성을 이용해서 빠르게 작업한다는점을 강조했다.

 

지역성에 대한 자세한 설명은 이미 다뤘으니 생략하고 이것을 확인해보는 코드를 작성해보자

using System;
using System.Threading;
using System.Threading.Tasks;

namespace ServerCore
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //캐시 

            int[,] arr = new int[10000, 10000];
            {
                long now = DateTime.Now.Ticks;
                for (int y = 0; y < 10000; y++)
                {
                    for (int x = 0; x < 10000; x++)
                    {
                        arr[y, x] = 1;

                    }
                }
                long end = DateTime.Now.Ticks;
                Console.WriteLine($"(y,x)순서 걸린 시간{end - now}");
            }

            {
                long now = DateTime.Now.Ticks;
                for (int y = 0; y < 10000; y++)
                {
                    for (int x = 0; x < 10000; x++)
                    {
                        arr[x, y] = 1;
                    }
                }
                long end = DateTime.Now.Ticks;
                Console.WriteLine($"(x,y)순서 걸린 시간{end - now}");


            }

        }
    }
}

 

위와 아래를 비교하면 대충 이런느낌이다.

 

 

 

그래서 위의 케이스는 공간적 지역성의 Hit될 확률이 매우높기때문에 x,y보다 훨씬 빠른 시간내에 끝낸다.