Я читаю исходный код для glibc2.9
. Считая исходный код функции strcpy
, производительность не так хороша, как я ожидаю.
Ниже приведен исходный код strcpy
в glibc2.9
:
char * strcpy (char *dest, const char* src)
{
reg_char c;
char *__unbounded s = (char *__unbounded) CHECK_BOUNDS_LOW (src);
const ptrdiff_t off = CHECK_BOUNDS_LOW (dest) - s - 1;
size_t n;
do {
c = *s++;
s[off] = c;
}
while (c != '\0');
n = s - src;
(void) CHECK_BOUNDS_HIGH (src + n);
(void) CHECK_BOUNDS_HIGH (dest + n);
return dest;
}
Поскольку я не знаю причину использования смещения, я провел несколько тестов производительности, сравнив приведенный выше код со следующим кодом:
char* my_strcpy(char *dest, const char *src)
{
char *d = dest;
register char c;
do {
c = *src++;
*d++ = c;
} while ('\0' != c);
return dest;
}
В результате производительность strcpy
хуже во время моих тестов. Я удалил коды привязанного указателя.
Почему версия glibc
использует смещения ??
Ниже приводится введение о тестах.
- платформа: x86 (Intel (R) Pentium (R) 4), версия gcc 4.4.2
- флаг компиляции: нет флагов, потому что я не хочу никакой оптимизации; Команда:
gcc test.c
.
Код теста, который я использовал, следующий:
#include <stdio.h>
#include <stdlib.h>
char* my_strcpy1(char *dest, const char *src)
{
char *d = dest;
register char c;
do {
c = *src++;
*d++ = c;
} while ('\0' != c);
return dest;
}
/* Copy SRC to DEST. */
char *
my_strcpy2 (dest, src)
char *dest;
const char *src;
{
register char c;
char * s = (char *)src;
const int off = dest - s - 1;
do
{
c = *s++;
s[off] = c;
}
while (c != '\0');
return dest;
}
int main()
{
const char str1[] = "test1";
const char str2[] = "test2";
char buf[100];
int i;
for (i = 0; i < 10000000; ++i) {
my_strcpy1(buf, str1);
my_strcpy1(buf, str2);
}
return 0;
}
При использовании функции my_strcpy1
выходы:
[root@Lnx99 test]#time ./a.out
real 0m0.519s
user 0m0.517s
sys 0m0.001s
[root@Lnx99 test]#time ./a.out
real 0m0.520s
user 0m0.520s
sys 0m0.001s
[root@Lnx99 test]#time ./a.out
real 0m0.519s
user 0m0.516s
sys 0m0.002s
При использовании my_strcpy2
вывод:
[root@Lnx99 test]#time ./a.out
real 0m0.647s
user 0m0.647s
sys 0m0.000s
[root@Lnx99 test]#time ./a.out
real 0m0.642s
user 0m0.638s
sys 0m0.001s
[root@Lnx99 test]#time ./a.out
real 0m0.639s
user 0m0.638s
sys 0m0.002s
Я знаю, что это не очень точно с командой time
. Но я мог бы получить ответ от пользователя времени.
Обновление:
To remove the cost used to calculate the offset, I removed some code and added a global variable.
#include <stdio.h>
#include <stdlib.h>
char* my_strcpy1(char *dest, const char *src)
{
char *d = dest;
register char c;
do {
c = *src++;
*d++ = c;
} while ('\0' != c);
return dest;
}
int off;
/* Copy SRC to DEST. */
char *
my_strcpy2 (dest, src)
char *dest;
const char *src;
{
register char c;
char * s = (char *)src;
do
{
c = *s++;
s[off] = c;
}
while (c != '\0');
return dest;
}
int main()
{
const char str1[] = "test1test1test1test1test1test1test1test1";
char buf[100];
off = buf-str1-1;
int i;
for (i = 0; i < 10000000; ++i) {
my_strcpy2(buf, str1);
}
return 0;
}
Но производительность my_strcpy2
все еще хуже, чем my_strcpy1
. Затем я проверил собранный код, но тоже не смог получить ответ.
Я также увеличил размер строки, и производительность my_strcpy1
все еще лучше, чем my_strcpy2