リソースを節約すると古いパソコンが使えるくらい速くなる話

どうも、インフラバカ一代(命名:弊社 常盤木)の津村です。ケーブルと人を繋ぎ続けて早23年。はやいものです・・・。(注:これでもまだ35歳です!!!)

さて、「まくはりちほー」ではInterop 2017なんて開催されているのですが、自分が仕事では2004あたりから関わっていて、公私ともに色々お世話になっています。13年だと、もうインターネット老人でいいんじゃないかとw
というわけで、今日は「あきばちほー」に居ることもあり、老人なお話でもしたいと思います。うん、おっさんって言っていいよ!!(認!!!)

初めて買ったパソコンには、メモリが640KBしか無かった

1993年(当時12歳)、あまりにパソコンが大好きで家電店の店頭展示のパソコンでBASICとMS-DOSを覚えてしまい、親が呆れたのかどうか知りませんが、結果として自腹で中古のパソコンを10万円も出して買いました。当時のスペックを観てみましょう。


Intel i80286(16bit 1core) 10MHz
メインメモリ 640KB(最大8.6MB)
ハードディスク なし
フロッピードライブ 1.25MB 5インチ フロッピードライブ 2機
OS MS-DOS 3.3D(NEC版・別売)
画面 640×400 4096色中16色 2画面

まだ「ぴーぽー!…640KB OK」で起動していた時代ですね。なつかし。

当時インターネットなど、まだ大学の研究室くらいでしか使えなかったので(しかも学術系と商用系で分かれてた!)、GUIの実装が進んでいたMacかPC-UNIXあたりを使って繋いでたものです。

