dotMemory CLI with .NET Core throws exception

I'm trying to profile a .NET Core console application with the dotMemory CLI using the profilling API.  This works fine from the GUI, but the CLI throws an exception:

The profiler is running. Waiting for connection from profiling process...

Press Ctrl-C to stop profiling

Profiler connected. PID:11612, runtime v4.0.30319.0

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'System.Runtime, Version=4.2.0.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
  [PID:11612] Cannot set EOF
  [location] = C:\Build Agent\work\f532b5455ffc19e9\dotCommon\Native\Shared\include\jetbrains/common/memory_mapped_file_
allocator.hpp(301)
  [function] = void __cdecl jetbrains::common::memory_mapped_file_allocator<unsigned int,struct jetbrains::common::lockf
ree_allocator<65536,1,0>,1,1,0>::close(void)
  [WIN32 error] = 1224, The requested operation cannot be performed on a file with a user-mapped section open
Profiler disconnected. PID:11612
 
 
7 comments
Comment actions Permalink

Hello David,

Probably you try to start .NET Core application from .dll, please use dotnet.exe to start your .NET Core application from dotMemory console, for example:

dotMemory.exe start "C:\Program Files\dotnet\dotnet.exe" -- "<PathToApplication>.dll"

Path to dotnet.exe may differ on your machine.

Don't forget to specify any trigger to get a snapshot.

 

0
Comment actions Permalink

Hi Anna,

Using the fully qualified path to `dotnet.exe` did the trick.

Thanks

0
Comment actions Permalink

You're welcome!

dotMemory UI contains separate ".NET Core Application" configuration which allow to specify .NET Core application path only. dotnet.exe is launched for this configuration by default.

Currently, dotMemory CLI contains only "start" command, which corresponds "Standalone" configuration, and "start-iis" command, which corresponds IIS configuration.

0
Comment actions Permalink

Thanks.

Can I analysis the snapshot file produced within the GUI?
The docs say that the CLI is suitable for CI.

0
Comment actions Permalink

David,

Could you please describe your use case in details? Do you want to analyze memory snapshots data and perform any assertions automatically on CI server?

Currently, dotMemory CLI provides only possibility to start application and get snapshots using stdin messages. We have a feature request in our tracker: https://youtrack.jetbrains.com/issue/DMRY-4677

We suggest you to pay your attention on dotMemory Unit: https://www.jetbrains.com/dotmemory/unit/

It allows you to make memory assertions in unit tests.

 

0
Comment actions Permalink

It's a small use case for a blog post. I want to prove that an allocation is happening when I use a certain class. Unfortunately, can't export results from the GUI in a format that's consumable by anything to reduce a plain text report.

I think I can solve the problem with the ClrMD, but your tool is nicer.

0
Comment actions Permalink

David,

If you need allocation result in text view, you can try to copy it from dotMemory interface, probably it will be useful for you. For example, copy result from Similar Retention view looks like:
1048 bytes in 1 objects of AppName.Settings.Setting[]

Main Retention Path:
Roots: Static reference
<D> AppName.Settings.App.AppSettings.settings ->
<D> System.Collections.Generic.List<AppName.Settings.Setting>._items ->
    AppName.Settings.Setting[]

Or if you copy it from Creation Stack Trace view for certain object instance:

Setting[128]

Allocation stack trace

System.Collections.Generic.List<T>.set_Capacity(Int32 value)
System.Collections.Generic.List<T>.EnsureCapacity(Int32 min)
System.Collections.Generic.List<T>.Add(T item)
AppName.Settings.SettingsView.AddSettingDuringCtor<TSetting>(TSetting setting)
AppName.Settings.SettingsView.AddSettingsDuringCtor<TSettings>(TSettings settings)
AppName.Settings.SettingsBase.RegisterSectionDuringCtor<TSection>(TSection section)
AppName.Settings.App.AppSettings.ctor(SettingsStorageHandler storageHandler)
AppName.Settings.App.AppSettings.cctor()
[Native code]
AppName.Startup.StartPart2(String mutexName, String[] remainingArgs)
AppName.Startup.Start()
AppName.Startup.Main(String[] args)
[AllThreadsRoot]

 

Also you can use dotMemory Unit to create a sample with test which checks for this class:

      [TestMethod]
      public void MemoryTest()
      {
        // preconditions
        dotMemory.Check(memory =>
        {
          var objectSet = memory.GetObjects(_ => _.Type.Is(typeof(MyClass)));
          Assert.IsTrue(objectSet.ObjectsCount > 0);
        });
      }

Test run result:

MemoryTest Success

Or test with AssertTraffuc attribute if this object is collected after GC:

      [AssertTraffic(AllocatedObjectsCount = 0,Types = new []{typeof(MyClass)})]
      [TestMethod]
      public void MemoryTest()
      {
        // preconditions
        dotMemory.Check(memory =>
        {
          var objectSet = memory.GetObjects(_ => _.Type.Is(typeof(MyClass)));
          Assert.IsTrue(objectSet.ObjectsCount == 0);
        });
      }

Test run result:

Number of allocated objects of type [MyClass]
Expected: 0
But was: 1

 

 

0

Please sign in to leave a comment.