Pull to refresh

Снижаем нагрузку на процессор в Adobe AIR

Reading time 10 min
Views 4.2K
 
Снижаем нагрузку на процессор в Adobe AIR

Давайте будем честны. AIR часто ругают за непомерное потребление оперативной памяти и ресурсов процессора при использовании в режиме реального времени. Несмотря на то, что многие программы написанные на AIR грешат этим, данных проблем можно избежать. Существует несколько методик, позволяющих писать более "лёгкие" программы, которые превосходят другие написанные стандартными средствами в плане производительности.

Один из самых простых способов резко снизить нагрузку на ЦП основан на изменении частоты обновлений окна в секунду (Framerate Throttling). В этой статье я объясню метод с framerate'ами и покажу, как наилучшим образом использовать данный метод в Ваших программах.

Примечание: Чтобы использовать данный метод Вы должны иметь основные понятия об ActionScript'е и программировании на AIR.

Что же такое замедление framerate'ов (Framerate Throttling)?

Замедление framerate'ов — это техника, позволяющая контролировать framerate'ы программы, что, в свою очередь, позвляет увеличить её производительность при использовании (Active) и снизить количество потребляемые ресурсов когда она не используется (Idle). Как и в ActionScript 3, разрабочики имеют необычнайно полезную строчку кода в своём распоряжении — Stage.frameRate. Она позволяет изменять количество обновлений окна программы в секунду на лету. В предыдущих версиях ActionScript у нас были существенные проблемы с внедрением этой функции в интегрированную среду разработки (IDE). К счастью, времена изменились и теперь сложные программы не "висят", задерживаясь в памяти компьютера в фоновом режиме.

Как же использовать Framerate Throttling?

Поскольку данная методика целиком основана на изменении параметров Stage.frameRate в сторону большей или меньшей величины, то настройка и улучшение производительности в целом зависят исключительно от самого разработчика. Впрочем, это так же зависит и от самой программы — некоторые из них позволяют использовать данную методику эффективнее, чем другие.

Примечание: производительность замерена на Macbook Pro 2.8 GHz Intel Core 2 Duo с использованием нижеизложенных примеров программного кода и выражена в процентах. Естественно, результаты будут варьироваться в зависимости от конфигурации машины.


"Новичок"

Самый простой способ использования методики замедления framerate'ов — NativeApplication Event.ACTIVATE и Event.DEACTIVATE, эти события увеличивают количество framerate'ов когда программа используется (Active) и уменьшает когда она неактивна (Idle). С единичным пустым окном результаты показали нагрузку процессора в 1.8% в режиме использования и 0.4% в режиме простоя. Вы вообще можете установить частоту обновлений окна программы 0.01 или выключить его, тогда программа занимает всего 0.2% от общей нагрузки ЦП, при этом я выяснил, что chrome окна при этом не теряет фокусировки.

package {
   import flash.desktop.NativeApplication;
   import flash.display.Sprite;
   import flash.events.Event;
 
   public class Application extends Sprite {
      public function Application () {
         __init ();
      }
     
      private function __init ():void {
         NativeApplication.nativeApplication.addEventListener
           (Event.ACTIVATE, __activate__);
         NativeApplication.nativeApplication.addEventListener
           (Event.DEACTIVATE, __deactivate__);
      }
     
      private function __activate__
         ($event:Event):void {
         stage.frameRate = 50;
      }
      private function __deactivate__ ($event:Event):void {
         stage.frameRate = 1;
      }
   }
}


"Продвинутый"

Определённые программы позволяют более эффективно использовать методику замедления framerate'ов. Например, программа, которой необходим какой-то уровень взаимодействия даже в фоновом режиме. Программа, у которой есть прокручиваемый контент (scrollable content) с ссылками, поэтому AIR позволяет мыши прокручивать содержимое программы, когда она активна, что в свою очередь означает, что в текущий момент вам нужно большее значение framerate'ов.

В этом примере, если программа находится в фоновом режиме, но при этом мышь прокручивает содержимое программы, MouseEvent.MOUSE_WHEEL увеличивает framerate и устанавливает Event.ENTER_FRAME событие, которое уменьшит framerate на половину секунды после прокручивания. В случаях схожих с этим, лучшим выбором будет использование буфера, что позволит не менять каждый раз framerate с каждым прокручиванием, а так же потому, что тогда не нужно будет событие для момента, когда колесо мыши находится в режиме простоя (Idle).


