6

Does anybody know of a better/ faster way to get the call stack than "StackWalk"? I also think that stackwalk can also be slower on methods with a lot of variables... (I wonder what commercial profilers do?) I'm using C++ on windows. :) thanks :)

Idov
  • 93
  • 1
  • 4
  • 1
    Valgrind? http://stackoverflow.com/questions/413477/is-there-a-good-valgrind-substitute-for-windows – t0mm13b Oct 02 '10 at 12:47
  • hmmm... isn't valgrind only for unix? – Idov Oct 02 '10 at 13:09
  • and valgrind is instrumenting, I'm looking for a better way to sample the stack... – Idov Oct 02 '10 at 13:24
  • 1
    Why isn't StackWalk fast enough for you? What do you need it for? – jalf Oct 02 '10 at 14:46
  • I'm trying to write my own little profiler and i'm trying to make it as fast as i can :) – Idov Oct 02 '10 at 18:09
  • 1
    I ran into this same issue. I wrote a leak-tracking smart pointer which relied on `StackWalk` but it's *very* slow. How do apps like Process Monitor do it (since PM logs the stack for every single file/registry access incredibly quickly)? – the_mandrill Oct 04 '10 at 21:17

3 Answers3

2

I use Jochen Kalmbachs StackWalker.

I speedet it up this way:

  • The most time is lost in looking for the PDB files in the default directories and PDB Servers.

  • I use only one PDB path and implemented a white list for the images I want to get resolved (no need for me to look for user32.pdb)

  • Sometimes I dont need to dive to the bottom, so I defined a max deep

code changes:

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 )
    {

        ... 

    }
}
marsh-wiggle
  • 2,508
  • 3
  • 35
  • 52
2

I don't know if it's faster, and it won't show you any symbols, and I'm sure you can do better than that, but this is some code I wrote a while back when I needed this info (only works for 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;
    }
}
Asaf
  • 4,317
  • 28
  • 48
1

Check out http://msdn.microsoft.com/en-us/library/bb204633%28VS.85%29.aspx - this is "CaptureStackBackTrace", although it's called as "RtlCaptureStackBackTrace".

Damyan
  • 1,563
  • 9
  • 15