gnote on QEMUを速くしよう

  • どう遅いか?
    • キーを入力しても描画が追いついていないように見える
  • どこで遅いか?を見極める必要がある。
  • 例えば aaaaと入力したときにどのような挙動だろうか?
    • a を入力後、0.3-0.5秒後くらいに a が出力される
  • さて問題をどう切り分けよう
    • 考えられる原因と検証方法を考えてみよう。
  • 原因と検証方法
    • (1)GUIサーバーでaという文字の描画が遅い
    • (2)QEMUは描画が遅いのでこれが限界である
    • (3)aというキー入力→(イベント処理)→a出力指令が出る。イベント処理のどこかが遅い
      • A.カーネルが遅い
      • B.BayGUIが遅い
      • C.gnoteが遅い
  • (2)を検証する。これは結構簡単でCUIとgnote上で a という文字の描画速度を同じQEMU上で比較すれば良い
    • [結果]CUIでは十分に速いので(2)は誤りである
  • (1)を検証する。同じくGUIサーバーを使用している、MonaFormsのGUI Shellと比べれば良い。
    • [結果]MonaFormsのGUI Shellは十分速いので(1)は誤りである
  • (3-A)は(1)(2)の検証で否定される
  • (3-B)(3-C)の検証には、「キーが押下されてから画面に表示されるまでに何が起きているか?」を知ることが必要である。
    • 「キー押下→画面に表示」のフロー
      • [gnote] void Controller::ProcessEvent(Event* event)
      • [gnote] void Controller::ProcessKeyPressedEvent(KeyEvent* event)
      • [gnote] document.Insert(code, cursol.wy, cursol.wx)
      • [gnote] GoRight(cursol, document);
      • [gnote] window.GetCanvas()->repaint();
      • [baygui] Frame::repain()
      • [baygui] Container::repaint()
      • [baygui] paint()をcall
      • [baygui] Window::update()をcall
      • [baygui] Message::SendでGUIサーバーに再描画を指示
    • 上記のフローの各所でrtdscをはさむのはどうか?
    • せっかくなのでAPI monapi_rdtscを追加した。
    • マクロも追加
      • #define LOG_RDTSC {dword h, l; monapi_rdtsc(&l, &h); logprintf("%x:%x : %s %s:%d\n", h, l, __func__, __FILE__, __LINE__);}
  • 結果は
    • 3:e930f965 : ProcessEvent controller.cpp:57
    • 3:e9363511 : ProcessKeyPressedEvent controller.cpp:199 53BAB
    • 3:e93bdbe8 : Insert document.cpp:129 5A6D7
    • 3:e942a1c6 : GoRight controller.cpp:342 6C5DE
    • 3:f87ff1df : WindowHandler window.cpp:405 F3D5019
    • 3:fa653232 : WindowHandler window.cpp:412 1E54053
    • 4:9b0026d : WindowHandler window.cpp:405 F4AD03B
    • 4:ba3abe4 : WindowHandler window.cpp:412 1F3A977

今日はここまで。
おまけ。

void monapi_rdtsc(dword* timeL, dword* timeH)
{
    dword l,h;
    asm volatile("rdtsc           \n"
                 "mov   %%eax, %0 \n"
                 "mov   %%edx, %1 \n"
                 : "=m"(l), "=m"(h)
                 : /* no */
                 : "eax", "edx");
    *timeL = l;
    *timeH = h;
}