Maoni0 / realmon

A monitoring tool that tells you when GCs happen in a process and some characteristics about these GCs
MIT License
280 stars 25 forks source link

Proposal: Prettify console output using Spectre.Console #21

Open ryandle opened 2 years ago

ryandle commented 2 years ago

I hacked together a prototype of what the console might look like if we used a library like Spectre.Console to markup the output:

image

The above styling is just to get the idea across.

Is there any interest in using Spectre.Console to beautify the output? Leaving out extra details to first see if there is even interest in this or if there are reasons to keep the output simpler.

Maoni0 commented 2 years ago

hi @ryandle, this looks great! as long as this library doesn't increase the resource usage of this tool by much I'm all for it.

right now on windows the tool is taking up ~25mb in committed size, and the GC heap is committing < 3mb. there's a 4mb commit for Etw real time session, then there's at least 5mb for jitting some tracing methods like this (this commits ~70k and there are many of them) -

Name
 Event Windows Kernel/VirtualMem/Alloc
+ ntoskrnl!??MiAllocateVirtualMemory
 + ntoskrnl!NtAllocateVirtualMemory
  + ntdll!ZwAllocateVirtualMemory
   + ntdll!RtlpFindAndCommitPages
    + ntdll!RtlpExtendHeap
     + ntdll!RtlpAllocateHeap
      + ntdll!RtlpAllocateHeapInternal
       + coreclr!JitHost::allocateSlab
        + clrjit!ArenaAllocator::allocateNewPage
         + clrjit!LinearScan::BuildUse
          + clrjit!LinearScan::BuildNode
           + clrjit!LinearScan::buildIntervals
            + clrjit!LinearScan::doLinearScan
             + clrjit!ActionPhase >::DoPhase
              + clrjit!Compiler::compCompile
               + clrjit!Compiler::compCompileHelper
                + clrjit!Compiler::compCompile
                 + clrjit!jitNativeCode
                  + clrjit!CILJit::compileMethod
                   + coreclr!UnsafeJitFunction
                    + coreclr!MethodDesc::JitCompileCodeLocked
                     + coreclr!MethodDesc::JitCompileCodeLockedEventWrapper
                      + coreclr!MethodDesc::JitCompileCode
                       + coreclr!CodeVersionManager::PublishVersionableCodeIfNecessary
                        + coreclr!MethodDesc::DoPrestub
                         + coreclr!PreStubWorker
                          + coreclr!ThePreStub
                           + microsoft.diagnostics.tracing.traceevent!TraceEventParser.AddCallbackForEvents
                            + BROKEN
                             + Thread (32880) CPU=411ms (.NET ThreadPool Worker)

and the runtime needs memory to store type info; and I see things from yamldotnet for serialization like this one (for 200k):

Name
 Event Windows Kernel/VirtualMem/Alloc
+ ntoskrnl!??MiAllocateVirtualMemory
 + ntoskrnl!NtAllocateVirtualMemory
  + ntdll!ZwAllocateVirtualMemory
   + ntdll!RtlpFindAndCommitPages
    + ntdll!RtlpExtendHeap
     + ntdll!RtlpAllocateHeap
      + ntdll!RtlpAllocateHeapInternal
       + ucrtbase!_malloc_base
        + ucrtbase!_crt_state_management::wrapped_invoke
         + icu!icu::`anonymous namespace'::MixedBlocks::init
          + icu!icu::`anonymous namespace'::MutableCodePointTrie::compactData
           + icu!icu::`anonymous namespace'::MutableCodePointTrie::compactTrie
            + icu!icu::`anonymous namespace'::MutableCodePointTrie::build
             + icu!icu::InitCanonIterData::doInit
              + icu!icu::umtx_initOnce
               + icu!icu::Normalizer2Impl::ensureCanonIterData
                + icu!icu::CollationBuilder::CollationBuilder
                 + icu!icu::RuleBasedCollator::internalBuildTailoring
                  + icu!ucol_openRules
                   + coreclr!CloneCollatorWithOptions
                    + coreclr!GetCollatorFromSortHandle
                     + coreclr!GlobalizationNative_CompareString
                      + system.private.corelib!System.Int32 System.Globalization.CompareInfo::IcuCompareString(System.ReadOnlySpan`1[System.Char], System.ReadOnlySpan`1[System.Char], System.Globalization.CompareOptions)
                       + system.private.corelib!System.Int32 System.Globalization.CompareInfo::Compare(System.ReadOnlySpan`1[System.Char], System.ReadOnlySpan`1[System.Char], System.Globalization.CompareOptions)
                        + system.private.corelib!System.Int32 System.Globalization.CompareInfo::Compare(System.String, System.String, System.Globalization.CompareOptions)
                         + system.private.corelib!System.Globalization.TextInfo::PopulateIsAsciiCasingSameAsInvariant()
                          + system.private.corelib!System.Char System.Globalization.TextInfo::ToLower(System.Char)
                           + system.private.corelib!System.Char System.Char::ToLower(System.Char)
                            + yamldotnet!StringExtensions.FromCamelCase

if you could show me how much more memory this library uses it'd be great :) in general I see the CPU usage is basically 0 from the tool so hopefully that stays roughly the same by using this library. not trying to pick on this lib usage at all - it's just that as we pull in more libraries we need to start being conscious about the memory usage 'cause we don't want to have a tool that monitors memory but its own memory usage is unreasonably high 😂 I definitely love the result! this looks so much easier to read!

ryandle commented 2 years ago

Hey @Maoni0 - that makes sense! I ran GCRealTimeMon for ~1min with my new changes and watched the commit size. It ranged from 23-25k and after about a minute was at 24k. I'd be happy to collect before/after perfview traces too. Let me know what you think.

Edit: let it keep running for a little over an hour, up to 27,600 K commit. Screenshot below is from the 1min mark.

image

ryandle commented 2 years ago

Hey @Maoni0, hope you are enjoying the holiday season. No rush to get to this, but I had a little spare time so I wanted to share an update.

I've updated my branch to have the latest changes from main and now I'm running my local changes side-by-side with dotnet-gcmon v0.5.0.

I launched both to monitor a local process that emitted ~120 events before I captured the below. Commit size seems comparable and CPU is basically 0 for both.

I'd still need to do some cleanup of the code, but beyond that I'd be ready to open a pull request and get the next level of input from you. Let me know what you think!

image

Maoni0 commented 2 years ago

Merry Christmas @ryandle! thanks for doing the measurements! looking forward to seeing your PR :)