ホーム 主筆 その他ソフト その他情報 Syuhitu.org English

Windows関連

スクリーンセーバー作成法

半透明ウインドウの性能

bootfont.bin

キャビネット形式

ウインドウスタイルをいじる

Java製ソフトをServiceに登録する

イベントログにメッセージを出力する

コントロールパネルにアイコンを追加する

スクリプトによる拡張1

スクリプトによる拡張2

ガジェットの作成

大容量メモリ

メモリ搭載量の下限に挑む

スパースファイルにする

表示されるアイコンの種類を調べてみた

メモリマップIOとエラー処理

ファイルを作る順番と速度の関係

Cryptography API: Next Generationを使う

Windows 10のアクセントカラー

iSCSIディスクにバックアップを取る

サーバプロセスを分離して実装する

サーバプロセスを分離して実装する - F#

レジストリに大量に書き込む

Solaris関連

OpenGL

Solaris設定

ディレクトリの読み込み

主筆プラグイン開発

マルチスレッドでの開発

door

音を出す

Blade100の正しい虐め方

パッケージの作成

画像入出力

BMPファイル

ICOファイル

ANIファイル

JPEGファイル

減色アルゴリズム

減色アルゴリズムの並列化

その他アルゴリズムなど

自由軸回転

Base64

文字列操作

CPU利用率の取得

正規表現ライブラリ

メタボールを作る

メタボールを作る2

正規表現とNFA・DFA

C言語の構文解析

液晶ディスプレイを解体してみた

iSCSIの理論と実装

単一フォルダにファイルを沢山作る

USB-HUBのカスケード接続

SafeIntの性能

VHDファイルのフォーマット

USBメモリに書き込み続けてみた

大容量メモリ

2011年5月7日公開

x86の32bitのアーキテクチャでは、メモリは最大4GBまでしか使えないと言われる。

また、mallocに失敗する例として、下記のようなプログラムを見かける。

void* p = malloc( 0xFFFFFFFF );
if ( NULL == p ) {
    printf( "メモリの確保に失敗しました。\n" );
}

まぁ確かに、問答無用で4GBのメモリ領域を要求すれば失敗するのも無理ないような気がしないでもない。

だがしかし、俺のマシンには物理的に12GBのメモリが搭載されている。ということは、4GB程度であれば余裕で割り当てられるのではないか?

ということで、ちょっとやってみた。

テスト用のプログラム

わかりやすいように、メモリの確保だけを行うテスト用のプログラムを作ってみた。

画面には、確保されるメモリ領域長を入力するエディットボックスとボタンを配置しておく。

OKをボタンを押下すると、メモリの確保を行い結果を表示する。

プログラムはこうなっている。

void CMemoryTestDlg::OnBnClickedButton1()
{
  unsigned int i = 0;
  unsigned int j = 0;
  unsigned int k = 0;
  unsigned int allocsize = 0;
  CEdit* p = (CEdit*)GetDlgItem( IDC_EDIT1 );
  CString str;
  size_t size2 = 0;

  // 既存のメモリ領域を開放する
  for (  i = 0; i < vBuffer.size(); i++ ) {
    free( vBuffer[i] );
    vBuffer[i] = NULL;
  }

  // 入力されたメモリ領域長を取得する
  p->GetWindowTextW( str );
  size2 = _ttoi( str );

  // 512MB単位で確保する個数と余りを算出する
  j = size2 / 512;
  k = size2 - ( j * 512 );

  // 512MB単位でメモリ領域を確保する
  for ( i = 0; i < j; i++ ) {
    void *p = malloc( 512 * 1024 * 1024 );
    if ( NULL == p )
      break;
    for ( l = 0; l < k * 1024 * 1024; l++ )
      ( (char*)p )[l] = 0;
    vBuffer.push_back( p );
    allocsize += 512;
  }

  // 余りの分を確保する
  if ( k > 0 ) {
    void *p = malloc( k * 1024 * 1024 );
    if ( NULL != p ) {
      for ( l = 0; l < k * 1024 * 1024; l++ )
        ( (char*)p )[l] = 0;
      vBuffer.push_back( p );
      allocsize += k;
    }
  }

  // 結果を表示しておく
  str.Format(
    _T( "要求されたサイズ:%u\n確保したサイズ:%u" ),
    size2, allocsize
  );
  MessageBox( str );
}

処理内容としてはコメントに記載しているとおり、512MB単位でmallocを行い、最後に余りの分を確保して、結果を表示するというだけである。

たとえば、エディットボックスに「1025」と入力したのであれば、512MBのmallocを2回と、1MBのmallocを1回行うことになる。

64bit版Windows7での動作

動作確認を兼ねて、64bit版Windows7で動かしてみた。

まずは32bit用にコンパイルした場合。

1456MBまでは正しく領域を確保することができるらしい。

64bit用にコンパイルした場合。

たくさん確保できるようだ。

ついでに言うと、タスクマネージャのメモリ使用量の表示が大変なことになる。

限界に挑んでみた。

スラッシングが発生して酷いことになったが、32GBのメモリ領域の確保に成功してしまった。

今度は、32bit版のプロセスを多数起動してみる。

1プロセスあたりの最大は1.4GB程度だが、そのプロセスを多数起動することは可能なようだ。

例のごとく、タスクマネージャの画面は大変なことになっている。

