また戻ってきた
このシリーズの内容のリスト:
可変長型シフト
辞書圧縮方式
尾部切除
ウルトラパックと時空交換の原理
V8エンジン形而上学
この記事は「情報理論」シリーズ(奇妙な知識シリーズ)の最後の記事です。このシリーズの4つの記事はすべて次のとおりです。
「情報とエントロピー:生命は情報を養う」(情報理論の基礎)
「最適なバイナリツリーとハフマンコーディング」(1〜5章)
「シリアライゼーションの限界を探る」(6章から11章)
「ホスト、時間と空間の置換、V8形而上学」(12〜16章)(この記事)
12
—
可変長オフセット実数
文字列型はutf8のハフマンツリーを枝刈りして、すべての葉が独立したエンコーディングオブジェクトになるようにします。ある程度の時間は犠牲になりますが、minUTF8は情報理論で最適な文字エンコーディングになります。次に、実数型の圧縮方式を調べます。そうです、数値を圧縮してください!
誰かが尋ねました、実数型はどのように圧縮できますか?IEEEで定義された補数と浮動小数点10進数は、実数のストレージ要件を最大限に満たしており、ほぼ完璧です。より良いフォーマットを設計できますか?
私の圧縮のアイデアは、人々の使用習慣に基づいています。使用習慣に基づいて情報を圧縮することは信頼できないと以前に述べました(以前にTypedArrayを使用する習慣について述べました)が、そのようなものがあることは否定できません。この「使用の習慣」はより古く、変更されていません。つまり、小さい実数の発生頻度は、大きい実数の発生頻度より常に高いです。人々は常に0に近い正の数値を測定に使用することを好みます。たとえば、ケルビンの代わりに摂氏が使用されます。数億と数兆の数値が表示されることはほとんどありません。すべての数値が64ビット浮動小数点である場合、それを証明する必要はないと私は信じています。ストレージは間違いなく無駄なので、mspは可変長の実数型を提供します。異なる範囲の実数は異なるバイト数を占有します。
しかし、可変長の実数は原則2に違反します。
可変長の正の整数を例にとります。図で異なる長さの正の整数は、元のバイナリコードの形式で格納されます。8ビットと16ビットの2つの範囲では、[00000000]と[00000000 00000000]はどちらも実数0を表します。同じであるが異なるバイト文字列は、原則2に違反します。
の解き方?
最良の方法は、可変長実数を可変長オフセット実数にアップグレードすることです。各長さの最下位ビットは、前の長さの最上位ビットに続きます。たとえば、図に示すように、各実数は、このカテゴリのオフセット値を実際の値になるように追加する必要があります。
8ビット整数:MIN = 0、MAX = 2 ^ 8-1 = 255
16ビット整数:MIN = MAX [上] + 1 = 256、MAX = MIN + 2 ^ 16-1 = 65792
32ビット整数:MIN = MAX [上] + 1 = 65793、MAX = MIN + 2 ^ 32-1
13
—
辞書圧縮方式
さて、文字列と実数の新しい形式は直列化の理論的な限界に達していますが、それらはすべて基本的なデータ型であり、複合型である辞書の圧縮アルゴリズムに挑戦しています。
辞書が圧縮可能かどうかは、まず、前の2つの原則に違反しているかどうかによって異なります。mspでは、ディクショナリタイプは各キーと値のペアを[キー、値、キー、値...]の方法で格納し、各キーまたは値は基本タイプまたは複合タイプにすることができます。
クロスプラットフォームでは、ほとんどの場合、「キー」のタイプは文字列であるため、タイプフィールドを省略してスペースを節約できます。
要素は主に、タイプ、長さ、内容の3つの部分で構成されます。type + lengthはエンコーディングオブジェクトを構成し、lengthはコンテンツの長さです。
また、ほとんどの場合、キーと値のペアは順序付けされておらず、ハッシュテーブルのように順序付けはあまり意味がありません。ただし、jsonやmspのようなキーと値のペアを配置すると、常に順序どおりになります。この順序を使用しなくても、この順序の情報は常に存在します。情報=重要であり、情報はスペースを占有します。辞書を削除する方法オーダー?
解決策は、キーと値のペアを強制的にソートすることです。
ソートキーコードバイトに従って、つまり、文字列を大きな整数として、次に小さなものから大きなものへ。エンコードするとき、各キーの位置はキー自体を格納するのではなく、以前のキーの「増分」を格納します。デコードするとき、各キーは増分を累積することによって取得されます。
このように、ソートされた辞書はまだ「順序付け」されていますが、キーの昇順は100%確実であり、他の可能性はなく、情報は不確実性(エントロピー)が除去されるため、「シーケンス」自体によって提供される情報の量は0であり、当然、スペースを占有しません。
14
—
尾部切除
上記の分析によると、文字列、実数、および辞書はすべて、独自の極端な圧縮アルゴリズムを見つけました。待って、リストはどうですか?
実際、フロントエンドを研究したことのある人なら誰でも、リストが特殊な辞書であることを知っていますが、リストの「キー」は0、1、2、3の自然数です。自然数を最適化する必要はなく、リストタイプ自体はすでにシリアル化されています。限界。
これまでのところ、ランダム入力バイナリバイト文字列もハードウェアを考慮する必要があるため、シリアル化の制限は実際には実現されていません。ランダムバイト文字列の長さが8の倍数に満たされている場合でも、メモリの最小単位は1バイトです。より究極的な問題を考える:尾部切除の問題。
データ全体の終わりであるEOFをスキャンし、最後の要素の長さがプレフィックスで宣言された長さに達していないことを発見した場合、どうすればよいですか?このとき、エラーが報告されると、原則1に違反し(エラーを報告しない)、原則2に違反する0で埋めることはできません(冗長性を拒否)。
とりあえず、最後の要素の接頭辞の「長さ」部分を削除することを考えることができます。これは、要素の長さを示すためにEOFレストを使用することと同じです。しかし、この方法には多くの落とし穴があるようですが、理論上の予備力とエネルギーが限られていることを考慮すると、テール圧縮の具体的な実装の詳細はあなたに任されています。
新入生の高等数学の試験を終えて以来、基礎知識はあまり上達していませんが、その後のコンピュータ理論の進歩は、以前に学んだ数学、物理学、化学に完全に基づいています。毎日、新しい知識を学ぶこの日はもうすぐ終わりだと感じています。 、人間の物理学のように。。
15
—
ウルトラパック
非常に多くの圧縮方法について説明した後、目的はもちろん、より優れたバイナリシリアル化形式を開発することです。そのため、適切に設計されたハフマンツリーを備えたMessagePackから改良されたUltraPackと、限界まで圧縮できる完全な形式があります。実数、文字列、バイト文字列、リスト、辞書などの一般的な形式の改善されたデータ構造は、理論的に最適なコードです!
私はファイル拡張子とMIMEタイプについても考えていますが、UltraPackは特定の実装とプロモーションに数え切れないほどの困難があるため、理論的には生き残るフォーマットです。いわゆる「制限」は情報理論の意味における制限ですか?言いにくい。このプロジェクトは現在資金提供されていませんが、チームは未定であり、コードは一時的に利用できませんが、これらは私たちがプロジェクトを証明することを妨げるものではありません。
この目的のために、UltraPackエディターを想像しました。これにより、ユーザーはUltraPack形式の構成ファイルを視覚的に読み書きできるため、読みやすさが向上し、セキュリティが向上し、テキスト形式の編集中に発生する可能性のある文法エラーを回避できます。
理論的には、UltraPackはJSONよりも小さく、機能が豊富で、安全です。しかし、すべてが理論にとどまり、空間の限界に達したUltraPackは、必然的に失敗します。
アインシュタインの相対性理論は、小さな光速で時間と空間を統合し、時間と空間が交換可能であることを人々に認識させるため、シリコンベースの科学(コンピューターサイエンス)の分野にはCPUとメモリがあります。ゲーム、アルゴリズム、データ構造の制約、時間の複雑さ、スペースの複雑さの結合。
当初から、UltraPackは時間の問題を考慮していませんでしたが、スペースの利点と引き換えに時間を可能な限り犠牲にしました。特に、完全なハフマンツリーを実現するために、バイト全体の物理的な制限を超えることをためらわないため、エンコードおよびデコード時にCPUの追加の時間オーバーヘッドが直接発生します。しかし、ここでも、時間と空間は同時に達成できない2つの矛盾であり、時間を犠牲にして、空間の費用を理論上の限界に到達させることは価値があります。
16
—
V8エンジン形而上学
終わりに近づくと、前に残った小さな質問があります:mspのパフォーマンステストで、より一般的なJS / nodeプラットフォームではなくpythonプラットフォームが選ばれたのはなぜですか?JS /ノードプラットフォームでは、エンコードでもデコードでも、mspの速度はjsonの速度よりもはるかに遅いためです。この悲劇的な事実の原因は何ですか?
犯人はV8エンジンです。
一般に、mspは理論的にはjsonよりも明らかに高速ですが、JSプラットフォームの実験結果が理論上の期待とはかなり異なる根本的な理由は、jsonの速度が速すぎるのではなく、V8エンジンによってmspの速度が大幅に低下することです。
同じJSオブジェクトが以下で定義されています。次の2つの方法のどちらが高速ですか?
// spawn an object, which way is faster?
// 第一种
const data = { foo: 42, bar: 133 }; // ????
// 第二种
const data = JSON.parse(`{"foo":42,"bar":133}`); // ????
最初の方法はオブジェクトを直接定義するため、直感的には最初の方法の方が高速です。2番目の方法はJSON文字列を使用してデコードするため、「コンパイル」操作の余分なレイヤーがあり、遅くなるようです。テスト後、2番目の方法は最初の方法よりもはるかに高速です。
基本的な理由は、最初の方法がエンジンの上にあり、2番目の方法がボンネットの下にあるためです。JSはエンジンで実行される高級言語であり、V8エンジンの存在は両刃の剣であり、人には便利ですが機械には害を及ぼします。JS仕様では、単純な関数でも完了するまでに数十ステップかかる場合があります。たとえば、Array.prototype.push()は新しい要素を配列にプッシュします。これはJSが必要とする基本的な操作です次の手順を実行します。
新しい要素を追加するために、V8は最初にチェックの長さをチェックし、次にタイプをチェックし、最後に安全であることが確実になるまでプッシュすることができます。多数のプッシュが同時に実行される場合、時間の浪費を想像することは不可能です。開発者を幸せにして、このようにマシンをトスするために、私は初めて、まだ弱く型付けされた言語を使用していることを恥ずかしく思いますか????!
これが、JSプラットフォームでmspが非常に遅い理由です。mspインタープリターはV8エンジンで実行されます。解析は高速ですが、JSオブジェクトの構築効率は大幅にブロックされ、JSONはV8エンジンでのAPIです。 、ネイティブサポートにより、JSON解析速度がハードウェアの制限に直接触れることができます。
Python、C ++などの他のプラットフォームでは、同じ配列のプッシュ操作。要素にはタイプ(TypedArray)と事前に割り当てられたメモリがあるため、プッシュの速度はエンジンの影響を受けず、mspが表示できる物理的な速度によってのみ制限されますその当然の利点。
「情報理論」シリーズは、キーワードを含む16の章すべてを完了しました:情報エントロピー、生命、二分木、シリアライゼーション、スペース制限、V8エンジン。
<終了>
私の仕事を終えた後: