2017-11-07 6 views
2

플래시 편집기에서 이미지를 렌더링하는 AIR 앱이 있습니다. 여러 서피스를 사용자화할 수 있습니다 - 모두 동일한 너비와 높이를가집니다. 각 표면은 AIR 응용 프로그램에서 렌더링됩니다.AS3 드로잉 Sprite on BitmapData 메모리 누수

저는 메모리 누출 문제로 고심하고 있습니다.

렌더링해야하는 각 표면마다 많은 구성 요소 (다른 스프라이트 - 일부는 이벤트 리스너, BitmapDatas 및 기타 하위 구성 요소, 스프라이트 등)가 포함 된 스프라이트가 있습니다.

  • 가 하나의 BitmapData을 다시 null로

      (처리 후 렌더링 각각에 대해 새의 BitmapData를 만드는
    • ) 및 점 :

      내가 쓰레기 수집로 이미의 BitmapData 문제를 알고 있어요, 나는 모두를 테스트 각 렌더링

    메모리 누수는 여전히 같은 비율로 발생하고 있습니다.

    var bm:BitmapData = new BitmapData(destDim.x, destDim.y, true, bgColor); 
    var mtx:Matrix = new Matrix(); 
    trace('before drawing :'+(System.privateMemory/1024)); 
    bm.draw(myBigSprite, mtx, null, null, null, true); 
    trace('after drawing :'+(System.privateMemory/1024)); 
    var result:Bitmap = new Bitmap(bm, PixelSnapping.NEVER, true); 
    
    //return result and encode Bitmap to png 
    
    result.bitmapData.dispose(); 
    result.bitmapData = null; 
    result = null; 
    

    결과 : 나는 그리기 기능 동작에서 뭔가 빠진 것 같은 기분

    before drawing :208364 
    after drawing :302816 
    Wrote bitmap to file: surface0.png 
    before drawing :303296 
    after drawing :446160 
    Wrote bitmap to file: surface1.png 
    before drawing :446160 
    after drawing :565212 
    Wrote bitmap to file: surface2.png 
    before drawing :565924 
    after drawing :703100 
    Wrote bitmap to file: surface3.png 
    before drawing :703572 
    after drawing :834420 
    Wrote bitmap to file: surface4.png 
    

    여기 내 루프입니다. 그것은 그리기 작업 후에도 지속되는 myBigSprite의 구성 요소 인스턴스를 새로 만든 것처럼 보입니다.

    내가 완전히 각 루프의 끝에서 myBigSprite을 파괴하려고

    , 그것은 아무것도 ....

    이 어떤 힌트를 주시면 감사하겠습니다을 변경하지 않습니다!

  • +0

    당신은 어떻게 알 수 있습니까? 가비지 수집 프로세스가 실행 되었습니까? 당신이 그것을 강요합니까? 또한 sidenote와 마찬가지로 System.gc()를 호출하여 gc를 강제 실행하면 디버그 플레이어에서만 작동합니다. – Patang

    +0

    그리기 작업의 끝과 다음 작업의 시작 사이의 메모리는 거의 동일하지만 그 사이에 많은 메모리를 소비하는 작업이 있습니다. 특히 비트 맵을 png로 인코딩합니다. 그래서 나는 GC 프로세스가 그 작업을하고 있다고 가정합니다. 그 이유는 내가 원하는 모든 리소스가 그려진 함수를 제외하고는 정리되어 있기 때문입니다. 결코 System.gc()를 명시 적으로 호출하지 않습니다. – Bedu33

    +0

    bitmapdata에 대한 참조를 보유하고 있으므로 "result"를 null로 설정합니까? – Patang

    답변

    0

    안녕하세요, 저는 결국이 문제를 이해하고 수정했습니다.

    우선, Adobe Scout를 설치하고 실행했습니다. 우수한 도구. 당신이 볼 수있는 바와 같이

    Adobe Scout memory profiling

    는 (플러스는 프랑스어에서의), 나는 가장자리에 해당하는 3 표면을 생성. 오른쪽의 대용량 메모리 인 "큰"녹색 막대는 "비트 맵 표시 객체"를 나타냅니다. 흥미 롭 군! 전에는 들어 본 적이 없었습니다., https://help.adobe.com/en_US/as3/dev/WS5b3ccc516d4fbf351e63e3d118a9b90204-7e26.html

    그것은 PICT는 Loader 객체의로드 작업이 완료되면, 앞에서 인용 한 코드에서, 예를 들어

    설명 :

    구글 검색 후, 나는이 글을 발견 pict 객체는 비트 맵인 하나의 자식 표시 객체를로드합니다. 이 비트 맵 표시 객체 에 액세스하려면 pict.getChildAt (0)를 작성할 수 있습니다.

    그래서 어쨌든, 어쩌면 비트 맵 객체가 의 일부 객체에 어린이로 첨부됩니다.

    마지막으로, 내가 검색하고 draw 작동

    //inside render function 
    bm.draw(myBigSprite, mtx, null, null, null, true); 
    destroyDisplayObjects(myBigSprite); 
    

    후에 myBigSprite에 포함 된 모든 Bitmap, BitmapDataByteArray 오브젝트를 파괴하는 재귀 함수 ...

    private function destroyDisplayObjects(obj):void{ 
        if ("numChildren" in obj){ 
         for (var i:int = 0; i<obj.numChildren; i++) 
         { 
          destroyDisplayObjects(obj.getChildAt(i)); 
         } 
        } 
        else { 
         if (flash.utils.getQualifiedClassName(obj) == "flash.display::Bitmap"){ 
          //trace ('FREE BITMAP'); 
          obj.bitmapData.dispose(); 
          obj.bitmapData = null; 
          obj = null; 
          return; 
         } 
         else if (flash.utils.getQualifiedClassName(obj) == "flash.display::BitmapData"){ 
          //trace ('FREE BITMAPDATA'); 
          obj.dispose(); 
          obj = null; 
          return; 
         } 
         else if (flash.utils.getQualifiedClassName(obj) == "flash.display::ByteArray"){ 
          //trace ('FREE BYTEARRAY'); 
          obj.clear(); 
          obj = null; 
          return; 
         } 
    
         return; 
        } 
    } 
    

    잇를 늘리면 생성, 메모리 무승부 작업 후 100 % 청소, 더 이상 누출되지 않습니다 :)

    0

    BitmapData을 함수 밖에서 선언 한 다음 루프 내에 사용하기 위해 (메모리에 추가 할 내용이 모두 new이 아닌) 리사이클링하면됩니다.

    변수 bm의 비트 맵 데이터가 더 이상 필요하지 않을 때 마지막 이미지에만 .dispose()을 사용하십시오. 다른 경우 처분 될 경우 추가 사용을 위해 새 대안 인 var someThing :BitmapData = new BitmapData을 다시 만들어야합니다.

    ////# declare globally (not inside some specific function..) 
    
    //var destDim :Point = new Point(your_X_num , your_Y_num); 
    //var bgColor :uint = 0x505050; 
    
    var bm:BitmapData = new BitmapData(destDim.x, destDim.y, true, bgColor); 
    var result:Bitmap = new Bitmap(bm, PixelSnapping.NEVER, true); 
    //result.bitmapData = bm; //can be set here but done within function for clarity... 
    
    var mtx:Matrix = new Matrix(); 
    
    
    ////# update bitmap by replacing its bitmapdata with new colour values of existing pixels 
    
    function Here_is_my_loop(): void 
    { 
        trace('before drawing :'+(System.privateMemory/1024)); 
    
        //overwrite pixel colours in bitmap (result) 
        bm.draw(myBigSprite, mtx, null, null, null, true); 
        result.bitmapData = bm; //update bitmap 
    
        trace('after drawing :'+(System.privateMemory/1024)); 
    
    
        //return result and encode Bitmap to png 
    
        //result.bitmapData.dispose(); 
        //result.bitmapData = null; 
        //result = null; 
    } 
    
    +0

    답변 해 주셔서 감사합니다. 불행하게도 원래 게시물에서 말했듯이 재사용 된 BitmapData를 사용하면 동일한 결과를 얻을 수 있습니다. 그러나 한 번 더 해보 았는데 동일한 결과가 있음을 확인했습니다. – Bedu33

    +0

    흠. 내가 어떻게 놓쳤는 지 잘 모르겠다. "각각의 렌더링에 대해 하나의 BitmapData를 재사용한다"_ 마지막으로, 루프에서'new'를 사용하면 메모리를 먹는 좋은 방법입니다. 내 코드는 ** 이미 존재하는 데이터를 덮어 쓰는 ** 것이어야하므로 어떻게 든 ** 새로운 데이터를 추가하는 방법 (메모리 사용량 증가)을 이해할 수 없습니다. 가능한 경우 플래시로 이동하겠습니다. –

    +0

    "내 코드는 이미 기존 데이터를 덮어 쓰면 어떻게 든 새로운 데이터를 추가하는 방법 (메모리 사용량을 늘리는 방법)을 이해할 수 없습니다." 이것은 정확하게 내 질문이기도합니다. :) – Bedu33