64bitの環境

早速だが、64bitOSでの動作を確認してみた。

なお、動作環境は全てVirtualBoxであり、仮想OSに割り当てるメモリ容量は全て8192MBである。なおかつ、限界値がわかりにくくなるので仮想OSでのページング領域のサイズは0に設定している。

ただし、Windows 7とWindows Server 2008は仮想環境ではなくホストOSの値を記載している。なぜならば環境を作るのが面倒だったからだ。

バージョン バージョン番号 認識されたメモリサイズ 1プロセスの最大(32bit) 1プロセスの最大(64bit) 複数プロセスの最大
Windows XP Professional SP3 5.2.3790 8.0GB 1293MB 7344MB 7344MB
Windows Server 2003 R2 Enterprise Edition 5.2.3790 8.0GB 1293MB 7339MB 7339MB
Windows Vista Ultimate 6.0.6002 8.0GB 1750MB 7060MB 7060MB
Windows Server 2008 R2 Standerd Edition 6.1.7600 8.0GB 1700MB 6244MB 6244MB
Windows 7 Professional(注1) 6.1.7600 12.0GB 1456MB 10456MB 10456MB

注1 Windows 7は12GBの物理メモリを搭載したマシンで動作した値を記載している。

なお、上記で述べたとおり、ページング領域を0より大きな値にすればその分メモリを使用することができる。複数プロセスで共用して使用することもできるし、1プロセスで目一杯まで使ってしまうこともできる。

32bitの環境

同じ要領で、32bitOSでの動作を確認してみた。

動作環境は同じくVirtualBoxであり、仮想OSには8192MBのメモリを割り当てて起動している。

バージョン バージョン番号 認識されたメモリサイズ 1プロセスの最大 複数プロセスでの最大
Windows 98(注1)(注2) 4.10.1998 1160MB 240MB 1029MB
Windows 2000 Professional SP4(注2) 5.00.2195 3.5GB 1499MB 3354MB
Windows XP Professional SP3 5.1.2600 3.5GB 893MB 3140MB
Windows Home Server SP2 5.2.3790 4.0GB 1293MB 3621MB
Windows Server 2003 SP2 Enterprise Edition 5.2.3790 8.0GB 1293MB 7682MB
Windows Vista Ultimate 6.0.6002 3.5GB 1657MB 2796MB
Windows 7 Ultimate 6.1.7600 3.5GB 1657MB 3028MB

注1 Windows 98は1160MB以上のメモリを割り当てると正常に起動できなくなる。

注2 Windows 2000およびWindows 98は、Visual Studio 2010のランタイムがインストールできないことから、上記のプログラムと同じ処理を行うものをVisual Studio 6.0で作り直している。

なお、認識されるメモリ領域が4GBないし3.5GBに制限されていたとしても、ページング領域を必要十分に確保してあげれば、それ以上のメモリ領域(仮想記憶領域)を使用することができる。もっともその場合は、本当は使うことができるはずのRAMが使用されることはなく、ディスクI/Oが多発することになるため性能が著しく劣化することになる。

たとえば下記は、Windows 2000でメモリを8192MB割り当てて起動し、なおかつ合計で4GB以上のメモリを使用してる時の画面である。

使えるRAM領域は3.5GBだが、7.5GB程度の仮想記憶領域が割り当てられていることが分かる。

/3GB指定

32bitOSで32bitのプロセスを実行する場合、使えるメモリの上限が2GBにすら届かないのは、OSが2GBのメモリ空間を使用しているためだという。いろいろと検索したら、こんなページが出てきた。

そのページの記載によれば、C:\BOOT.INIに/3GBという指定を追加してやって、なおかつ、実行ファイルにIMAGE_FILE_LARGE_ADDRESS_AWAREというフラグを設定してやれば、ユーザ領域として3GBまで使えるようになるらしい。

ということでやってみた。

まずは、c:\BOOT.INIを編集する。

折り返し表示になっているが、最後と最後から2番目の行は1行である。でもって、行末に「/3GB」という指定を追記してやった。

次は、実行プログラムの編集である。Microsoftの説明のページではeditbin.exeを使えと記載されていたが、そんなことおwしなくてもVisual Studio 2010ではリンク時の設定として「/LARGEADDRESSAWARE」が指定できるようになっている。

これで、再コンパイルしてやれば完了である。

その上でもう一度測定してみる。

バージョン 認識されたメモリサイズ 1プロセスの最大
Windows 2000 Professional SP4 3.5GB 1499MB
Windows XP Professional SP3 3.5GB 1535MB
Windows Server 2003 SP2 Enterprise Edition 8.0GB 2047MB

測定するにはしたが、正直言ってかなり酷いことになる。

「/3GB」のフラグをつけて再起動しただけで、OracleVMのディスプレイドライバが使えなくなり、640x480・16色表示になってしまう。それ以外にもいろいろなプロセスが正常に起動できず、ネットワークへのアクセスもだいぶ疑わしくなる。それでも一応、使えるメモリ領域がちょっとだけ増えた。

なお、Windows VistaとWindows 7はやり方がよく分からなかったし、調べるのも面倒になったからやっていない。


連絡先 - サイトマップ - 更新履歴
Copyright (C)  2000 - 2016 nabiki_t All Rights Reserved.