2014年7月20日日曜日

Chromeの不具合?とWindowsの仕組み

最近、Google ChromeがノートPCのバッテリを過剰消費しているという不具合が話題に上がっていました。

これはFirefoxやInternet Explorerでは起きない不具合となっているのですが、Windowsの仕組みの問題でもあるので、改善されるに越したことはないですが、Chromeを責めるのも少し可哀想な気がします。

OSの仕組み


WindowsなどのOSでは、起動している状態でもかなり多数のアプリケーション(プロセス)が起動しています。それに比べてCPUは多くても8つなど数が少なく、1つの場合もあります。よって、少ないCPUで複数のアプリケーションを切り替えながら実行する必要があります。

OSの中でその切り替えの役割を担っているプログラムをスケジューラと言います。このスケジューラは定期的に実行され、どのアプリケーションがCPUを必要としているかを判断し、実行するアプリケーションをCPUに割り当てます。

このスケジューラを定期的に実行する間隔が、記事に書かれている「システムティックレート」と言われているもので、割り込みコントローラと言うものが、CPUに定期的に実行するように指令しています。

Windowsの場合


Windowsの場合はスケジューラの実行間隔が15msと言うことです。ちなみに最近はあまり見かけないですが、1CPUのパソコンの場合には10msとなっています。

この15msと言う数字は一秒間に約67回スケジューラが動いていると言うことになり、人間から見ると、アプリケーションの切り替えが分からず、同時に複数のアプリケーションが動いているようにみえるわけです。

しかし、15msが速いかというと、コンピュータの世界では非常に遅く(例えば、CPUの1命令が1クロックで行われるとすると、1GHzのCPUでも1命令は0.000001msで完了する)、処理によっては、この間隔で切り替えられても困ることになります。特に動画や音楽関連などリアルタイムな処理をしたい場合は致命的です。

そこで、WindowsではtimeBeginPeriod()というマルチメディア用Win32APIによって「システムティックレート」を切り替えできるようになっています。以下のソースコードのように使い方は非常に簡単です(ビルド時にはwinmm.libをリンクしてください) 。


#include <windows.h>
#include <mmsystem.h>

int WINAPI WinMain(HINSTANCE hInstance,
                HINSTANCE hPrevInstance,
                LPSTR lpCmdLine,
                int nCmdShow)
{
        timeBeginPeriod(1);
        MessageBox(0, "ok end", "sysmtem tick test", MB_OK);
        return 0;
}


ダイアログが表示されますが、ここでOKを押してこのアプリケーションが終了するまで、「システムティックレート」が1msとなります。ちなみにWindows上に動いているアプリケーションの中でtimeBeginPeriod()に指定した値が一番低い値がシステムで使われることになります。

そして、以下のプログラムを上記のプログラムが実行している状態と実行していない状態で動作させてみてください。

#include <windows.h>

int main()
{
        int i;
        for (i = 0; i < 1000; i++) {
                Sleep(1);
        }
        return 0;
}


timeBeginPeriod(1)を実行している状態だと終了が速いはずです。Sleep(1)は少なくとも1msは別のアプリケーション(プロセス)の処理を行ってください、という指令です。しかし「システムティックレート」切り替え間隔が15msの場合には、アプリケーションの切り替えに15msかかってしまうためにSleep(1)は少なくとも15msの時間がかかるためです。

そしてあるCPUでSleep()指令を実行した後に、15ms経って他のアプリケーション切り替えするまでの間はというとCPUはどのアプリケーションも実行していない状態になり、非常に無駄な時間を使うことになります。

そのため頻繁なプロセスの切り替えを行うとパフォーマンスが大幅低下します。Google Chromeは昔から処理が速いことで評判でしたが、 単に消費電力よりパフォーマンスを取った結果と思っていました。

Internet Explorerはバージョン10の時に、消費電力が他のブラウザよりも低いとMicrosoftは宣伝していました。
この頃からChromeはtimeBeginPeriod(1)を使用しているはずですけど、それほどの差はありません。なぜ今ごろまた騒がれているのかが不思議です。もしかすると最近のCPUは省電力機能が発達してきているので、15msの間に積極的に休むようになってきたのかもしれません。

しかし、1つのアプリケーションの timeBeginPeriod(1)の1つの命令でシステム全体に影響を与えるWindowsの仕組みも少々怖い気がします。少なくとも短い間隔のSleep()でタイミングを合わすようなプログラムは書かない方がいいでしょう。

Linuxの場合


Linuxの場合は、tickless(ティックがない)と呼ばれる仕組みが2.6.21から使われています。Windowsのように15msというような一定の期間を設けず、動的に変更するようになっているので、dynaticks(dynamic ticks) (動的なティック)と呼ばれることもあります。

その動的な値を知るためにはPowerTopというソフトで得られます(sudo yum install powertop でインストール)。Fedora 20で確認したところ、色々な普通に使っている状態で一秒間に約800の割り込みが起きています。これを計算すると1.4msぐらいのティックになるので、Linuxは結構消費電力を使っているということになってしまうかもしれません。LinuxではChromeの不具合は起きないと言っても、消費電力を使うのであれば意味がない気がします。ただChrome自体の割り込みは全部合わせても100回/秒程度のようです。

それと、Fedora20ではLinux3.10から導入された完全なticklessであるFull ticklessが使用されていません。確認するには/boot/config-3.13-3-201.fc20.x86_64などのconfigファイルを見ると分かりますが、CONFIG_NO_HZ_FULLが設定されていません。これが使用されると更に消費電力がよくなるかもしれませんが、このティックの辺りはOSの基本の部分であり、少しでも割り込みを減らすのには課題が多そうです。

Mac OS Xも資料が少ないので詳細は判りませんが、ticklessのようです。

0 件のコメント:

コメントを投稿