私が使用しているCアプリケーションの1つで、 ctype.h の関数の下に:
isalpha()、isspace()、ispunct()、tolower()。
プロファイリング後、これらの関数の呼び出しにいくつかのボトルネックがあることがわかりました (基本的に、私のアプリは入力テキスト ファイルからの文字/文字列処理であるため、これらの関数は重要なループ内で徹底的に呼び出されます)。役立つ場合は独自の実装。
それらを実装するためのそのようなロジックはどこにありますか?
私が使用しているCアプリケーションの1つで、 ctype.h の関数の下に:
isalpha()、isspace()、ispunct()、tolower()。
プロファイリング後、これらの関数の呼び出しにいくつかのボトルネックがあることがわかりました (基本的に、私のアプリは入力テキスト ファイルからの文字/文字列処理であるため、これらの関数は重要なループ内で徹底的に呼び出されます)。役立つ場合は独自の実装。
それらを実装するためのそのようなロジックはどこにありますか?
それらをマクロまたはインライン関数として実装できます。
#define IS_ALPHA(x) (((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z'))
#define IS_SPACE(x) ((x) == ' ' || (x) == '\t')
... etc.
ただし、元isalpha
の 、isspace
、ispunct
などは現在のロケールに依存し、言語によって異なる結果になる可能性があることに注意してください。
256要素のルックアップテーブルを使用して、これらの関数を高速に実装できます。isalpha()の場合、ASCII値がiの文字が英数字の場合、i番目の要素は1です。その場合、isalphaは単なるテーブルルックアップです。
各エントリの1ビットを1つの関数の結果に割り当てることで、スペースを節約し、これらすべての関数を1つのテーブルでエンコードできます。次に、各関数は渡された文字のエントリを検索し、必要なビットをマスクします。
デイブ
そのような関数がボトルネックになるというのは奇妙に思えます。ロケールを考慮できる可能性が高く、これにより「遅く」なります。無視できる場合は、次のように簡単に実装できます(例:これはその場で書いた単なるアイデアです)
bool isalpha(int c)
{
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
bool isspace(int c)
{
return c == ' ' || c == '\t'; // || whatever other char you consider space
}
bool ispunct(int c)
{
static const char *punct = ".;!?...";
return strchr(punct, c) == NULL ? false : true; // you can make this shorter
}
int tolower(int c)
{
if ( !isalpha(c) ) return c;
return (c >= 'A' && c <= 'Z') ? c - 'A' : c;
}
次に、それらをインライン関数にします。
一般に、ライブラリ コードを記述する人々は非常に優れたソフトウェア エンジニアであり、それらの関数は n 度まで調整されています。これらの関数が考慮しなければならないいくつかのケースを削除できない限り、パフォーマンスの一致に問題が生じます。
ヘッダーを見てctype.h
ください。コンパイラ ライブラリには、これらの関数をインライン化またはマクロとして実装する方法が既に用意されている可能性があります (何らかの理由でインライン化がサポートされていない場合)。(ちなみに、どのコンパイラとターゲット プラットフォームを使用していますか?)
これらが既にインライン/マクロである場合は、関数の使用方法に関する詳細を投稿することをお勧めします。これらの関数の一部をショートカットして呼び出す方法があるかもしれません (たとえば、が true の場合、またはtrue であってはならないisspace()
ため、呼び出す必要はありません)。isalpha()
ispunct()