TransWikia.com

On making a graphical real-time memory usage monitor

Mathematica Asked on February 26, 2021

I’d like to make a graphical version of

Dynamic[Refresh[MemoryInUse[], UpdateInterval -> 1]]

A naive implementation would be something like:

miu = {};
Dynamic[Refresh[ListPlot[AppendTo[miu, MemoryInUse[]]], UpdateInterval -> 1]]

(Evaluate Quit[], or equivalently, choose Evaluation > Quit Kernel, to stop it.)

This code produces a very lousy memory monitor, because it, all by itself, causes the memory to grow steadily. IOW, it’s a honking memory leak.

I tried something that I thought would be more conservative:

nReadings = 100;
miu = Table[0, nReadings];
i = 0;
updatemiu[] := Module[{},
  i = Mod[i, nReadings] + 1;
  miu[[i]] = MemoryInUse[];
  Join[Drop[miu, i], Take[miu, i]]
  ]

Dynamic[Refresh[ListPlot[updatemiu[]], UpdateInterval -> 1]]

This one leaks too, even though, in contrast to the previous version, it gets its data from a fixed-size list.

Is there a reliable way to cap the amount of memory used by this monitor?

3 Answers

This is more an extended comment than an answer. A compact version of the code given in the question is

miu = Table[0, 150]; memmin = MemoryInUse[]; memmax = memmin + 10^7;
Dynamic[Refresh[miu = Append[Drop[miu, 1], MemoryInUse[]]; 
    ListPlot[miu, PlotRange -> {memmin, memmax}], UpdateInterval -> 1, 
    TrackedSymbols :> {}]]

(A small PlotRange is chosen here to emphasize the memory growth.) Run for ten minutes on my four-processor, Mathematica consumes about 20% more memory than when it started, from about 50000 to nearly 60000 kB.

enter image description here

CPU utilization is negligible. Note that TrackedSymbols :> {} is essential; without it memory growth is far greater and CPU utilization jumps to nearly 20%.

The sample Wolfram code identified by Karsten 7, on the other hand, produces only minor memory growth, although with nearly 20% CPU utilization. Of course, a larger UpdateInterval would reduce CPU utilization, as commented by m_goldberg. A larger UpdateInterval also would reduce memory growth for the code above.

Answered by bbgodfrey on February 26, 2021

Using Graphics directly instead of *Plot should give a better performance. The following code with timeStep set to 0.1 consumes less than 10% CPU on my laptop.

Click the graphics to pause, click again to resume, click the "Truncate to ..." button to truncate the record:

DynamicModule[{miu, flag = True, timeStep = .1},
    Module[{startTime = AbsoluteTime[], postlen = 10, maxlen = 200},
        miu = {{AbsoluteTime[] - startTime, MemoryInUse[]/1024^2 // N}};
        Pause[timeStep];
        DynamicWrapper[
            Column[{
                    Button[
                        Deploy@Graphics[{
                                    Line[Dynamic[miu, TrackedSymbols :> {miu}]]
                                    }, AspectRatio -> 1/GoldenRatio, Frame -> True, 
                                FrameTicks -> {{None, All}, {True, None}},
                                ImageSize -> 400,
                                Background -> 
                                    Dynamic[If[flag, White, GrayLevel[.95]], 
                                        TrackedSymbols :> {flag}]
                                ],
                        flag = ! flag,
                        Appearance -> "Frameless"],
                    Button[
                        Row[{"Truncate to ", "〚", postlen, 
                                ";;〛"}],
                        If[Length[miu] > postlen, miu = miu[[postlen ;;]]]
                        ],
                    Button[
                        Row[{"Truncate to ", "〚-", maxlen, 
                                ";;〛"}],
                        If[Length[miu] > maxlen, miu = miu[[-maxlen ;;]]]
                        ]
                    }],
            If[flag,
                Refresh[
                    miu = 
                        Join[miu, {{AbsoluteTime[] - startTime, (
                                        MemoryInUse[] - ByteCount[miu])/1024^2 // N}}],
                    UpdateInterval -> timeStep]
                ],
            TrackedSymbols :> {flag}
            ]
        ]
    ]

simple memory monitor

Answered by Silvia on February 26, 2021

As a Palette

1) Using ListLinePlot:

CreatePalette[{
  DynamicModule[{miu, timeStep = 0.1},
   Grid[{
     {Row[{"Current MemoryInUse [MiB]: ", 
        Dynamic[Style[miu[[-1]], Bold], TrackedSymbols :> {miu}]}],
      Item[Row[{"time step: ", RadioButtonBar[Dynamic[timeStep], {0.1, 0.5, 1}], 
         Spacer[35]}], Alignment -> Right]},
     {Dynamic[
       ListLinePlot[
        miu = Append[Drop[miu, 1], MemoryInUse[]/1024.^2.], 
        Frame -> True, FrameTicks -> {{None, All}, {True, None}}, 
        ImageSize -> 500, PlotRange -> All],
       TrackedSymbols :> {}, UpdateInterval -> timeStep, 
       Initialization :> (miu = ConstantArray[MemoryInUse[]/1024.^2., 500]; 
        timeStep = 0.1;)], 
      SpanFromLeft}}, Spacings -> {0, 0}]],
  CancelButton["Close", DialogReturn[]]},
 WindowTitle -> "Kernel Memory Usage"]

enter image description here

2) Using Graphics and additional styling:

CreatePalette[{
  DynamicModule[{miu, timeStep, xRange},
   Grid[{
     {Row[{"Current MemoryInUse [MiB]: ", 
        Dynamic[Style[miu[[-1]], Bold], TrackedSymbols :> {miu}]}],
      Item[
       Row[{"time step: ", RadioButtonBar[Dynamic[timeStep], {0.03, 0.1, 0.5, 1}], 
         Spacer[32]}], Alignment -> Right]},
     {Graphics[{Hue[0.5908], 
        Line[Dynamic[
          Refresh[Thread[{xRange, miu = Append[Drop[miu, 1], MemoryInUse[]/1024.^2.]}], 
           TrackedSymbols :> {}, UpdateInterval -> timeStep], None, 
          TrackedSymbols :> {}, UpdateInterval -> Infinity]]}, 
       Frame -> True, FrameTicks -> {{None, All}, {True, None}}, 
       AspectRatio -> 1/GoldenRatio, ImageSize -> 500, 
       PlotRange -> All, FrameStyle -> GrayLevel[0.5]], SpanFromLeft}
     }, Spacings -> {0, 0}, BaseStyle -> {GrayLevel[0.5]}], 
   Initialization :> (miu = ConstantArray[MemoryInUse[]/1024.^2., 500]; 
      xRange = Range[500]; timeStep = 0.1)],
  CancelButton["Close", DialogReturn[]]}, 
 Background -> GrayLevel[0.17], WindowTitle -> "Kernel Memory Usage", 
 WindowFrame -> "Frameless", WindowFloating -> True, 
 WindowClickSelect -> False, Deployed -> True]

Animation2

Answered by Karsten 7. on February 26, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP