JavaScriptの検索の最適化
15890 ワード
Originally Posted on Skiplist blog
Skiplist JavaScriptはずっと下です.
それはゾンビのウイルスのようです.その言語はすべてを引き継いだ.そして、私の手は噛む.私は私の内側のJavaScriptキティを受け入れるか、私は常に恐れているか、私はチャンスがある間、それをチョップする必要がありますか?
今週私はメモリキャッシュのルックアップを最適化しました.顧客データセットは予想より大きかった.その結果、メモリキャッシュのデータ構造をリファクタにしなければならなかった.
キャッシュの初期のバージョンはTDDを通してプログラムされて、駆動されました.私は、私がそうすることができるとき、私の内側の機敏な技術コーチを受け入れるのが好きです.それは偶然の一致であるかもしれません、しかし、ルックアップが一定時間で起こるように、実装詳細をリファクタリングするのは簡単でした.最適化トリックの技術的な詳細については後述する.
以下の例のソースを見つけることができますhere in GitHub .
宣言型プログラミング
命令は、方法を指示します.宣言コードは何を指示します.
例を見て三人の年齢を集めましょう.
map() reduce() filter() forEach() find() 言い換えれば、宣言的なコードは表現的で、エレガントで、機能的です."clean ソーセージがどのように作られているか気にしないで、私は同意します、あなたはそれをとてもよりよく楽しむことができます!
findを使用して値を検索する
何百万のエントリのリストにIDで人を見ている同様のシナリオについてはどうですか?
キーが一意であり、我々のデータセットが管理可能なサイズの場合、我々は人々の人々のリストをIDによって人々の地図に回すことによってパフォーマンスを向上させることができ、次に、ID上のハッシュルックアップ、O(1)を実行することができます!我々は、より悪い、1回のO(n)配置ステップ、そして、o(1)が各々の記録の上でルックアップしている.
コード例
グッドスチュアートsoftware craftsmanship , 失敗から始めましょうJavaScript Unit Test を指定する.
命令
この点で、我々は赤いテストをします.我々の最初のアプローチを実装しましょう.
宣言
我々は、行動とパフォーマンステストハーネスをアサートする緑色のテストを持って、我々はキャビンについて移動することができます
最適化
最後に、私たちが大きなコレクションの入れ子になったループの中でこの探索を行っていたとしたらどうでしょう.数百と50ミリレコードの検索では、各顧客の経験を簡単に低下することができます.それでは、地図を使って例を見てみましょう.安array in JavaScript は連想配列ですので、簡単にできます
結論
JavaScriptの私の問題は、私がそれが好きでないということではないと思います.閉じるこの動画はお気に入りから削除されています.私はプリブラウザの標準化(IE 6〜2005のW/ActiveX)JavaScriptのWeb開発のメモリで怖いです.私は開発コミュニティ内の現在の位置を尊重し、ソリューションのあらゆる層で共通のプラットフォームオプションを見つけるのを楽しみにしています.
Skiplist JavaScriptはずっと下です.
それはゾンビのウイルスのようです.その言語はすべてを引き継いだ.そして、私の手は噛む.私は私の内側のJavaScriptキティを受け入れるか、私は常に恐れているか、私はチャンスがある間、それをチョップする必要がありますか?
今週私はメモリキャッシュのルックアップを最適化しました.顧客データセットは予想より大きかった.その結果、メモリキャッシュのデータ構造をリファクタにしなければならなかった.
キャッシュの初期のバージョンはTDDを通してプログラムされて、駆動されました.私は、私がそうすることができるとき、私の内側の機敏な技術コーチを受け入れるのが好きです.それは偶然の一致であるかもしれません、しかし、ルックアップが一定時間で起こるように、実装詳細をリファクタリングするのは簡単でした.最適化トリックの技術的な詳細については後述する.
以下の例のソースを見つけることができますhere in GitHub .
宣言型プログラミング
命令は、方法を指示します.宣言コードは何を指示します.
例を見て三人の年齢を集めましょう.
const people = [
{id: 1, name: "Jason", age: 38},
{id: 2, name: "Justin", age: 34},
{id: 3, name: "Josh", age: 33}
]
// imperative
const ages = []
for(let person of people) {
ages.push(person.age);
}
// declarative
const ages = people.map(person => person.age)
JavaScriptには、いくつかの組み込みヘルパー関数があります.findを使用して値を検索する
何百万のエントリのリストにIDで人を見ている同様のシナリオについてはどうですか?
const idToFind = 1000000
person = people.find(person => person.id === idToFind);
上記のステートメントはクリーンで、IDが100000の最初の人を見つけます.対照的に、同じ線形探索への命令的アプローチは、コードのおよそ1ダースのより多くの線である.シンプルです素晴らしい.シンプルでクリーンです.しかし、大文字表記(Big O Notation である.linear search 文字通り悪い.私たちは清潔さのためにパフォーマンスを犠牲にします.そして、それは私が時間的に99.8 %を選択するトレードオフですプログラミングキーが一意であり、我々のデータセットが管理可能なサイズの場合、我々は人々の人々のリストをIDによって人々の地図に回すことによってパフォーマンスを向上させることができ、次に、ID上のハッシュルックアップ、O(1)を実行することができます!我々は、より悪い、1回のO(n)配置ステップ、そして、o(1)が各々の記録の上でルックアップしている.
コード例
グッドスチュアートsoftware craftsmanship , 失敗から始めましょうJavaScript Unit Test を指定する.
const assert = require('assert');
const Search = require("./search");
describe('Search', function () {
const people = [];
before(() => {
people.push({id: 1, name: "Jason", age: 38});
people.push({id: 2, name: "Justin", age: 34});
people.push({id: 3, name: "Josh", age: 33});
});
it('should return the correct element', function () {
const expectedName = "Justin";
const search = new Search(people);
const person = search.find(2);
assert.equal(expectedName, person.name);
});
});
命令
この点で、我々は赤いテストをします.我々の最初のアプローチを実装しましょう.
class Search {
constructor(people) {
this.people = people;
}
find(id) {
for(let person of this.people) {
if(person.id === id) {
return person;
}
}
}
}
module.exports = Search;
パフォーマンスを評価するためにテストハーネスを設定します.// performance output:
// >>> Average time for find for 3 records: 0.001 ms
// >>> Total time for find for 3 records: 2 ms
// >>> Average time for find for 1000000 records: 2.617 ms
// >>> Total time for find for 1000000 records: 2906 ms
宣言
我々は、行動とパフォーマンステストハーネスをアサートする緑色のテストを持って、我々はキャビンについて移動することができます
find
方法)命令型から宣言的な形式への移行:// ...
find(id) {
return this.people.find(person => person.id === id);
}
// ...
// performance output:
// >>> Average time for find for 3 records: 0.001 ms
// >>> Total time for find for 3 records: 2 ms
// >>> Average time for find for 1000000 records: 2.356 ms
// >>> Total time for find for 1000000 records: 2690 ms
100万件の記録の検索時間は比較的変わりません.命令から宣言への移動で、コードの清潔度を得る.今すぐ“コードは、”何かのような方法では、別のデータ構造では、地図のようにスワッピングをコンセプトに簡単です.我々は認知負荷の減少を有する.最適化
最後に、私たちが大きなコレクションの入れ子になったループの中でこの探索を行っていたとしたらどうでしょう.数百と50ミリレコードの検索では、各顧客の経験を簡単に低下することができます.それでは、地図を使って例を見てみましょう.安array in JavaScript は連想配列ですので、簡単にできます
map
オブジェクトのキーとしてのID.class Search {
constructor(people) {
const peopleMap = [];
people.forEach(person => peopleMap[person.id] = person);
this.people = peopleMap
}
find(id) {
return this.people[id]
}
}
module.exports = Search;
// performance output:
// Average time for find for 3 records: 0.001 ms
// Total time for find for 3 records: 2 ms
// Average time for find for 1000000 records: 0 ms
// Total time for find for 1000000 records: 302 ms
結論
JavaScriptの私の問題は、私がそれが好きでないということではないと思います.閉じるこの動画はお気に入りから削除されています.私はプリブラウザの標準化(IE 6〜2005のW/ActiveX)JavaScriptのWeb開発のメモリで怖いです.私は開発コミュニティ内の現在の位置を尊重し、ソリューションのあらゆる層で共通のプラットフォームオプションを見つけるのを楽しみにしています.
Reference
この問題について(JavaScriptの検索の最適化), 我々は、より多くの情報をここで見つけました https://dev.to/dev3l/optimizing-search-in-javascript-2lcaテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol