2013-03-09 2 views
1

매 0.1 초마다 NSTimer가있는 그리드에서 셀을 그립니다. 크기는 약 96x64 => 6144 셀/이미지입니다. 녹색 직사각형 대신 이미지를 드로잉하는 경우 4 배 느립니다!drawRect의 성능 향상 :

- (void)drawRect:(CGRect)rect 
{ 
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    UIGraphicsPushContext(context); 
    CGContextSetRGBFillColor(context, 0, 0, 0, 1); 
    CGContextFillRect(context, CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height)); 
    int cellSize = self.bounds.size.width/WIDTH; 
    double xOffset = 0; 
    for (int i = 0; i < WIDTH;i++) 
    { 
     for (int j = 0; j < HEIGHT;j++) 
     {     
       NSNumber *currentCell = [self.state.board objectAtIndex:(i*HEIGHT)+j]; 
       if (currentCell.intValue == 1) 
       { 
        [image1 drawAtPoint:CGPointMake(xOffset + (cellSize * i),cellSize * j)]; 
       } 
       else if (currentCell.intValue == 0){ 
        [image2 drawAtPoint:CGPointMake(xOffset + (cellSize * i),cellSize * j)]; 
       } 
     } 
    } 
    UIGraphicsPopContext(); 
} 

각 사각형에 png 또는 jpg를 그리려면 어떻게하면 더 빨리 만들 수 있을까요? 이미지의 크기가 이미 적절한 크기로 조정되었습니다.

+0

이미지가 실제로 이미지 파일의 크기가 조정되었거나 메모리 크기가 조정 되었습니까? –

+0

그들은 지금 메모리에서만 확장됩니다. 나는 전혀 결과가 없었던 파일들을 스케일링 해 보았습니다 (놀랐습니다)! 64x64 픽셀에서 10x10 픽셀로 변경되었습니다 ... – Shamino

+1

코드를 성능 향상을 위해 여러 가지 방법이 있습니다 (예 : 'CGPointMake'에있는 곱셈을 덧셈으로 변환하여'self.levelState.board'를'NSArray'가 아닌 C 배열로 만듭니다. 그러나 병목 현상은 다시 칠할 영역을 확인하지 않고 0.1 초마다 다시 칠해도 이상하게 보입니다.게임에서만 그런 칠을해야하기 때문에 OpenGL을 사용하는 이유는 무엇입니까? – Sulthan

답변

3
  • a)보기의 경계 외부에있는 이미지/rect를 다시 그리지 마십시오.

  • B)는 한 이미지는 이전 업데이트 이후하지 않은 변경이 /의 구형을 다시 그리기하지 마십시오 한 이미지는 dirtyRect

  • C 외부 /의 구형을) 다시 그리기하지 마십시오.

  • d) 레이어를 사용하여 이미지를 사전 렌더링하므로 그림을 그리는 데 을 렌더링 할 필요가 없습니다.

+0

a) 확인 b) 확인 c) 이전 그래픽 컨텍스트를 유지하려면 어떻게해야합니까/새 사각형 만 추가되고 이전 사각형은 그대로 유지해야합니까? d) 버퍼처럼 작동합니까? 비동기입니까? – Shamino

+0

지금 내가 믿는 c)와 d)는 현재 그래픽 컨텍스트에서 드로잉을하기 때문에 함께 해결되는 경우에만 가능합니다. 그 밖의 다른 작업은 비어있는/회색 포켓이 발생합니다 .... – Shamino

+0

UIImage * currentContext = [self drawCurrentContext ]; [currentContext drawInRect : self.bounds]; 그 결과를 전혀 시도하지 않은 채로 ... 여전히 greyish blob을 중간에서 시도해 보았습니다. 고려한 결과 저는 drawCurrentContext를 늦게 호출한다고 생각합니다. – Shamino

0

