0

と言われている

JavaScript の数値はすべて 64 ビット浮動小数点数です。

数値が常にメモリ内で 64 ビットを使用するかどうか疑問に思っていますか?

私はこのようなデータ構造を持っています(Cスタイルのコードで)

{
  int x; // [0-9]
  int y; // [0-9]
  int d; // [0-3]
}

x と y は絶対に [0-9] の範囲内にあり、d の唯一の可能な値は 0、1、2、3 です。

それらを 3 つの数字で区切って格納すると、構造体は 64 ビット * 3 = 192 ビット = 24 バイトを使用しますか?

もしそうなら、x * 100 + y * 10 + d という 1 つの数値に格納したいと思います。これは 64 ビット (8 バイト) のみを使用する必要があります。CPU使用率を考慮しない方が良いですか?

また、文字列ソリューションについても検討しました。

x.toString() + y.toString() + d.toString();

x、y、d はすべて 10 未満であるため、1 文字、16 ビットである必要があります。したがって、構造は 16 ビット * 3 = 48 ビット = 6 バイトになります。これは最もストレージに最適化されたソリューションですか?

mongoDB のストレージはどうですか? データ構造を mongoDB に格納すると、同じ状況になりますか?


mongo でストレージをテストするためのスニペットを作成しました。最終的な構造には、上記の構造の 3 つのインスタンスが含まれます。合計金額は 66816 です。

それらを3つの別々のデータベースに保存しました:

  • layout-full ('s' を失いました): 配列には 3 つの {x: valueX, y: valueY, d: valueD} が含まれます
  • layouts-int: xydxydxyd (10 進数) ex. 233250750 は {x:2,y:3,d:3},{x:2,y:5,d:0},{x:7,y:5,d:0} を意味します
  • layouts-str: 上記の int を 2 文字の文字列に変換します。文字列.fromCharCode(i >> 16) + 文字列.fromCharCode(i & 0xFFFF)

そして結果は…

> show dbs
layout-full     0.03125GB
layouts-int     0.03125GB
layouts-str     0.03125GB

しかし、詳細は...

レイアウトフルのコレクション

"size" : 8017920,
"avgObjSize" : 120,
"storageSize" : 11182080,

layouts-int のコレクション

"size" : 2138112,
"avgObjSize" : 32,
"storageSize" : 5591040,

layouts-str のコレクション

"size" : 2405396,
"avgObjSize" : 36.000299329501914,
"storageSize" : 5591040,

これらの結果から、int ストレージが最も省スペースな方法であることがわかりました。

私もこれをしました:

> db.tiny.save({})
> db.tiny.stats().avgObjSize
24
> db.tiny.remove()
> db.tiny.save({l:null})
> db.tiny.stats().avgObjSize
28
> db.tiny.remove()
> db.tiny.save({l:[{x:null,y:null,d:null},{x:null,y:null,d:null},{x:null,y:null,d:null}]})
> db.tiny.stats().avgObjSize
84

したがって、_idは 24 バイトを使用し、キー部分 は{l:4 = 28 - 24 バイトを使用します。

また、整数は 32 - 28 = 4 バイトを使用することがわかります。したがって、2^31 未満の整数は mongo db に 32 ビット整数として格納されるようです。

また、文字列内のソリューションでは、2 文字の文字列は 36 - 28 = 8 バイトを使用し、私が推測した値とちょうど同じです。

また、完全な構造のソリューションでは、最後の tiny db テストから、データのない構造は 84 バイトを使用することがわかります。したがって、データは 120 - 84 = 36 バイト = 9 * 4 バイトを使用します。そして、最終的なデータ構造 (トリプル x、y、d) には 9 つの整数しかありません。これは、整数が 32 ビット整数として格納されていることも証明しています。

そして、空の構造体が 84 バイトを使用するのはなぜですか?

さらにいくつかの実験を通じて、1 つの配列または空の json オブジェクトが 4 バイトを使用し、キーが * 4 を使用することがわかりました。

したがって、空の構造は実際には

{                                               // 1 object +4 bytes       = 4
  '_id': ObjectId('0123456789abcdef012345678'), // 3-char key + 12-byte id = 24
  'l': [                                        // 1-char key + 1 array    = 8
    {'x': null, 'y': null, 'd': null},          // 1 object+ 3 keys        = 16
    {'x': null, 'y': null, 'd': null},          // 1 object+ 3 keys        = 16
    {'x': null, 'y': null, 'd': null}           // 1 object+ 3 keys        = 16
  ]
}

結果は 4 + 24 + 8 + 16 * 3 = 84 バイトです。

私の実験が他の人に役立つことを願っています。

4

1 に答える 1

1

これにより、3 つの数値が 1 文字の文字列に格納されます。これを改善する唯一の方法は、型付き配列を使用することですが、それがここでのオプションかどうかはわかりません。

function showMeSomeMagic(x, y, d) {
  // we assume that:
  // - x, y are integers in the range [0 9] 
  // - d is an integer in the range [0 3]
  // if not add the appropriate checks/casting/coercing
  var n = (d << 8) + (y << 4) + x;
  // return a String made of a single Unicode code point in 
  // the range [0xE000 0xE399], i.e. inside the Unicode BMP PUA
  return String.fromCharCode( n + 0xE000 );
}

function showMeSomeInverseMagic(s) {
  // we assume that:
  // s is a String created by showMeSomeMagic
  var n = s.charCodeAt(0) - 0xE000;
  var x = n & 15;
  var y = (n >> 4) & 15;
  var d = (n >> 8) & 15;
  return { x:x, y:y, d:d };
}

編集:OPコメントに従って更新

于 2012-05-18T08:15:12.693 に答える