visual studio c++ release mode slower than debug mode for a loop incrementing a volatile

93 Views Asked by At

I have a very simple c++ program

int main()
{
    volatile int index = 0;
    for (int i = 0; i < 1000000000; i++) {
        for(int j = 0; j < 50; j++)
        {
            index++;
        }
    }
}

I compiled the code in release and debug mode and checked the assembly codes.

// Release mode assembly
main    PROC                        ; COMDAT

; 9    :    volatile int index = 0;

    mov DWORD PTR index$[rsp], 0

; 10   :    for (int i = 0; i < 1000000000; i++) {

    mov edx, 1000000000             ; 3b9aca00H
    npad    3
$LL4@main:

; 11   :        for(int j = 0; j < 50; j++)

    mov eax, 50                 ; 00000032H
    npad    11
$LL7@main:

; 12   :        {
; 13   :            index++;

    mov ecx, DWORD PTR index$[rsp]
    inc ecx
    mov DWORD PTR index$[rsp], ecx
    sub rax, 1
    jne SHORT $LL7@main

; 10   :    for (int i = 0; i < 1000000000; i++) {

    sub rdx, 1
    jne SHORT $LL4@main

; 14   :        }
; 15   :    }
; 16   : }

    ret 0
main    ENDP
_TEXT   ENDS
END
// Debug mode assembly
main    PROC                        ; COMDAT
; 8    : {

$LN9:
    push    rbp
    push    rdi
    sub rsp, 328                ; 00000148H
    lea rbp, QWORD PTR [rsp+32]
    lea rcx, OFFSET FLAT:__38206C9F_Source@cpp
    call    __CheckForDebuggerJustMyCode

; 9    :    volatile int index = 0;

    mov DWORD PTR index$[rbp], 0

; 10   :    for (int i = 0; i < 1000000000; i++) {

    mov DWORD PTR i$1[rbp], 0
    jmp SHORT $LN4@main
$LN2@main:
    mov eax, DWORD PTR i$1[rbp]
    inc eax
    mov DWORD PTR i$1[rbp], eax
$LN4@main:
    cmp DWORD PTR i$1[rbp], 1000000000      ; 3b9aca00H
    jge SHORT $LN3@main

; 11   :        for(int j = 0; j < 50; j++)

    mov DWORD PTR j$2[rbp], 0
    jmp SHORT $LN7@main
$LN5@main:
    mov eax, DWORD PTR j$2[rbp]
    inc eax
    mov DWORD PTR j$2[rbp], eax
$LN7@main:
    cmp DWORD PTR j$2[rbp], 50          ; 00000032H
    jge SHORT $LN6@main

; 12   :        {
; 13   :            index++;

    mov eax, DWORD PTR index$[rbp]
    inc eax
    mov DWORD PTR index$[rbp], eax

; 14   :        }

    jmp SHORT $LN5@main
$LN6@main:

; 15   :    }

    jmp SHORT $LN2@main
$LN3@main:

; 16   : }

    xor eax, eax
    lea rsp, QWORD PTR [rbp+296]
    pop rdi
    pop rbp
    ret 0
main    ENDP
_TEXT   ENDS
END

Based on the assemblies variables i and j are just in registers in release mode while in debug mode they are in memory and any change to them is written back instantly.

So I think release mode should be faster than debug mode but it was actually twice slower. I checked the program outside the visual studio by using stopwatch, release mode took 1 minute to finish while debug mode took only 30 seconds.

I'm really curious why it is slower!

details:

release mode machine code

; Listing generated by Microsoft (R) Optimizing Compiler Version 19.30.30706.0 

include listing.inc

INCLUDELIB OLDNAMES

EXTRN   __security_check_cookie:PROC
PUBLIC  main
; Function compile flags: /Ogtpy
;   COMDAT main
_TEXT   SEGMENT
index$ = 8
main    PROC                        ; COMDAT
; File D:\Visual Studio Projects\MultiThread_Test\Source.cpp
; Line 9
  00000 c7 44 24 08 00
    00 00 00     mov     DWORD PTR index$[rsp], 0
; Line 10
  00008 ba 00 ca 9a 3b   mov     edx, 1000000000        ; 3b9aca00H
  0000d 0f 1f 00     npad    3
$LL4@main:
; Line 11
  00010 b8 32 00 00 00   mov     eax, 50            ; 00000032H
  00015 66 66 66 0f 1f
    84 00 00 00 00
    00       npad    11
$LL7@main:
; Line 13
  00020 8b 4c 24 08  mov     ecx, DWORD PTR index$[rsp]
  00024 ff c1        inc     ecx
  00026 89 4c 24 08  mov     DWORD PTR index$[rsp], ecx
  0002a 48 83 e8 01  sub     rax, 1
  0002e 75 f0        jne     SHORT $LL7@main
