2017-10-25 6 views
-1

C#에서 cgi를 실험하고 있습니다. 크기를 조절할 수있는 사각형 안에 정사각형 (화살표가있는)을 움직일 수있는 앱을 만들었습니다. 크기를 조정하기 위해 하나 이상의 직사각형을 페인팅합니다. 충돌 클래스를 사용하여 가장자리를지나 이동을 제한합니다.너무 많은 메모리를 사용하는 C# 콘솔 CGI 그래픽

모든 것이 잘된 것처럼 보이지만 메모리 사용에 대해서는 우려합니다. 크기를 늘리면 메모리 소비가 증가하고 GC가 시작됩니다.

누군가이 누출을 찾도록 도와 줄 수 있습니까? 나는 그 사용량을 급증시키는 잘못된 것을하고 있습니까? 버퍼를 잘못 사용합니까?

EDIT :: 실제로,이 코드 줄이 메모리 사용을 유발하는 원인을 발견했습니다. 이 코드 블록을 주석 처리 한 후, 내 프로그램은 2GB 대신 16MB 만 사용했습니다.

if (player.rectHeight >= tempWidth) 
      { 
       Program.bufferedGraphics = context.Allocate(Program.graphics, 
    new Rectangle(0, 0, Convert.ToInt32(player.rectWidth) + 100, 
       Convert.ToInt32(player.rectHeight) + 100)); 
      } 

감사합니다.

코드

class Program 
{ 

    static Graphics graphics; 
    static BufferedGraphics bufferedGraphics; 
    static Player player; 
    static Collision collision; 
    static Utility utility; 
    static SByte value = 0; 
    static float tempWidth = 500; 
    static void Main() 
    { 
     Program.player = new Player(); 
     Program.utility = new Utility(); 
     Program.collision = new Collision(); 
     Console.CursorVisible = false; 
     Process process = Process.GetCurrentProcess(); 
     Program.graphics = Graphics.FromHdc(GetDC(process.MainWindowHandle)); 
     BufferedGraphicsContext context = BufferedGraphicsManager.Current; 
     context.MaximumBuffer = new Size(Console.WindowWidth, Console.WindowHeight); 
     Program.bufferedGraphics = context.Allocate(Program.graphics, new Rectangle(0, 0, Convert.ToInt32(player.rectWidth), 
      Convert.ToInt32(player.rectHeight))); 


     while (true) 
     { 
      collision.worldEdges = new Collision.WorldEdges() 
      { 
       rightBorder = Convert.ToInt32(player.rectWidth), 
       leftBorder = 0, 
       topBorder = 0, 
       bottomBorder = Convert.ToInt32(player.rectHeight), 
      }; 
      if (player.rectHeight >= tempWidth) 
      { 
       Program.bufferedGraphics = context.Allocate(Program.graphics, new Rectangle(0, 0, Convert.ToInt32(player.rectWidth) + 100, 
       Convert.ToInt32(player.rectHeight) + 100)); 
      } 
      //Debug.Print(Convert.ToString(player.rectHeight)); 
      // Debug.Print(Convert.ToString(player.x)); 
      //Debug.Print(Convert.ToString(player.x- collision.worldEdges.rightBorder)); 
      if (player.y > collision.worldEdges.bottomBorder-19.7f) // if on the edge, clamp its movement 
      { 
       player.y = collision.worldEdges.bottomBorder-19.8f; 


      } 
      if (player.x > collision.worldEdges.rightBorder - 19.7) 
      { 
       player.x = collision.worldEdges.rightBorder - 19.8f; 
      } 
      else 
      { 
       Program.player.DoMove(); 
      } 
      Program.player.ResizeScreen(out value); //check whether resize the rectangle 

      if (value ==1) //g decrease size 
      { 
       bufferedGraphics.Graphics.FillRectangle(Brushes.Black, 0, 0, 
        Convert.ToInt32(player.rectWidth), Convert.ToInt32(player.rectHeight)); 
       player.rectHeight -= 0.08f; 
       player.rectWidth -= 0.08f; 
       tempWidth = player.rectWidth; 
      } 
      if (value == -1) //h increase size 
      { 
       bufferedGraphics.Graphics.FillRectangle(Brushes.Black, 0, 0, 
        Convert.ToInt32(player.rectWidth), Convert.ToInt32(player.rectHeight)); 
       player.rectHeight += 0.08f; 
       player.rectWidth += 0.08f; 
       //Program.bufferedGraphics = context.Allocate(Program.graphics, new Rectangle(0, 0, 320,200)); 
       bufferedGraphics.Graphics.FillRectangle(Brushes.Green, 0, 0, Convert.ToInt32(player.rectWidth), 
      Convert.ToInt32(player.rectHeight)); 
       tempWidth = player.rectWidth; 
      } 
      else 
      { 
       bufferedGraphics.Graphics.FillRectangle(Brushes.Green, 0, 0, Convert.ToInt32(player.rectWidth), 
     Convert.ToInt32(player.rectHeight)); 
      } 
      Program.player.DrawPlayer(Program.bufferedGraphics.Graphics, Brushes.Blue); //draw player controlled cube 
      Program.bufferedGraphics.Render(Program.graphics); //finally render on screen 

     } 
    } 
    [DllImport("user32.dll", CharSet = CharSet.Auto)] 
    public static extern IntPtr GetDC(IntPtr hWnd); 
    [DllImport("user32.dll", CharSet = CharSet.Auto)] 
    static extern short GetKeyState(int nVirtKey); 
} 
class Player //detect input and set player size and it's movement 
{ 
    const int LEFT = 0x25; 
    const int UP = 0x26; 
    const int RIGHT = 0x27; 
    const int DOWN = 0x28; 
    const int G = 0x47; 
    public float rectWidth = 200, rectHeight = 200; 
    public float x; 
    public float y; 
    public Player() 
    { 
     this.x = 0; 
     this.y = 0; 
    } 
    public void DoMove() 
    { 

     if ((GetKeyState(LEFT) | 0x8000) > 0 && this.x < rectWidth-10) 
     { 
      this.x += 0.1f; 
     } 
     if ((GetKeyState(RIGHT) | 0x8000) > 0 && this.x > 0) 
     { 
      this.x -= 0.1f; 
     } 
     if ((GetKeyState(UP) | 0x8000) > 0) 
     { 
      this.y += 0.1f; 
     } 
     if ((GetKeyState(DOWN) | 0x8000) > 0 && this.y > 0) 
     { 
      this.y -= 0.1f; 
     } 
    } 
    public void DrawPlayer(Graphics g, Brush color) 
    { 
     g.FillRectangle(color, this.x , this.y , 20, 20); 
    } 
    public void ResizeScreen(out SByte value) 
    { 
     if ((GetKeyState(G) | 0x8000) < 0) 
     { 
      value = 1; 
     } 
     else if ((GetKeyState(0x48) | 0x8000) < 0) 
     { 
      value = -1; 
     } 
     else 
     { 
      value = 0; 
     } 
    } 
    [DllImport("user32.dll")] 
    static extern short GetKeyState(int nVirtKey); 

} 
class Collision //used for colliding with other objects and world boundaries 
{ 
    public struct WorldEdges 
    { 
     public int leftBorder; 
     public int rightBorder; 
     public int topBorder; 
     public int bottomBorder; 
    } 
    public WorldEdges worldEdges; 


} 

