timcassell / ProtoPromise

Robust and efficient library for management of asynchronous operations in C#/.Net.
MIT License
151 stars 13 forks source link

Ability to Force Release Build in NuGet Target #434

Closed creativitRy closed 3 months ago

creativitRy commented 4 months ago

NuGet target causes the debug build to be used when building a client project in debug configuration. However, the ProtoPromise debug build causes heap allocations (example) that are not useful outside of debugging. Is it possible to use the release build regardless of the client project/solution configuration?

timcassell commented 4 months ago

@creativitRy Why do you care about allocations in a debug build? This library is guaranteed to be alloc-free in release builds only.

If you really need it, I suppose you could just use the release dll directly instead of a package reference.

creativitRy commented 4 months ago

We are looking to build our project in debug configuration but use ProtoPromise via its release build. If possible, we are looking to do so via NuGet and not by building from source.

If we were to use the ProtoPromise release DLL directly regardless of our project's configuration, I came up with the following snippet:

  <ItemGroup>
    <PackageReference Include="ProtoPromise" GeneratePathProperty="true">
      <ExcludeAssets>build</ExcludeAssets>
    </PackageReference>
  </ItemGroup>
  <ItemGroup>
    <Reference Include="ProtoPromise">
      <HintPath>$(PkgProtoPromise)\lib\net6.0\Release\ProtoPromise.dll</HintPath>
    </Reference>
  </ItemGroup>

However, this needs to be copied to all csprojs that use ProtoPromise. This also has the path hardcoded to use net6.0.

Instead, it would be more pleasing if we can configure to use the ProtoPromise release build via some custom variable. Example pseudocode:

  <PropertyGroup>
    <PROTO_PROMISE_DEBUG_DISABLE>true</PROTO_PROMISE_DEBUG_DISABLE>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="ProtoPromise"/>
  </ItemGroup>
timcassell commented 4 months ago

Hm, that might be possible to do. I'll have to investigate.

But I'm also curious why you want to use ProtoPromise in RELEASE with your own projects in DEBUG. ProtoPromise in DEBUG has some extra safety measures built in to ensure the library is used properly by the consumer, which are stripped out of the RELEASE build for performance.

creativitRy commented 4 months ago

We are building a realtime application that runs in very high frame rates, and ProtoPromise in DEBUG is allocating many thousands of times per second. The frequent garbage collection is unfortunately causing very noticeable stutters.

I guess this wouldn't matter when we ship a release build, but we have our own safety checks enabled during development, and we would prefer to keep both our safety checks and a stutter-free debugging experience.

timcassell commented 4 months ago

I added the option to force a configuration via <ProtoPromiseConfiguration> property in #437. Use Release or Debug as the value. It will be in the next release.

timcassell commented 4 months ago

Also noteworthy is that even with ProtoPromise in Release, all of your async Promise functions will still allocate. This is because of the backing state machine that the C# compiler generates uses a class in Debug, and a struct in Release. So you will only truly get zero-alloc with your projects in Release.

creativitRy commented 4 months ago

Ah I didn't know. Thanks for the heads up! The release build still causes significantly less GC stutters than the debug build.