我的strchr()比最初的Visual Studio 2015慢

我的strchr()比最初的Visual Studio 2015慢,c,windows,visual-studio,C,Windows,Visual Studio,。我假设在VS 2015中的实现是相同的。我在一个新函数中复制了它并尝试了。我对堆中存储的字符数组[15001767]有很大的不同,3毫秒原始,17毫秒我的 这种差异在哪里 char *teststr(const char *s, int c) { while (*s != (char)c) if (!*s++) return 0; return (char *)s; } int main() { DWORD pa; c

。我假设在VS 2015中的实现是相同的。我在一个新函数中复制了它并尝试了。我对堆中存储的字符数组[15001767]有很大的不同,3毫秒原始,17毫秒我的

这种差异在哪里

char *teststr(const char *s, int c)
{
    while (*s != (char)c)
        if (!*s++)
            return 0;
    return (char *)s;
}

int main()
{
    DWORD pa;

    char *test = (char*)HeapAlloc(HeapCreate(NULL, 0, 0), NULL, 15001767);
    ReadFile(CreateFileW(L"MyFile.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, NULL, NULL), test, 15001767, &pa, NULL);

    //strchr(test, '£');
    teststr(test, '£');

}

您可能会对我使用标准库MSVC、OP函数和两个汇编程序版本(其中一个被告知字符串长度,另一个必须先找到它)构建的不同strchr实现的比较感兴趣。第二个仍然比OP的常规动作快

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

#define LEN 15001767
#define REPS 100

char array[LEN];

char *asmstrchrA(const char *s, int c)
// knows the string length
{
    __asm {
        push    es
        mov     ax,ds
        mov     es,ax
        mov     edi,s
        mov     ecx,LEN
        mov     eax,c
        cld
        repne   scasb
        jz      foundA
        xor     edi,edi         ; not found
        inc     edi
    foundA:
        dec     edi
        mov     s,edi
        pop     es
    }
    return (char *)s;
}    

char *asmstrchrB(const char *s, int c)
// finds the string length first
{
    __asm {
        push    es
        mov     ax,ds
        mov     es,ax

        mov     edi,s           ; find string length
        xor     eax,eax
        mov     ecx,-1
        cld
        repne   scasb
        mov     ecx,edi
        sub     ecx,s

        mov     edi,s           ; find char
        mov     eax,c
        cld
        repne   scasb
        jz      foundB
        xor     edi,edi         ; not found
        inc     edi
    foundB:
        dec     edi
        mov     s,edi
        pop     es
    }
    return (char *)s;
}    

char *OPstrchr(const char *s, int c)
// from OP's link
{
    while (*s != (char)c)
        if (!*s++)
            return 0;
    return (char *)s;
}    

int main (void) {
    clock_t start;
    int i;
    char * cptr;

    memset(array, '1', LEN-1);
    array[LEN-5] = '2';

    start = clock();
    for(i=0; i<REPS; i++)
        cptr = OPstrchr(array, '2');
    printf("OPstrchr   %p, time = %f seconds\n", (void*)cptr, (double)(clock() - start) / CLOCKS_PER_SEC);

    start = clock();
    for(i=0; i<REPS; i++)
        cptr = asmstrchrA(array, '2');
    printf("asmstrchrA %p, time = %f seconds\n", (void*)cptr, (double)(clock() - start) / CLOCKS_PER_SEC);

    start = clock();
    for(i=0; i<REPS; i++)
        cptr = asmstrchrB(array, '2');
    printf("asmstrchrB %p, time = %f seconds\n", (void*)cptr, (double)(clock() - start) / CLOCKS_PER_SEC);

    start = clock();
    for(i=0; i<REPS; i++)
        cptr = strchr(array, '2');
    printf("strchr     %p, time = %f seconds\n", (void*)cptr, (double)(clock() - start) / CLOCKS_PER_SEC);
return 0;
}

也许它们是使用repne scasb指令在汇编程序中编写的。标准库的名称是实现的保留名称。不要在代码中使用它们。你还需要提供问题中的代码,而不仅仅是链接。我显然改变了我函数的名称。在我做的任何测试中,即使没有新的功能,我也有大约17毫秒的持续时间。如果你为每个人展示汇编程序,请考虑把问题弄清楚,并通过张贴相关的代码来展示你的努力。我的目标是找到一个StruChr反函数。因为为找到的每个字符写入数据并从零开始。我希望避免无用的写入+开始位置0,因为我假设它比较慢。当我手动尝试它时,因为我没有找到反向函数,我得到了这个可怕的持续时间。对不起,这是一个不同的问题吗?strrchr将从字符串的末尾开始,并向后扫描。写什么?是的,这是一个关联的问题。我只假设它从位置0开始,因为文件末尾有一个字符,strchr和strrchr搜索它的时间是相同的。它必须从位置0开始,因为C不知道字符串长度。因此,它要么找到字符串长度,然后向后执行ref 1,要么像您的strchr示例那样合并这两个操作。碰巧,当我实现ref 1时,我的汇编程序strrchr比库稍微快一点,但可能只是因为搜索的字符接近字符串的末尾。是的,可能是因为字符位于字符串的末尾。那么,我唯一的方法就是编写自己的strrchr实现?没有比汇编程序更好的方法了?
OPstrchr   0125F5A2, time = 7.488000 seconds
asmstrchrA 0125F5A2, time = 1.248000 seconds
asmstrchrB 0125F5A2, time = 2.512000 seconds
strchr     0125F5A2, time = 1.045000 seconds