Я отлаживаю приложение, которое работает немного медленнее, когда оно собрано как 64-битный исполняемый файл Linux ELF, чем как 32-битный исполняемый файл Linux ELF. Используя Rational (IBM) Quantify, я отследил большую часть различий в производительности до (барабанная дробь ...) memset
. Как ни странно, memset
занимает на лот больше в 64-битном исполняемом файле.
Я даже могу увидеть это с помощью небольшого, простого приложения:
#include <stdlib.h>
#include <string.h>
#define BUFFER_LENGTH 8000000
int main()
{
unsigned char* buffer = malloc(BUFFER_LENGTH * sizeof(unsigned char));
for(int i = 0; i < 10000; i++)
memset(buffer, 0, BUFFER_LENGTH * sizeof(unsigned char));
}
Я строю так:
$ gcc -m32 -std=gnu99 -g -O3 ms.c
и
$ gcc -m64 -std=gnu99 -g -O3 ms.c
Время настенных часов, сообщаемое time
, больше для сборки -m64
, и Quantify подтверждает, что дополнительное время затрачивается на memset
.
До сих пор я тестировал в VirtualBox и VMWare (но не в «голом железе» Linux; я понимаю, что мне нужно сделать это дальше). Количество потраченного дополнительного времени может немного отличаться от одной системы к другой.
Что здесь происходит? Существует ли общеизвестная проблема, которую не может обнаружить мой Google-foo?
РЕДАКТИРОВАТЬ: Разборка (gcc ... -S
) в моей системе показывает, что memset
вызывается как внешняя функция:
32-бит:
.LBB2:
.loc 1 14 0
movl $8000000, 8(%esp)
.loc 1 12 0
addl $1, %ebx
.loc 1 14 0
movl $0, 4(%esp)
movl %esi, (%esp)
call memset
* +1034 * 64-битный: * +1035 *
.LBB2:
.loc 1 14 0
xorl %esi, %esi
movl $8000000, %edx
movq %rbp, %rdi
.LVL1:
.loc 1 12 0
addl $1, %ebx
.loc 1 14 0
call memset
Система:
- CentOS 5.7 2.6.18-274.17.1.el5 x86_64
- GCC 4.1.2
- Процессор Intel® Core ™ TM i7-2600K @ 3,40 ГГц / VirtualBox
(расхождение хуже на Xeon E5620 @ 2,40 ГГц / VMWare)