【C言語】
自作のstrcpyは
標準関数の5~6倍遅かった

自作のstrcpyは遅い

パチモノ自作関数を実務で作ってはいけない

と別の投稿でも書きましたが

どのくらい処理速度が違うのか
mem系関数に続いてsrc系関数を
自作関数と標準関数で比較してみました。

■自作strcmp

int 自作strcmp(const char* s1, const char* s2) {
    while (*s1 && (*s1 == *s2)) {
        s1++;
        s2++;
    }
    return *s1 - *s2;
}

■自作strcpy

char *自作strcpy(char* dest, const char* src) {
  while (*src != '\0') {
    *dest = *src;
    dest++;
    src++;
  }
  *dest = '\0';
  return    dest;
}

■自作strlen

size_t 自作strlen(const char *s) {
    size_t len = 0;
    while (*s != '\0') {
        len++;
        s++;
    }
    return len;
}

■自作strncmp

int 自作strncmp(const char* str1, const char* str2, size_t n)
{
    for (size_t i = 0; i < n; i++){
        if (str1[i] != str2[i]){
            return str1[i] - str2[i];
        }
        if (str1[i] == '\0'){
            return 0;
        }
    }
    return 0;
}

■自作strncpy

char* 自作strncpy(char* dest, const char* src, size_t n) {
    char* ret = dest;
    while (n > 0 && *src != '\0') {
        *dest++ = *src++;
        n--;
    }
    while (n > 0) {
        *dest++ = '\0';
        n--;
    }
    return ret;
}

■自作関数vs標準関数

#include    <stdio.h>
#include    <string.h>
#include    <time.h>
#include    <assert.h>

int 自作2引数(char *dst,char *src){
    自作strcpy(dst,src);
    return  自作strcmp(src,dst) ;
}
int 標準2引数(char *dst,char *src){
    strcpy(dst,src);
    return  strcmp(src,dst) ;
}
int 自作3引数(char *dst,char *src){
    size_t  size = 自作strlen(src)+1;
    自作strncpy(dst,src,size) ;
    return  自作strncmp(dst,src,size);
}
int 標準3引数(char *dst,char *src){
    size_t size = strlen(src)+1;
    strncpy(dst,src,size) ;
    return  strncmp(dst,src,size);
}
typedef  int (*関数ポインタ_型)(char *,char *);
static inline void    時間計測(
    char    *title,
    関数ポインタ_型     計測対象関数,
    char    *dst,
    char    *src
){
    clock_t     start   = clock();
    for(int j = 0;j < 0x10000 ; j++){
        const size_t max = strlen(src);
        for(size_t i = 0;i < max ; i++){   
            if(計測対象関数(dst,src+i) != 0){
                assert(0);
            }
        }
    }    
    clock_t     end     = clock();
    printf("%s\t:%.2f 秒\n",title, (double)(end - start) / CLOCKS_PER_SEC); 
    //printf("%s\t%8ld clock\n",title, end - start);
}
char *src = 
"Jugemu Jugemu," 
"Gokō no Surikire," 
"Kaijarisuigyo no Suigyōmatsu," 
"Ungyōmatsu," 
"Fūraimatsu," 
"Kuunerutokoro ni Sumutokoro," 
"Yaburakōji no Burakōji," 
"Paipo Paipo," 
"Paipo no Shūringan," 
"Shūringan no Gūrindai," 
"Gūrindai no Ponpokopī no Ponpokona no Chōkyūmei,"
"Chōkyūmei no Chōsuke";
static  char    dst1[BUFSIZ];
static  char    dst2[BUFSIZ]; 
static  char    dst3[BUFSIZ]; 
static  char    dst4[BUFSIZ];  
int main(void){
    時間計測("標準2引数",標準2引数,dst2,src);
    時間計測("標準3引数",標準3引数,dst4,src);
    時間計測("自作2引数",自作2引数,dst1,src);
    時間計測("自作3引数",自作3引数,dst3,src);
    
    printf("dst1[0]=%c\n",dst1[0]);
    printf("dst2[0]=%c\n",dst2[0]);
    printf("dst3[0]=%c\n",dst3[0]);
    printf("dst4[0]=%c\n",dst4[0]);
}

やっている事は
“Jugemu Jugemu,~~”の長い文字列を
一文字づつずらしながら
外部変数の配列にコピーして、
コピー元と比較しています。

ご自分の環境にコピペしてコンパイル&実行してみて下さい。


■実験結果

+ gcc -Wall -Wextra vs.c
+ ./a.out
標準2引数       :0.47 秒
標準3引数       :0.83 秒
自作2引数       :10.77 秒
自作3引数       :19.02 秒
dst1[0]=e
dst2[0]=e
dst3[0]=e
dst4[0]=e
+ gcc -Wall -Wextra vs.c -O
+ ./a.out
標準2引数       :0.67 秒
標準3引数       :1.14 秒
自作2引数       :3.98 秒
自作3引数       :6.20 秒
dst1[0]=e
dst2[0]=e
dst3[0]=e
dst4[0]=e

筆者の環境下では

最適化ありで1.14秒対6.20秒。
毎回結果が微妙に変わりますが、

だいたい自作関数は標準関数より
5~6倍くらい遅いようです。

自分ならもっと高速な自作関数を書けると
お考えの方は是非自作関数を書き換えて実験してみて下さい。