What is a safe Maximum Stack Size or How to measure use of stack?

后端 未结 6 1766
栀梦
栀梦 2020-12-15 11:12

I have an app with a number of worker threads, one for each core. On a modern 8 core machine, I have 8 of these threads. My app loads a lot of plugins, which also have their

6条回答
  •  囚心锁ツ
    2020-12-15 11:55

    I remember i FillChar'd all available stack space with zeroes upon init years ago, and counted the contiguous zeroes upon deinit, starting from the end. This yielded a good 'high water mark', provided you send your app through its paces for probe runs.

    I'll dig out the code when i am back nonmobile.

    Update: OK the principle is demonstrated in this (ancient) code:

    {***********************************************************
      StackUse - A unit to report stack usage information
    
      by Richard S. Sadowsky
      version 1.0 7/18/88
      released to the public domain
    
      Inspired by a idea by Kim Kokkonen.
    
      This unit, when used in a Turbo Pascal 4.0 program, will
      automatically report information about stack usage.  This is very
      useful during program development.  The following information is
      reported about the stack:
    
      total stack space
      Unused stack space
      Stack spaced used by your program
    
      The unit's initialization code handles three things, it figures out
      the total stack space, it initializes the unused stack space to a
      known value, and it sets up an ExitProc to automatically report the
      stack usage at termination.  The total stack space is calculated by
      adding 4 to the current stack pointer on entry into the unit.  This
      works because on entry into a unit the only thing on the stack is the
      2 word (4 bytes) far return value.  This is obviously version and
      compiler specific.
    
      The ExitProc StackReport handles the math of calculating the used and
      unused amount of stack space, and displays this information.  Note
      that the original ExitProc (Sav_ExitProc) is restored immediately on
      entry to StackReport.  This is a good idea in ExitProc in case a
      runtime (or I/O) error occurs in your ExitProc!
    
      I hope you find this unit as useful as I have!
    
    ************************************************************)
    
    {$R-,S-} { we don't need no stinkin range or stack checking! }
    unit StackUse;
    
    interface
    
    var
      Sav_ExitProc     : Pointer; { to save the previous ExitProc }
      StartSPtr        : Word;    { holds the total stack size    }
    
    implementation
    
    {$F+} { this is an ExitProc so it must be compiled as far }
    procedure StackReport;
    
    { This procedure may take a second or two to execute, especially }
    { if you have a large stack. The time is spent examining the     }
    { stack looking for our init value ($AA). }
    
    var
      I                : Word;
    
    begin
      ExitProc := Sav_ExitProc; { restore original exitProc first }
    
      I := 0;
      { step through stack from bottom looking for $AA, stop when found }
      while I < SPtr do
        if Mem[SSeg:I] <> $AA then begin
          { found $AA so report the stack usage info }
          WriteLn('total stack space : ',StartSPtr);
          WriteLn('unused stack space: ', I);
          WriteLn('stack space used  : ',StartSPtr - I);
          I := SPtr; { end the loop }
        end
        else
          inc(I); { look in next byte }
    end;
    {$F-}
    
    
    begin
      StartSPtr := SPtr + 4; { on entry into a unit, only the FAR return }
                             { address has been pushed on the stack.     }
                             { therefore adding 4 to SP gives us the     }
                             { total stack size. }
      FillChar(Mem[SSeg:0], SPtr - 20, $AA); { init the stack   }
      Sav_ExitProc := ExitProc;              { save exitproc    }
      ExitProc     := @StackReport;          { set our exitproc }
    end.
    

    (From http://webtweakers.com/swag/MEMORY/0018.PAS.html)

    I faintly remember having worked with Kim Kokkonen at that time, and I think the original code is from him.

    The good thing about this approach is you have zero performance penalty and no profiling operation during the program run. Only upon shutdown the loop-until-changed-value-found code eats up CPU cycles. (We coded that one in assembly later.)

提交回复
热议问题