スポンサーリンク

Linux上で,巨大なサイズのダミーファイルを作成する方法


Linux上で,巨大なサイズのダミーファイルが欲しい場合がある。

例えば,圧縮ソフトの圧縮率を比較したい場合など。


この場合,ダミーファイルの性質として,下記の点が求められる。

  • 内容が,極端に「均質」過ぎてはいけない。(圧縮結果が小さくなりすぎるから)
  • 内容が,極端に「ランダム」過ぎてはいけない。(圧縮結果が大きくなりすぎるから)


ここでは,以下の3つの方法を検討し,それぞれ生成処理に要した時間も記録する。

  1. ランダムな内容の巨大データを,データベース上に作成
  2. ランダムな内容の巨大ファイルを,ファイルシステム上に作成
  3. 均質な内容の巨大ファイルを,ファイルシステム上に作成

(1)ランダムな内容の巨大データを,データベース上に作成

データベース(PostgreSQL)内に,巨大データを登録する。

そこでpg_dumpすれば,指定したサイズ(を上回るサイズ)の巨大なファイルが得られる。


ストアドファンクションを使えば,forループ内でINSERT文を繰り返し発行できて楽だ。

下記のSQLを実行。

-- 10000件のダミーレコードを登録する
CREATE OR REPLACE FUNCTION create_big_data() RETURNS bool
AS $$
  DECLARE
    char_random char(1);
    str_value   varchar(10);
    str_sql     varchar(200);
  BEGIN
    -- INSERT文を繰り返し発行
    FOR i IN 1..10000 LOOP
      -- 10バイトのデータを作成
      str_value = '';
      FOR j IN 1..10 LOOP
        -- ランダムな1文字の数字を取得
        SELECT
          ceiling( random() * 10 ) - 1
        INTO
          char_random
        ;
        -- 結合
        str_value = str_value || char_random;
      END LOOP;
      
      -- SQL文を作成
      str_sql = 'INSERT INTO hoge_table( fuga_column ) VALUES ('
        || '''' || str_value || ''''
        || ');'
      ;
      
      -- SQLを実行
      EXECUTE str_sql;
    END LOOP;
    
    RETURN true;
  END;
$$ LANGUAGE plpgsql
;

-- 実行する
SELECT create_big_data();

これで,10バイトのレコードが10000件作成される。

計100kBと見て,実行に2秒ほどかかった。

これでpg_dumpすれば,「内容が均質でない巨大データ」をファイルとして取得できる。


なお,PL/pgSQLの導入方法と基礎文法は下記を参照。

PREPARE文と,PL/pgSQL の入門  (PostgreSQLで「動的に」SQLを実行するために,プリペアド・クエリやストアドファンクションを定義しよう)
http://language-and-engineering.hatenablog.jp/entry/20110218/p1

(2)ランダムな内容の巨大ファイルを,ファイルシステム上に作成

直接,ファイルとして巨大なデータを書き込む。


hoge.sh

#!/bin/sh

target_dir="/tmp"
target_file="${target_dir}/big_data"

# 初期化
rm -f ${target_file}
touch ${target_file}


# 書き込み
echo "started at $(date)"
for ((i=0; i<10000; i++))
do
  # 10バイト分
  printf "%05d" ${RANDOM} >> ${target_file}
  printf "%05d" ${RANDOM} >> ${target_file}
done
echo "end at $(date)"

# 終了
ls -l ${target_dir}


100kBで2秒かかった。

速度は,DB上に登録するのと大差ない。



補足:

  • bashのfor文の記述方法として,「算術演算forループ」を利用している。
  • ランダムな数字の並びを5バイト分確保するために,printfで乱数を0埋めしてフォーマットをそろえている。

なお,成果物がASCIIテキストでなくてもよいのであれば,ランダムなバイナリを生成するために下記のコマンドを実行できる。

-- 1GBのランダムなバイナリを作成
head -c 1000m /dev/urandom > /tmp/big_data

/dev/urandomは,ランダムなビット列を比較的高速に生成するデバイスファイル。

これだと,1GBのファイル生成に5分かかる。


こいつをgzipすると,逆にファイルサイズが大きくなる。

最初から最後まで,ビット単位で機械的なランダム性を持っているため,圧縮のしようがないのだ。

なので,この方法は,gzipに渡すためのテストファイルとしては利用できない。

中身がランダムなファイルを任意のサイズで作成する
http://kazmax.zpp.jp/linux/random_fil...


/dev/random と /dev/urandom の違い
http://kaworu.jpn.org/kaworu/2010-11-...

(3)均質な内容の巨大ファイルを,ファイルシステム上に作成

前述の方法は,いずれも「ファイルの内容が均質でないようにする」という制限があった。

その制限がなければ,巨大なファイルを作るのは楽。

ddコマンドを使う。

# 1GBのファイルを作成
dd if=/dev/zero of=/tmp/big_data bs=1M count=1024

1GBのダミーファイルを作成するのに20秒かかった。前述の方法よりずっと速い。

容量指定のダミーファイルを作成したい
http://www.itmedia.co.jp/help/tips/li...


なお,ファイルの内容が均質なので,gzipで圧縮すると1メガになってしまう。