; Line 10
  00030 48 83 ea 01  sub     rdx, 1
  00034 75 da        jne     SHORT $LL4@main
; Line 16
  00036 c3       ret     0
main    ENDP
_TEXT   ENDS
END
Debug mode machine codes
; Listing generated by Microsoft (R) Optimizing Compiler Version 19.30.30706.0 

include listing.inc

INCLUDELIB MSVCRTD
INCLUDELIB OLDNAMES

msvcjmc SEGMENT
__38206C9F_Source@cpp DB 01H
msvcjmc ENDS
PUBLIC  main
PUBLIC  __JustMyCode_Default
EXTRN   _RTC_InitBase:PROC
EXTRN   _RTC_Shutdown:PROC
EXTRN   __CheckForDebuggerJustMyCode:PROC
;   COMDAT pdata
pdata   SEGMENT
$pdata$main DD  imagerel $LN9
    DD  imagerel $LN9+107
    DD  imagerel $unwind$main
pdata   ENDS
;   COMDAT rtc$TMZ
rtc$TMZ SEGMENT
_RTC_Shutdown.rtc$TMZ DQ FLAT:_RTC_Shutdown
rtc$TMZ ENDS
;   COMDAT rtc$IMZ
rtc$IMZ SEGMENT
_RTC_InitBase.rtc$IMZ DQ FLAT:_RTC_InitBase
rtc$IMZ ENDS
;   COMDAT voltbl
voltbl  SEGMENT
_volmd  DB  01bH
    DB  053H
    DB  058H
voltbl  ENDS
;   COMDAT xdata
xdata   SEGMENT
$unwind$main DD 025050f01H
    DD  010a230fH
    DD  070030029H
    DD  05002H
xdata   ENDS
; Function compile flags: /Odt
;   COMDAT __JustMyCode_Default
_TEXT   SEGMENT
__JustMyCode_Default PROC               ; COMDAT
  00000 c2 00 00     ret     0
__JustMyCode_Default ENDP
_TEXT   ENDS
; Function compile flags: /Odtp /RTCsu /ZI
;   COMDAT main
_TEXT   SEGMENT
index$ = 4
i$1 = 36
j$2 = 68
main    PROC                        ; COMDAT
; File D:\Visual Studio Projects\MultiThread_Test\Source.cpp
; Line 8
$LN9:
  00000 40 55        push    rbp
  00002 57       push    rdi
  00003 48 81 ec 48 01
    00 00        sub     rsp, 328       ; 00000148H
  0000a 48 8d 6c 24 20   lea     rbp, QWORD PTR [rsp+32]
  0000f 48 8d 0d 00 00
    00 00        lea     rcx, OFFSET FLAT:__38206C9F_Source@cpp
  00016 e8 00 00 00 00   call    __CheckForDebuggerJustMyCode
; Line 9
  0001b c7 45 04 00 00
    00 00        mov     DWORD PTR index$[rbp], 0
; Line 10
  00022 c7 45 24 00 00
    00 00        mov     DWORD PTR i$1[rbp], 0
  00029 eb 08        jmp     SHORT $LN4@main
$LN2@main:
  0002b 8b 45 24     mov     eax, DWORD PTR i$1[rbp]
  0002e ff c0        inc     eax
  00030 89 45 24     mov     DWORD PTR i$1[rbp], eax
$LN4@main:
  00033 81 7d 24 00 ca
    9a 3b        cmp     DWORD PTR i$1[rbp], 1000000000 ; 3b9aca00H
  0003a 7d 23        jge     SHORT $LN3@main
; Line 11
  0003c c7 45 44 00 00
    00 00        mov     DWORD PTR j$2[rbp], 0
  00043 eb 08        jmp     SHORT $LN7@main
$LN5@main:
  00045 8b 45 44     mov     eax, DWORD PTR j$2[rbp]
  00048 ff c0        inc     eax
  0004a 89 45 44     mov     DWORD PTR j$2[rbp], eax
$LN7@main:
  0004d 83 7d 44 32  cmp     DWORD PTR j$2[rbp], 50 ; 00000032H
  00051 7d 0a        jge     SHORT $LN6@main
; Line 13
  00053 8b 45 04     mov     eax, DWORD PTR index$[rbp]
  00056 ff c0        inc     eax
  00058 89 45 04     mov     DWORD PTR index$[rbp], eax
; Line 14
  0005b eb e8        jmp     SHORT $LN5@main
$LN6@main:
; Line 15
  0005d eb cc        jmp     SHORT $LN2@main
$LN3@main:
; Line 16
  0005f 33 c0        xor     eax, eax
  00061 48 8d a5 28 01
    00 00        lea     rsp, QWORD PTR [rbp+296]
  00068 5f       pop     rdi
  00069 5d       pop     rbp
  0006a c3       ret     0
main    ENDP
_TEXT   ENDS
END
0

There are 0 best solutions below