package {
   import flash.desktop.NativeApplication;
   import flash.display.Sprite;
   import flash.events.Event;
   import flash.events.MouseEvent;
   import flash.utils.getTimer;
 
   public class Application extends Sprite {
      public static const ACTIVE:int = 50;
      public static const INACTIVE:int = 1;
 
      public var active:Boolean;
      public var scrolling:Boolean;
      public var buffer:int;
     
      public function Application () {
         __init ();
      }
     
      private function __init ():void {
        NativeApplication.nativeApplication.addEventListener
        (Event.ACTIVATE, __activate__);
        NativeApplication.nativeApplication.addEventListener
        (Event.DEACTIVATE, __deactivate__);
        stage.addEventListener
        (MouseEvent.MOUSE_WHEEL, __mouseWheel__);
      }
     
      private function __activate__ ($event:Event):void {
         active = true;
         stage.frameRate = ACTIVE;
      }
      private function __deactivate__ ($event:Event):void {
         active = false;
         stage.frameRate = INACTIVE;
      }
      private function __mouseWheel__ ($event:MouseEvent):void {
         if (!active) {
           if (!scrolling) {
              stage.addEventListener
                (Event.ENTER_FRAME, __enterframe__);
           }
           stage.frameRate = ACTIVE;
           scrolling = true;
           buffer = getTimer () + 500;
         }
      }
      private function __enterframe__
         ($event:Event):void {
         if (buffer < getTimer ()) {
           stage.frameRate = INACTIVE;
           scrolling = false;
           stage.removeEventListener
            (Event.ENTER_FRAME, __enterframe__);
         }
      }
   }
}


"Эксперт"

Если оптимизация — смысл вашей жизни, то вы можете удивить своих друзей сложными манипуляциями с замедлением числа framerate'ов. (Примечание: это не впечатлит Вашу девушку).

В моих программах я люблю делать переходы из одного состояния окна в другое плавным и более эстетичным. Поэтому я использую высокое число framerate'ов — 50. К сожалению, такое большое число ведёт к сильной нагрузке на ЦП. Поэтому я устанавливаю framerate 50 только при движении элементов \ окон. После окончания движения, я снижаю количество framerate'ов до 24. Бывают случая, когда загрузчик проигрывает анимацию, в то время когда сама программа находится в фоновом режиме. Загрузчику не нужно 50 fps, поэтому я устанавливаю число framerate равное 5 когда програма видна в фоновом режиме и ставлю 1 когда не видна.

Примечание: для этого примера я использую animate() для вызова в начале каждого движения. Возможно, Вам захочется интегрировать свой собственный замедлитель fps в ваш tweet-движок, так что вам более не нужно будет вручную вызывать animate().

package {
   import flash.desktop.NativeApplication;
   import flash.display.Sprite;
   import flash.events.Event;
   import flash.utils.getTimer;
 
   public class Application extends Sprite {
      public static const ANIMATING:int = 50;
      public static const ACTIVE:int = 24;
      public static const INACTIVE_VISIBLE:int = 5;
      public static const INACTIVE_INVISIBLE:int = 1;
     
      public var active:Boolean;
      public var animating:Boolean;
      public var buffer:int;
     
      public function Application () {
         __init ();
      }
     
      private function __init ():void {
        NativeApplication.nativeApplication.addEventListener
        (Event.ACTIVATE, __activate__);
        NativeApplication.nativeApplication.addEventListener
        (Event.DEACTIVATE, __deactivate__);
      }
     
      public function activate ():void {
         if (!animating) {
           stage.frameRate = ACTIVE;
         }
      }
      public function deactivate ():void {
         if (!animating) {
           stage.frameRate = (stage.nativeWindow.visible) ?
              INACTIVE_VISIBLE : INACTIVE_INVISIBLE;
         }
      }
      public function animate ($duration:int = 1000):void {
         stage.frameRate = 50;
         buffer = getTimer () + $duration;
         animating = true;
        
         if (!animating) {
           stage.addEventListener (Event.ENTER_FRAME, __checkBuffer__);
         }
      }
     
      private function __activate__ ($event:Event):void {
         active = true;
         activate ();
      }
      private function __deactivate__ ($event:Event):void {
         active = false;
         deactivate ();
      }
      private function __checkBuffer__ ($event:Event):void {
         if (buffer < getTimer ()) {
           stage.removeEventListener
           (Event.ENTER_FRAME, __checkBuffer__);
           animating = false;
           if (active) {
             activate ();
           } else {
             deactivate ();
           }
         }
      }
   }
}


Замедление framerate'ов лишь малая глава в оптимизации вашей программы, написанной на AIR. Но это основы оптимизации, и применение данной методики приведёт Вас к оптимальному использованию ресурсов компьютера при написании программ. Согласитесь, никто не любит громоздкие и неудобные программы.

Об авторе

Джонни — опытный дизайнер команды XDCE Adobe. До присоединения к Adobe, он разрабатывал программы на AIR такие как DestroyFlickr и DestroyTwitter в своё свободное время для развлечения. Так же у него есть собственный блог, "Destroy Today", который стал возможностью для него делиться своими находками в программировании с другими. Довольно странно, ведь Джонни получил Бакалавра в Колледже искуств при институте Мэриленда.
 
Оригинальный текст на английском языке тут:
www.adobe.com/devnet/air/flex/articles/framerate_throttling.html
Tags:
Hubs:
+35
Comments 19
Comments Comments 19

Articles