▲当時の「ホームページ」は、タイトルかバナー画像くらいしか画像を使わず、ほとんど文字ばかりだった。
もう少しすると「掲示板CGI」や「アクセスカウンタCGI」とか出てきて、「キリ番の方はこちら」とか出てくる(懐

メモリは極力空けるもの

さて、NEC PC-98シリーズには「640KB」の壁というものがあります。これはCPU「Intel 8086」の仕様に関係しており、同時にアクセス出来るIO番地が1MB分しかなく、そのうちメインメモリに割り当てられた領域が640KBである為です。(この1MBの中には、通称BIOSと呼ばれるプログラムや、BASIC言語、各種IOが含まれている)しかし、OSを起動した次(具体的にはMS-DOSカーネルが起動し、CONFIG.SYSという定義ファイルを読み込むタイミング)で「デバイスドライバー」をメインメモリに展開します。この概念はWindowsにも通じますが、拡張機器を制御する為のプログラムを「デバイスドライバー」と言い、OSとデバイスの間を仲介するものです。しかし、デバイスドライバーをメインメモリに展開し過ぎると、今度は実際に実行したいプログラムに十分な容量のメモリを明け渡すことが出来ず、メモリの確保に失敗して暴走する事も多々ありました。

現代のWindows 10では各アプリケーションは内部的にコンテナとして展開され、ハードウェア間やアプリケーション間の直接通信が出来なくなっています。よって、仮にアプリケーションがクラッシュした場合、Kernelはコンテナを破棄し他のアプリケーションやOS自身に影響が無いように対処します。

幸い、当時はハードディスクがまだ普及しておらず、1フロッピー=1環境として構築をする事が出来た為(牧歌的に良い時代だった)、例えばゲームのフロッピーの場合、日本語に関する余計なドライバーをロードしなくても良く、楽だったものです。
(追記:フロッピーディスクは消耗品である為クラッシュする事も多く、その場合「データエラー」と表示され涙を呑む事も多かったものです。当時2HDのフロッピーディスクが1,000円程しました。)

しかし、「一太郎(今でいうWord)」「ロータス 1-2-3(今でいうExcel)」といった大きなアプリケーションでは、高機能なアプリケーションの他、FEP(Front End Processor、日本語変換エンジン、今でいうIME)をロードし、辞書を読み書き出来るようにしなければいけません。当時は文字入力や変換しようとするたびに「ガコガコガッコンガッコンガコガコガコッ」とフロッピードライブが鳴ったものです。(遠い思い出)
さて、これでは仕事が遅くなるので、メモリ上に辞書をロードする事を考えるわけですが、メモリは僅か640KBしか無く、皆泣く泣くメモリ拡張を行うのでした。

メモリを増設したら、メモリのドライバーを入れる

メモリを増設すると、次は増設したメモリにアクセスする為のドライバーをインストールします。これはi386以降の仮想86モードにおける「HIMEM.SYS」や「EMM386.SYS」といった名前で呼ばれており、8086ではアクセスできない領域のメモリにアクセスする為のドライバーを指します。
また、その昔には「バンク切り替え」という技術も用いられており、具体的にはメインメモリの一部に穴をあけ、拡張したメモリと順次中身を入れ替えて参照できる領域を疑似的に広げる処理をしています。
さて、この技術はPC-98に始まったものではなく、他のパソコンやファミコン、スーパーファミコン等でも使用されている技術です。ファミコン等の場合は「メモリマッパー」と呼ばれるチップをカセットの中に実装していました。
現代のエミュレーターの類は、このいくつかの種類があるメモリマッパーの物理チップをエミュレートする事で動いています。(エミュレーターはCPUや周辺チップだけではなく、カセットの中や拡張カードまでのエミュレートする場合があります。)

こんな老人の話を聴いて何の得があるか?

iPhoneのメインメモリは僅か2GB

さて、今の時代よく使われている「iPhone 7」、システムメモリは僅か2GBです。iPhone 7 Plusでも3GBです。よく「iPhoneがよく落ちる」という意見があります。しかし、iOSのバグは否定しませんが、おおよその場合ユーザーがアプリの起動のし過ぎや無茶な使い方をしたせいで落ちやすくなっている場合が多いようです。もちろんハードウェアの劣化も考えられますが、僕はiPhone 5Sを3年ほど使い続けていますがバッテリーを交換した以外はほぼノントラブルです。

BSD Kernelの気持ちになる

さて、じゃあiPhoneの気持ちになってみましょう。iOS Kernelの実態はFreeBSD ARM版のフォークです。現代ではNintendo SwitchやPS4といったプロダクトにもFreeBSDが採用されています。FreeBSD 4.11(i386)とか公私ともによく触っていたので覚えていますが、メモリの管理など含めとても厳しいOSです。(そのストイックさが大好きなのですが。)最近のLinuxの場合、あまり活発ではないプロセスのメモリ領域を自動的にswap領域に追い出して(=スワップアウトして)メインメモリの容量を確保するのですが、昔はあまりムチャをするとsshdが落ちるなどして、電源を落とす以外のリセット方法が無くなる場合も多々ありました。

C言語の原理原則論

また、Cで開発した事のある方ならわからなければいけない事ですが、malloc関数でメモリを要求して取得した場合、かならずfreeで開放してあげなければいけません。これに変数1個でも漏れがあると通称「メモリリーク」となり、プロセスが終了してもメモリが解放されない現象が発生し、結果としてOSのフリーズを招きます。
さて、時代はObjective-CやVisual C++といった言語へ進化しつつありますが、それ以外の言語やIDEもKernelもDriverも殆どはC言語ベースで書かれており、この基本原則は揺らいでおりません。コンテナ化や仮想化によりメモリの扱い方が変わったのは、まだここ数年の事でしょう。
具体例として挙げられるのが、あるPHPの開発エンジニアが「自分はC言語のエンジニアでPHPを開発しているから、PHPでの開発はわからない」と発言した事を聞き及んでいます。

Windowsアプリケーションの実体

さて、現代のWindows の話に戻しましょう。今のWindows 10は、Win32APIといったOSのAPIや、DirectXといったAPIをコールするバイナリの事をアプリケーションと言います。具体的にはWindows Kernelがプロセスを作り、そこにアプリケーションをロードし、CPUリソースやメモリリソースを随時割り当て、アプリケーションからのAPI要求を処理する事で出来ています。
実はWin16APIの頃(=Windows 3.1の頃)はメモリの絶対番地指定による読み書きが出来ていたのですが、WIN32API(=Windows95の頃)から相対番地指定に変わりました。これにより、他のアプリケーションのメモリを壊すような粗相が出来なくなりました。
また、ラグナロクオンラインの初期ユーザーなら記憶にあるかもしれませんが、チートツール「自動芋」などもこのメモリのコントロールによります。これは特定プロセスのメモリ領域のオフセット(特定の相対位置)にどのパラメータが入っているかを解析し、それによりプロセス外部からHP値を確認し、HP値が一定以下になった場合に「芋の使用」をする命令を実行する仕組みです。

じゃあどうしたらWindows 10は軽くなるのか

あー、やっと本題に入れたw

津村はロースペックPCで仕事している

さて、僕が今使っているPCは、DELL Venue 8 Proという、Windows8時代の32bitタブレットです。Windows 10を入れてカスタマイズして使用しています。詳細は以下のエントリをみてね。
http://blog.mikalab.info/archives/16172332.html

32bit QuadCore メモリ2GB。「こんなPCで仕事になるの?」という人は多いでしょう。しかし、このパソコンを買ったことで、重たいThinkPadを持ちあることはなくなり、むしろ仕事が捗るようになりました。

しかし、このマシンは長いバッテリー駆動時間を優先する為、CPUクロックはアイドル時500MHz程度までダウンクロックされます。よって、いかに無駄な処理を実行しないかに重点を置いてチューニングする必要があります。

余計なスタートアップアプリケーションは1つでも切る

まず、タスクマネージャからスタートアップアプリケーションを無効化します。具体的にはIntel Graphic Adapterのユーティリティや、DELLの診断ユーティリティなどを無効化しています。

画面描画のエフィクト(アニメーション)を無効化する

「その他オプション→Windowsでアニメーションを再生する」を無効化します。Explorerによる余計なAPIコールそのものを減らします。

アプリケーションを節約する

ブラウザのタブは開き過ぎないようにします。Google Chrome時代はボコボコとタブを開いて大量にメモリを消費していましたが、このマシンでは無理です。多くても4枚までしかタブを開く事ができません。
また、アプリケーションは同時に3つまでしか実行しません。例えば「Word+Visual Studio Code+Edge」程度に抑えます。OneNoteを開かなければいけない時は、Edgeを落とすなどします。
これにより、マシンのリソースを空けると同時に、忘却の彼方に葬られたタブやプロセスを貯める必要がなくなります。

通知はOSに任せる

これは新しい概念かもしれませんが、メールやSlack、Facebook、TwitterといったアカウントはOS側に設定し、ウィンドウやアプリケーションは起動していません。必要時に起動するか、iPhoneで返事をする(実はこっちの方が早い)等して、マシンのリソースを消費しないようにしています。

OneDriveの初期同期は、事前にファイルをコピーしてから差分同期させる

実は初期セットアップで一番ハマったポイントはここです。数千ファイルを初期同期で転送させる場合に、OneDriveは帯域制御ができますが、同時並行プロセス数の制御はできない為、結果としてメモリが溢れる事となりました。残念ながらOneDriveはまだDropboxのようにクライアントアプリが発達していない部分があります。
(尚、Dropboxはブロードキャストパケットでネットワークを汚す代わりに、同一のファイルを持っているクライアントが同一セグメントにある場合、Peer-to-Peerでファイルを転送しようとします。)
この代替えとして、同期しようとするファイルを予めSDカードでメインマシンからコピーし、差分転送(=ファイルのハッシュ値の確認)のみにする事で、無事に初期同期を終える事ができました。

さいごに-万物のリソースは無限ではない

インターネットとパブリッククラウドが発達した事により、従来のコンピュータの物理法則「手元のコンピューティングリソースしか使うことが出来ない」は崩壊してしまいました。
しかし、パブリッククラウドとて有限ではなく、次は資金リソースや帯域リソースが侵されていき、いずれリソースの限界を迎えます。
さて、ここで初めてチューニングという概念にようやくなるのですが、チューニングとは「よりリソースに最適化したアプリケーションや環境を用意する事により、より省リソースで物事を達成する事」です。
最初に戻ると、いかに速く静かにヒトの命令を処理して反映するか、がPC-9801に求められ、その為にメモリを増設しチューニングを施す事で、おおよその場合はクリアしていたと思います。
この概念は今のWindows 10やパブリッククラウドでも変わることはありません。

具体例

さて、具体例を最後に挙げておきましょう。
ログデータ、バイナリデータ、何でもよいのですが、ここでは約1TBのMySQLのダンプデータとします。これを1Gbpsの回線を用いて別マシンに転送する場合、以下のどちらのコマンドを用いればよいでしょうか。
※OSやデータベースの設定は無視します

Example1# mysqldump contoso | gzip | ssh tsumura@example.nikujaga.info “cat - | tee /tmp/contoso.sql.gz | gzip -d | mysql contoso”


Example2# mysqldump contoso | mysql -u tsumura -p -h example.nikujaga.info contoso

おわりに

本稿は2017.06.16に更新をしました。主に仮想86モードについて追記をしています。
そういえば「リアルモード」とか「プロテクトモード」とか、久方ぶりに聞いて思い出すのに時間がかかりました…。
Okazakiさん、ご指摘頂きありがとうございました。(赤面

avatar

About 津村 彰

PCインストラクターに始まり、エンジニア職17年目。「エンジニアたるもの、リソースに甘えず」がモットー。好きなアーキテクチャはx86とsparc64。外身は軟派、中身は超硬派がお好みの焼き加減。