быстрее чем Stackwalk - PullRequest
       3

быстрее чем Stackwalk

6 голосов
/ 02 октября 2010

Кто-нибудь знает лучший / более быстрый способ получить стек вызовов, чем «StackWalk»?Я также думаю, что stackwalk также может работать медленнее в методах с большим количеством переменных ... (интересно, что делают коммерческие профилировщики?) Я использую C ++ в Windows.:) спасибо:)

Ответы [ 3 ]

2 голосов
/ 22 июня 2014

Я использую Йохен Кальмбахс StackWalker .

Я speedet it up таким образом:

  • Наибольшее время теряется при поиске PDB files в каталогах по умолчанию и на серверах PDB.

  • Я использую только one PDB path и внедрил white list для изображений, которые я хочу получить (мне не нужно искать user32.pdb)

  • Иногда мне не нужно погружаться на дно, поэтому я определил max deep

изменения кода:

BOOL StackWalker::LoadModules()
{

    ...

    // comment this line out and replace to your pdb path
    // BOOL bRet = this->m_sw->Init(szSymPath);
    BOOL bRet = this->m_sw->Init(<my pdb path>);

    ...

}

BOOL StackWalker::ShowCallstack(int iMaxDeep /* new parameter */ ... )
{

    ... 

// define a maximal deep
// for (frameNum = 0; ; ++frameNum )
    for (frameNum = 0; frameNum < iMaxDeep; ++frameNum )
    {

        ... 

    }
}
1 голос
/ 22 октября 2010

Check http://msdn.microsoft.com/en-us/library/bb204633%28VS.85%29.aspx - это «CaptureStackBackTrace», хотя и называется «RtlCaptureStackBackTrace».

0 голосов
/ 21 октября 2010

Я не знаю, быстрее ли это, и не будет ли показывать вам какие-либо символы, и я уверен, что вы можете сделать это лучше, но этот код я написал некоторое время назад, когда мне понадобилась эта информация ( работает только для Windows):

struct CallStackItem
{
    void* pc;
    CallStackItem* next;

    CallStackItem()
    {
        pc = NULL;
        next = NULL;
    }
};

typedef void* CallStackHandle;

CallStackHandle CreateCurrentCallStack(int nLevels)
{
    void** ppCurrent = NULL;

    // Get the current saved stack pointer (saved by the compiler on the function prefix).
    __asm { mov ppCurrent, ebp };

    // Don't limit if nLevels is not positive
    if (nLevels <= 0)
        nLevels = 1000000;

    // ebp points to the old call stack, where the first two items look like this:
    // ebp -> [0] Previous ebp
    //        [1] previous program counter
    CallStackItem* pResult = new CallStackItem;
    CallStackItem* pCurItem = pResult;
    int nCurLevel = 0;

    // We need to read two pointers from the stack
    int nRequiredMemorySize = sizeof(void*) * 2;
    while (nCurLevel < nLevels && ppCurrent && !IsBadReadPtr(ppCurrent, nRequiredMemorySize))
    {
        // Keep the previous program counter (where the function will return to)
        pCurItem->pc = ppCurrent[1];
        pCurItem->next = new CallStackItem;

        // Go the the previously kept ebp
        ppCurrent = (void**)*ppCurrent;
        pCurItem = pCurItem->next;
        ++nCurLevel;
    }

    return pResult;
}

void PrintCallStack(CallStackHandle hCallStack)
{
    CallStackItem* pCurItem = (CallStackItem*)hCallStack;
    printf("----- Call stack start -----\n");
    while (pCurItem)
    {
        printf("0x%08x\n", pCurItem->pc);
        pCurItem = pCurItem->next;
    }
    printf("-----  Call stack end  -----\n");
}

void ReleaseCallStack(CallStackHandle hCallStack)
{
    CallStackItem* pCurItem = (CallStackItem*)hCallStack;
    CallStackItem* pPrevItem;
    while (pCurItem)
    {
        pPrevItem = pCurItem;
        pCurItem = pCurItem->next;
        delete pPrevItem;
    }
}
...