基本的に何百万ものテストを実行しているソフトウェアを最適化しようとしています。これらのテストは、繰り返しが発生する可能性がある方法で生成されます。もちろん、効率的に回避できれば、すでに実行したテストの実行に時間を費やしたくありません。
そこで、すでに実行されたテストを保存するためにブルームフィルターを使用することを考えています。しかし、ブルームフィルターは私にとって危険な側面で誤りを犯します。誤検知が発生します。つまり、実行していないテストを実行したと報告される場合があります。これは私が取り組んでいるシナリオでは許容できるかもしれませんが、ブルームフィルターに相当するものがあるかどうか疑問に思っていましたが、反対側に誤りがありました。つまり、フォールスネガティブを与えるだけです。
私は運がなくて文献をざっと読んだ。
はい、不可逆ハッシュテーブルまたはLRUCacheは、高速O(1)ルックアップを備えたデータ構造であり、フォールスネガティブのみを提供します。「テストXを実行しましたか」と尋ねると、 「はい、間違いなく持っています」または「思い出せません」のいずれかが表示されます。
非常に大雑把な擬似コードを許してください。
setup_test_table():
create test_table( some large number of entries )
clear each entry( test_table, NEVER )
return test_table
has_test_been_run_before( new_test_details, test_table ):
index = hash( test_details , test_table.length )
old_details = test_table[index].detail
// unconditionally overwrite old details with new details, LRU fashion.
// perhaps some other collision resolution technique might be better.
test_table[index].details = new_test_details
if ( old_details === test_details ) return YES
else if ( old_details === NEVER ) return NEVER
else return PERHAPS
main()
test_table = setup_test_table();
loop
test_details = generate_random_test()
status = has_test_been_run_before( test_details, test_table )
case status of
YES: do nothing;
NEVER: run test (test_details);
PERHAPS: if( Rand()&1 ) run test (test_details);
next loop
end.
このタスクを実行する正確なデータ構造は 直接マップされたキャッシュ であり、CPUで一般的に使用されます。
function set_member(set, item)
set[hash(item) % set.length] = item
function is_member(set, item)
return set[hash(item) % set.length] == item
実行したテストを保存することは可能ですかnot実行しますか?これにより、フィルターの動作が逆になります。
ソリューションの一部を省略していると思います。誤検知を完全に回避するには、実行されたものを追跡する必要があります。基本的に、ブルームフィルターをショートカットとして使用して、テストが確実に実行されていないことを確認します。
とはいえ、事前にテストの数を知っているので、いくつかのよく知られた式を使用して、許容可能なエラー率を提供するようにフィルターのサイズを設定できます。誤検知を返す確率が1%の場合、エントリあたり最大9.5ビットが必要です。したがって、100万エントリの場合は1.2メガバイトで十分です。許容可能なエラー率を0.1%に減らすと、これは1.8MBにしか増加しません。
ウィキペディアの記事 ブルームフィルター は、優れた分析と、関連する数学の興味深い概要を示しています。
いいえ、あなたがそれについて考えるならば、それはあまり役に立ちません。あなたの場合、常に「偽陰性」が存在する場合、実行する必要のあるテストが常に存在するため、テストの実行が停止することを確信できませんでした...
私はあなたがただハッシュを使わなければならないと言うでしょう。
申し訳ありませんが、あまり役に立ちません。それは不可能だと思います。テストの実行を注文できない場合は、パック形式(1バイトあたり8テスト!)または結果をメモリに格納するための適切なスパース配列ライブラリを使用してください。