вопрос по классу Graphics
От: willi-spb Россия  
Дата: 19.06.14 10:48
Оценка:
привожу полный пример тестового файла — собственно вывод квадратика и текста в нем и под ним на экран с помощью
Graphics

Если используется таймер для перерисовки данного класса, то возникает ситуация с увеличением памяти как в самой среде Sciter, так и в программе (если она использует sciter.dll).
Т.е. память по графике не освобождается.

Как сделать, чтобы память при перерисовке освобождалась — возможно что-то в примере некорректно?


<html>
  <head>
    <title>Sciter2 </title>
    <style>
    
      div.Speedometer { 
        prototype:SpeedTT; 
        width:*;
        height:*;
        border:1px solid black;
      }
    
    </style>
    <script type="text/tiscript">
    
    // 2 вспомогат функции прорисовки
    // квадрат от центра
    function w_drawRectCenter(gfx,ax,ay,aWidth,aHeight,aRx=0,aRy=0)
  {
   var LRx=aRx;
   var LRy=aRx;
   if ((LRx>0) && (aRy>0)) {LRy=aRy}
   //
   if (LRx==0) {gfx.rectangle(ax-aWidth*0.5,ay-aHeight*0.5,aWidth,aHeight);}
   else {gfx.rectangle(ax-aWidth*0.5,ay-aHeight*0.5,aWidth,aHeight,LRx,LRy)}
  }
    //
    // текст в центре
   function w_drawTextCenter(gfx,Ltext,aLength,ax,ay,aSize,aLineWidth)
  {
   var L_deltaBaseLine=aSize/6;  // текст по базовой линии - поэтому сдвигаем его относительно нее вверх
   var L_L =Ltext; 
       L_L.font("Arial",aSize);
       L_L.width(aSize*(aLength+1));
       L_L.height(aSize);
       var (at,at1)=L_L.width();        
       //gfx.rectangle(-at*0.5,-L_L.height()*0.5,at+aLineWidth*2,L_L.height());
        gfx.save();
        gfx.drawText(L_L,ax-at*0.5,ay-L_L.height()*0.5-L_deltaBaseLine,7);    
        gfx.restore();
       return true;
  }
  
    
    // класс Behavior
      class SpeedTT: Behavior        
       {
       function attached() { 
         this.paintContent =this.drawSpeed;
       }
       
       function drawSpeed(gfx)
            { 
             var (x,y,w,h) = this.box(#rectw);
             var scale = w < h? w / 300.0: h / 300.0; 
             //             
             gfx.save();            
             gfx.translate(w*0.5,h*0.5);
             var Lmin = w < h? w: h;
             gfx.lineWidth(1);
             gfx.lineColor(color("red"));
             gfx.fillColor(color("yellow"));
             w_drawRectCenter(gfx,0,0,200,120,5,5);
             var TextStr1="Text+BB+text";
             var TextStr2="gggggggggggggggggggggggggggggggggggggggg";
             var LL1=new Graphics.Text(TextStr1);
             var LL2=new Graphics.Text(TextStr2);             
             gfx.lineColor(color("navy"));
             gfx.fillColor(color("lime"));
             var LtextSize=16;
             w_drawTextCenter(gfx,LL1,TextStr1.length, 0,0,LtextSize+8,1);
             w_drawTextCenter(gfx,LL2,TextStr2.length, 0,150,LtextSize+8,1);
             //             
             gfx.restore();
            }
        }
    
    //////  основное
    function self.ready(){
     
      var body = $(body);
      
      $(#spTT).prototype=SpeedTT;
      $(#spTT).attached();
    
      body.timer(30,function(){$(#spTT).refresh(); return true;});
      
     }

    </script>
  </head>
<body>
  <h2>Sciter2 test_TT</h2>
  <div #spTT class="Speedometer" ></div>

</body>
</html>
Re: вопрос по классу Graphics
От: c-smile Канада http://terrainformatica.com
Дата: 20.06.14 05:50
Оценка:
Здравствуйте, willi-spb, Вы писали:

Когда ты делаешь это или

var LL1 = new Graphics.Text(TextStr1);
var PP1 = new Graphics.Path();


то ты создаешь объекты в native/GPU memory space. В скриптовом пространстве они занимают всего ничего.
Поэтому GC в общем случае для них не срабатывает (вернее срабатывает, но в отдаленном будещем).

У тебя есть три опции:

1. создавать Graphics.Text один раз и его выводить не пересоздавая. Наиболее эффективный вариант.
2. создавать Graphics.Text и удалять его когда он не нужен: LL1.destroy();
3. время от временм принудительно вызывать garbage collector: gc();
Re[2]: вопрос по классу Graphics
От: willi-spb Россия  
Дата: 20.06.14 07:55
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Здравствуйте, willi-spb, Вы писали:


CS>Когда ты делаешь это или


CS>
CS>var LL1 = new Graphics.Text(TextStr1);
CS>var PP1 = new Graphics.Path();
CS>


CS>то ты создаешь объекты в native/GPU memory space. В скриптовом пространстве они занимают всего ничего.

CS>Поэтому GC в общем случае для них не срабатывает (вернее срабатывает, но в отдаленном будещем).

CS>У тебя есть три опции:


CS>1. создавать Graphics.Text один раз и его выводить не пересоздавая. Наиболее эффективный вариант.

CS>2. создавать Graphics.Text и удалять его когда он не нужен: LL1.destroy();
CS>3. время от временм принудительно вызывать garbage collector: gc();


Добрый день!
1. создавать объект один раз — используется для работы с Image — в данном примере подразумевается,
что текст будет меняться достаточно быстро (например показания прибора в динамике)
2.
добавил в данный пример: LL1.destroy();
LL2.destroy(); перед вызовом gfx.restore();и после — память растет

3.добавил в ready() таймер на очистку мусора body.timer(500,function(){gc(); return true;});

привожу чуть измененный пример — с учетом указанных Вами корректировок — память все равно увеличивается

Версия скайтера 3.0.2.5

<html>
  <head>
    <title>Sciter2 </title>
    <style>
    
      div.Speedometer { 
        prototype:SpeedTT; 
        width:*;
        height:*;
        border:1px solid black;
      }
    
    </style>
    <script type="text/tiscript">
    
    // 2 вспомогат функции прорисовки
    // квадрат от центра
    function w_drawRectCenter(gfx,ax,ay,aWidth,aHeight,aRx=0,aRy=0)
  {
   var LRx=aRx;
   var LRy=aRx;
   if ((LRx>0) && (aRy>0)) {LRy=aRy}
   //
   if (LRx==0) {gfx.rectangle(ax-aWidth*0.5,ay-aHeight*0.5,aWidth,aHeight);}
   else {gfx.rectangle(ax-aWidth*0.5,ay-aHeight*0.5,aWidth,aHeight,LRx,LRy)}
  }
    //
    // текст в центре
   function w_drawTextCenter(gfx,Ltext,aLength,ax,ay,aSize,aLineWidth)
  {
   var L_deltaBaseLine=aSize/6;  // текст по базовой линии - поэтому сдвигаем его относительно нее вверх
   var L_L =Ltext; 
       L_L.font("Arial",aSize);
       L_L.width(aSize*(aLength+1));
       L_L.height(aSize);
       var (at,at1)=L_L.width();        
       //gfx.rectangle(-at*0.5,-L_L.height()*0.5,at+aLineWidth*2,L_L.height());
        gfx.save();
        gfx.drawText(L_L,ax-at*0.5,ay-L_L.height()*0.5-L_deltaBaseLine,7);    
        gfx.restore();
       return true;
  }
  
    
    // класс Behavior
      class SpeedTT: Behavior        
       {
       function attached() { 
         this.paintContent =this.drawSpeed;
       }
       
       function drawSpeed(gfx)
            {        
             var (x,y,w,h) = this.box(#rectw);
             var scale = w < h? w / 300.0: h / 300.0; 
             //             
             gfx.save();            
             gfx.translate(w*0.5,h*0.5);
             var Lmin = w < h? w: h;
             gfx.lineWidth(1);
             gfx.lineColor(color("red"));
             gfx.fillColor(color("yellow"));
             w_drawRectCenter(gfx,0,0,200,120,5,5);
             var ii=rand(50000);
             var TextStr1=ii.toString();
             var TextStr2="gggggggggggggggggggggggggggggggggggggggg";
             var LL1=new Graphics.Text(TextStr1);
             var LL2=new Graphics.Text(TextStr2);             
             gfx.lineColor(color("navy"));
             gfx.fillColor(color("lime"));
             var LtextSize=16;
             w_drawTextCenter(gfx,LL1,TextStr1.length, 0,0,LtextSize+8,1);
             w_drawTextCenter(gfx,LL2,TextStr2.length, 0,150,LtextSize+8,1);
             //  
                       
             gfx.restore();
             LL1.destroy();
             LL2.destroy(); 
            }            
        }
    
    //////  основное
    function self.ready(){
     
      var body = $(body);
      
      $(#spTT).prototype=SpeedTT;
      $(#spTT).attached();
    
      $(#spTT).timer(30,function(){$(#spTT).refresh(); return true;});
      body.timer(200,function(){gc(); return true;});      
     }

    </script>
  </head>
<body>
  <h2>Sciter2 test_TT</h2>
  <div #spTT class="Speedometer" ></div>

</body>
</html>


конечно, таймер 30мсек — это немного утрированное значение, однако в реальной программе мне нужно показать "дребезг" стрелки прибора и отклонение значений в динамике и в этом случае 30мс — это близко к истине.
Может быть, у меня что-то еще некорректно сделано?
Re[3]: вопрос по классу Graphics
От: c-smile Канада http://terrainformatica.com
Дата: 20.06.14 18:35
Оценка:
Здравствуйте, willi-spb, Вы писали:

WS>Здравствуйте, c-smile, Вы писали:


Это вот
body.timer(200,function(){gc(); return true;});

тогда не надо если явно destroy вызываешь.

А memleak небольшой действительно увидел в new Graphics.Text(), поправил уже. В след. билде будет.
Re[3]: вопрос по классу Graphics
От: c-smile Канада http://terrainformatica.com
Дата: 21.06.14 19:46
Оценка:
Здравствуйте, willi-spb, Вы писали:

Попробуй 3.1.0.3 и посмотри пример sdk/samples/graphics/digital-clock.htm — это про то как оптимально делать такие вещи.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.