답변

0

은 메모리 소비가 증가하고 GC가 포함됩니다 것은 놀라운 일이 아니다. 반복적으로 큰 버퍼 (bufferedGraphics)를 할당하는 무한 루프가 있고, 그것을 사용하고 매달려 있습니다. 미친 것처럼 기억을 소비하고있을뿐 아니라 일회용 물체를 처분하지 못하고 있습니다.

BufferedGraphics 클래스는 IDisposable interface을 구현합니다. 즉, 사용 완료 후 Dispose 메서드를 호출해야합니다. 이렇게하면 메모리 부족을 상당히 완화 할 수 있습니다. 기억력을 없애지는 못하지만 조금 완화시켜야합니다.

bufferedGraphics 개체를 한 번만 할당하고 다시 사용할 수도 있습니다. 나는 충분히 친숙하지 않다. BufferedGraphics, 그래서 나는 그것이 합리적인지 여부를 말할 수 없다. 그러나 그렇게 할 수 있다면 프로그램에 대한 GC의 영향을 줄이기 위해 먼 길을 가야합니다.

마지막으로 while (true) 루프에서 최고 속도로 실행하려면이 기능이 필요합니까? 타이머에서이를 수행 할 수 있다면 20 또는 50 밀리 초마다 한 번씩 말하면 CPU 및 메모리의로드가 줄어 듭니다.

+0

답변 해 주셔서 감사합니다. 확실히 코드를 업데이트 할 것입니다. –

+0

나는 그 누출의 원인을 강조하기 위해 나의 질문을 편집했다. –