CGRectIntersects을 사용하여 이미지의 사각형이 dirtyRect 내부에 있는지 확인하고 그릴 필요가 있는지 확인하십시오.

1

성능 측면에서 코드를 개선하려고했습니다. 그러나 병목 현상에 대한 제 의견도 확인하십시오.

- (void)drawRect:(CGRect)rect { 
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    //UIGraphicsPushContext(context); //not needed UIView does it anyway 

    //use [UIView backgroundColor] instead of this 
    //CGContextSetRGBFillColor(context, 0, 0, 0, 1); 
    //CGContextFillRect(context, CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height)); 

    int cellSize = self.bounds.size.width/WIDTH; 
    double xOffset = 0; 

    CGRect cellFrame = CGRectMake(0, 0, cellSize, cellSize); 
    NSUinteger cellIndex = 0; 

    for (int i = 0; i < WIDTH; i++) { 
     cellFrame.origin.x = xOffset; 

     for (int j = 0; j < HEIGHT; j++, cellIndex++) {     
      cellFrame.origin.y = 0; 

      if (CGRectIntersectsRect(rect, cellFrame) { 
       NSNumber *currentCell = [self.state.board objectAtIndex:cellIndex]; 

       if (currentCell.intValue == 1) { 
        [image1 drawInRect:cellFrame]; 
       } 
       else if (currentCell.intValue == 0) { 
        [image2 drawInRect:cellFrame]; 
       } 
      } 

      cellFrame.origin.y += cellSize; 
     } 

     cellFrame.origin.x += cellSize; 
    } 

    //UIGraphicsPopContext(context); //not needed UIView does it anyway 
} 
+0

위의 코드를 구현 한 후 초당 10-20 프레임 정도의 속도 향상이있었습니다 .... 위와 같이 사용하게되어 대단히 감사합니다. 어떤 사람이 그렇게 할 수 있다면 내가 새롭기 때문에 ... – Shamino

2

이 시나리오는 Instruments와 정확히 일치합니다. 그걸 써. 여기에 제안을하는 사람은 누구나 병목 현상이 무엇인지 추측 할 수 있습니다.

그렇다면 병목 현상이 무엇인지 추측 할 것입니다. CPU를 사용하여 6114 개의 이미지를 그리는 중입니다 (시간 프로파일 러를 사용하여 확인하십시오.) drawRect 메서드를 찾고 가장 많은 시간을 사용했는지 확인하십시오. drawInRect이면 문제가됩니다.

우리는 그 사용을 줄이려고합니까? 쉬운 우승은 우리가 그릴 필요가있는 이미지를 다시 그리는 것입니다. CALayers는 이것을 쉽게 만듭니다. drawRect 메서드를 제거하고 각 이미지의 뷰 레이어에 하위 레이어를 추가하고 이미지를 레이어의 내용 속성으로 설정합니다. 이미지를 변경해야 할 때 뷰를 무효화하는 대신 관련 레이어의 content 속성을 새 이미지로 전환하면됩니다.

CALayers의 또 다른 장점은 레이어 내용을 GPU에 캐시한다는 것입니다. 즉, 발생하는 다시 그리기가 CPU 시간을 덜 필요로하고 나머지 부분이 발생했을 때이를 차단하지 않을 것입니다.

많은 계층의 오버 헤드가 용납 될 수 없다면 (Instrument는 친구입니다) CAReplicatorLayer를 확인하십시오. 많은 CALayers를 사용하는 것보다 유연성이 떨어지지 만 최소한의 오버 헤드로 단일 이미지를 여러 번 복제 할 수 있습니다.

+0

네, 그 방법에 대해서 .. CALayers를 시도 할 것입니다 ... – Shamino

+0

이 문제에 대한 새 스레드가 열렸습니다 : http://stackoverflow.com/questions/15315619/잃어 버리지 않고 컨텍스트 - 무의미한 방법으로 그리는 방법/15322628 # 15322628 – Shamino