ConcurrentDictionary - Good read speed even in the face of concurrency, but it’s a heavyweight object to create and slower to update.
Dictionary with lock - Poor read speed lightweight to create and “medium” update speed.
Dictionary as immutable object - best read speed and lightweight to create but heavy update. Copy and modify on mutation e.g. new Dictionary(old).Add(key, value)
Hastable - Good read speed (no lock required), sameish weight as dictionary but more expensive to mutate and no generics!
ImmutableDictionary - Poorish read speed, no locking required but more allocations require to update than a dictionary.
This sort of guidance usually only comes up when implementation tradeoffs are being made but I’d love to spend more time documenting details like this…
This post is from an internal conversation I had with @stephentoub. The architect for the .NET libraries. We’ve been having discussions about how to write better recommendations for types like this.
• • •
Missing some Tweet in this thread? You can try to
force a refresh
First, you'll be able to use Aspire 9 with .NET 8 and .NET 9! It will no longer require a call to dotnet workload install, and instead uses an MSBuild SDK. This should simplify CI/CD integration and getting started immensely! All you need is NuGet!
#dotnet #aspire
Next is the first-class addition of "WaitFor". You can now wait for dependencies to start, be healthy or to be complete before running your resource.
This is much like "depends_on" in docker compose, but with the ability to write health checks in C#.
@JamesNK has been posting about the most requested feature being the ability to start and stop services. If you have the debugger attached it will re-attach on restart 🤯!
Here's some code that is on the hot path on your application and you want to optimize it. This is what a typical C# developer would write (actually copilot wrote this). It's pretty clear, but suboptimal. How could you go about improving it? #dotnet #csharp
There are lots of allocations here: 1. The string[] splitting up query string parts by & 2. Each key value pair string[] splitting each part by = 3. The List<string> of new results 4. The final string
One more assumption you can make: The instanceId will only occur once or 0 times in the input querystring.
Discrete events masquerading as a workflow should be expressed as such. Consider the following event-based model: #dotnet
The game has 3 events:
- GameStarted
- GameEnded
- OnQuestion
The order of execution should be obvious from the naming...
The application doesn't control the event loop, the event loop will trigger the events at the appropriate time. Storing state across events means understanding the order in which they fire, the thread safety of such events and more (do they fire concurrently? can you block?)
Currently designing how this trivia game will work on multiple servers. I have 3 architectures in mind (Twitter can help me pick one, but I have a preferred one). Both clients are part of the same game. Games are ephemeral and last a maximum of 2 minutes.
Architecture 1 - Using Redis as the game state storage and SignalR backplane.
Architecture 2 - Use Orleans grains as the SignalR backplane and state storage for a game.