まず、すべてのプロファイリング スイッチと DEBUG スイッチをオフにします。これらはSTLを非常に遅くする可能性があります。
そうでない場合、文字列の最初の 80 ~ 90% が同一であることが問題の一部である可能性があります。これはマップにとって必ずしも悪いことではありませんが、文字列の比較には問題があります。この場合、検索に時間がかかる場合があります。
たとえば、このコードで find() を実行すると、文字列の比較が 2 回行われる可能性がありますが、それぞれが「david」までの最初の文字を比較した後に戻り、次に最初の 3 文字がチェックされます。そのため、呼び出しごとに最大 5 文字がチェックされます。
map<string,int> names;
names["larry"] = 1;
names["david"] = 2;
names["juanita"] = 3;
map<string,int>::iterator iter = names.find("daniel");
一方、次のコードでは、find() は 135 文字以上をチェックする可能性があります。
map<string,int> names;
names["/usr/local/lib/fancy-pants/share/etc/doc/foobar/longpath/yadda/yadda/wilma"] = 1;
names["/usr/local/lib/fancy-pants/share/etc/doc/foobar/longpath/yadda/yadda/fred"] = 2;
names["/usr/local/lib/fancy-pants/share/etc/doc/foobar/longpath/yadda/yadda/barney"] = 3;
map<string,int>::iterator iter = names.find("/usr/local/lib/fancy-pants/share/etc/doc/foobar/longpath/yadda/yadda/betty");
これは、各文字列の先頭が同じであるため、一致を見つけるために文字列比較でより深く検索する必要があるためです。
データセットが非常に小さいため、同等の比較で size() を使用しても、ここではあまり役に立ちません。std::map はソートされたままなので、その要素はバイナリ検索で検索できます。find を呼び出すたびに、ミスの場合は文字列比較が 5 回未満になり、ヒットの場合は平均 2 回の比較になります。しかし、それはあなたのデータに依存します。ほとんどのパス文字列の長さが異なる場合は、Motti が説明するようなサイズ チェックが大いに役立ちます。
代替アルゴリズムを考えるときに考慮すべきことは、取得する「ヒット」の数です。ほとんどの find() 呼び出しは end() またはヒットを返しますか? ほとんどの find() が end() (ミス) を返す場合、毎回マップ全体を検索しています (2logn 文字列比較)。
Hash_map は良い考えです。ヒットの検索時間を約半分に短縮する必要があります。ミスのためにもっと。
パス文字列の性質上、特に上記のコードのようにデータ セットに共通の祖先がある場合は、カスタム アルゴリズムが必要になることがあります。
考慮すべきもう 1 つの点は、検索文字列を取得する方法です。それらを再利用している場合は、比較しやすいものにエンコードすると役立つ場合があります。それらを一度使用して破棄すると、このエンコード手順はおそらくコストがかかりすぎます。
文字列検索を最適化するために、ハフマン コーディング ツリーのようなものを 1 回 (かなり前に) 使用しました。そのようなバイナリ文字列検索ツリーは、場合によってはより効率的かもしれませんが、あなたのような小さなセットではかなり高価です.
最後に、代替の std::map 実装を調べます。VC の stl コードのパフォーマンスの一部について悪いことを聞いたことがあります。特に DEBUG ライブラリは、すべての呼び出しであなたをチェックするのが苦手です。 StlPortは良い代替手段でしたが、ここ数年は試していません。ブーストも昔から大好きです。