Isis 是 Task Tracer GUI 的名字。
它會從特定的 log 格式產生如上的圖示:以 event type 來顯示 task 被執行的順序。

Thread Scheduler

為了測試這個工具,我另外做了簡易版的 Thread Scheduler 去模擬以下情境:

  • 模擬系統開機後會建立數個不同的 Thread,各自有名字:'UI', 'worker', 'BT', 'NFC', 'Telephony', 'Main', 'IO'
  • 事先亂數產生一些由任意數量 Task 組成的任務
  • 單一 Task 會屬於某個特定 Thread
  • 單一 Task 在產生時的執行時間已經決定了
  • 單一 Thread 同時間只能執行一個 Task,其他的請求會進入 pool 內等待正在忙碌的 Task 完成。

用 Javascript 來模擬這些事情並不難:

  • 設計 Task 類別
  • 設計 Thread 類別
  • 設計 Mission 類別用以產生並記錄一連串的 Task
  • 使用 Factory Pattern 創造 Thread
  • 使用 Manager Pattern 管理 Thread
  • 定義數個 Mission
  • Thread 用 setTimeout 來管理 Task
  • Task 用 Date.now() 來記錄狀態改變的時間

在寫這個的時候讓我想起作業系統課寫過的 Page Allocator,
如果再加入 Memory 狀態的話搞不好還可以順便模擬 Context Switch。

時光機器

回到正題,我的目標是想要很快的產生出一整組完整的測試資料,
但是 setTimeout 很明顯會無法達成這件事。

想到的解決方式是利用 sinonjs 的 fake timer 來 hack setTimeout 以及 Date

  var TimeMachine = {
    init: function() {
      this.start = Date.now();
    },
    startSimulation: function(done) {
      var clock = sinon.useFakeTimers(0, 'setTimeout', 'clearTimeout',
                                      'setInterval', 'clearInterval', 'Date');
      for (var i = 0; i < randomCount(10) + 1; i++) {
        var mission = new Mission();
      }

      clock.tick(1000000000);

      clock.restore();
      if (typeof(done) == 'function') {
        setTimeout(done);
      }
    },
    now: function() {
      return (Date.now());
    }
  };

時光機器果然一下子就讓需要等 1000000000ms 的程序結果出現了。

我沒有仔細看裡面的實作,不過我想是我的話:

  1. 替換 window.setTimeout 變成一個自己的函示,並在內部紀錄所有 callback。
  2. 替換 window.Date 變成自己的物件
  3. 實作 tick:用迴圈去更新 Date.now() 並且在該呼叫 callback 的時候呼叫。

Comments

comments powered by Disqus