SlideShare a Scribd company logo
.NET Systems Programming
Learned the Hard Way
By Aaron Stannard (@Aaronontheweb)
CEO, Petabridge
Creator, Akka.NET
About Me
• .NET developer since 2005 (college
internship)
• Built large-scale SaaS on top of
.NET
• Creator and maintainer of
Akka.NET since 2013
• Canonical actor model
implementation in .NET
• Highly concurrent, low-latency, and
distributed
• Used to build mission-critical real
time applications
• Performance is a feature
Garbage Collection
Perf Loss, GC Modes, and GC Generations
.NET GC
Source: https://www.csharpstar.com/interview-questions-garbage-collection-csharp/
Compacted
memory
GC Generations
The higher the generation, the most expensive the GC:
• Memory is more fragmented (access is random, not contiguous)
• Compaction takes longer (bigger gaps, more stuff to move,
longer GC pauses)
.NET Memory Model
private readonly Random myRandom = Random.Shared;
private void DoThing()
{
var i = myRandom.Next();
var j = myRandom.Next(i);
var b = i + j;
var str = b.ToString();
Console.WriteLine(str);
}
Stack
0xAEDC DoThing_vtable
0xFFBD ref(Random.Shared)
0x11CD i = 10;
0x11CE j = 5;
0x11CF b = 15;
0xADDE ref(string)
Managed Heap
0xAEDC class Thing_DoThing mthd
0xFFBD Random.Shared [1024b]
…
…
…
0xADDE string “15”
GC Considerations
• If you can: keep allocations in Gen 0 / 1
• Value types (no GC)
• Less memory fragmentation, compaction
• Less impact on latency, throughput
• If you can’t: keep Gen 2 objects in Gen 2 forever
• No GC if they’re still rooted!
GC Practice: Object Pools
• Microsoft.Extensions.ObjectPool<T> - great option for
long-lived Gen2 objects
• Best candidates are “reusable” types
• StringBuilder
• byte[](there are separate MemoryPool types for this)
• Use pre-allocated object, return to pool upon completion
• Doesn’t cause allocations so long as pool capacity isn’t exceeded
GC Practice: Object Pools
StringBuilder sb = null;
try
{
sb = _sbPool.Get();
using (var tw = new StringWriter(sb, CultureInfo.InvariantCulture))
{
var ser = JsonSerializer.CreateDefault(Settings);
ser.Formatting = Formatting.None;
using (var jw = new JsonTextWriter(tw))
{
ser.Serialize(jw, obj);
}
return Encoding.UTF8.GetBytes(tw.ToString());
}
}
finally
{
if (sb != null)
{
_sbPool.Return(sb);
}
}
Rent an instance from the
ObjectPool<StringBuilder>
Do our work
Return to the pool
GC Practice: Object Pools
• Pooling StringBuilder inside Newtonsoft.Json
~30% memory savings,
eliminated 100% of Gen 1
GC
~28% throughput
improvement in concurrent
use cases
.NET GC Modes
Workstation GC vs. Server GC
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="....common.props" />
<PropertyGroup>
<Description>Akka.Remote x-plat performance benchmark</Description>
<Copyright>Copyright (c) Akka.NET Team</Copyright>
<AssemblyTitle>RemotePingPong</AssemblyTitle>
<AssemblyName>RemotePingPong</AssemblyName>
<Authors>Akka.NET Team</Authors>
<TargetFrameworks>$(NetFrameworkTestVersion);$(NetTestVersion);$(NetCoreTestVersion)</TargetFrameworks>
<OutputType>Exe</OutputType>
</PropertyGroup>
<PropertyGroup>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<PropertyGroup>
<ServerGarbageCollection>true</ServerGarbageCollection>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="....coreAkka.RemoteAkka.Remote.csproj" />
</ItemGroup>
</Project>
Not enabled by
default!
Workstation GC vs. Server GC
Workstation GC Server GC
Memory Allocations
Hidden Sources of Allocations and Eliminating Them
Allocations: Delegates and Closures
/// <summary>
/// Processes the contents of the mailbox
/// </summary>
public void Run()
{
try
{
if (!IsClosed()) // Volatile read, needed here
{
Actor.UseThreadContext(() =>
{
ProcessAllSystemMessages(); // First, deal with any system messages
ProcessMailbox(); // Then deal with messages
});
}
}
finally
{
SetAsIdle(); // Volatile write, needed here
Dispatcher.RegisterForExecution(this, false, false); // schedule to run again if there are more messages,
possibly
}
}
Critical path of actor msg
processing
Closes over ‘this’, allocates
delegate each time
Eliminate Delegate: Inlining
/// <summary>
/// Processes the contents of the mailbox
/// </summary>
public void Run()
{
try
{
if (!IsClosed()) // Volatile read, needed here
{
var tmp = InternalCurrentActorCellKeeper.Current;
InternalCurrentActorCellKeeper.Current = Actor;
try
{
ProcessAllSystemMessages(); // First, deal with any system messages
ProcessMailbox(); // Then deal with messages
}
finally
{
//ensure we set back the old context
InternalCurrentActorCellKeeper.Current = tmp;
}
}
}
finally
{
SetAsIdle(); // Volatile write, needed here
Dispatcher.RegisterForExecution(this, false, false); // schedule to run again if there are more messages, possibly
}
}
Eliminate delegate by inlining function
From 21kb & 203kb to ~1kb
Throughput improvement of ~10%
Other Delegate Allocation Removal Methods
• C#9: declare `static` delegates
• Cache delegates / use expression compiler
• ValueDelegates
Value Delegates
private readonly struct RequestWorkerTask : IRunnable
{
private readonly DedicatedThreadPoolTaskScheduler _scheduler;
public RequestWorkerTask(DedicatedThreadPoolTaskScheduler
scheduler)
{
_scheduler = scheduler;
}
public void Run()
{
// do work
}
}
private void RequestWorker()
{
_pool.QueueUserWorkItem(new RequestWorkerTask(this));
}
Implement our “delegate interface”
using a value type
Runs just the same as a reference
type
Execute the work (might cause a
boxing allocation!)
Allocations: “Empty” Collections
public State(TS stateName, TD stateData, TimeSpan? timeout = null, Reason stopReason = null, IReadOnlyList<object> replies = null, bool
notifies = true)
{
Replies = replies ?? new List<object>();
StopReason = stopReason;
Timeout = timeout;
StateData = stateData;
StateName = stateName;
Notifies = notifies;
}
Allocates a new,
non-empty array
(32 bytes)
Suspicious…
Allocations: “Empty” Collections
public State(TS stateName, TD stateData, TimeSpan? timeout = null, Reason stopReason = null, IReadOnlyList<object> replies = null, bool
notifies = true)
{
Replies = replies ?? Array.Empty<object>();
StopReason = stopReason;
Timeout = timeout;
StateData = stateData;
StateName = stateName;
Notifies = notifies;
}
Creates an empty, non-
null collection
Value Types
Not Always Preferable Over Reference Types
Reference Type: FSM Events
public sealed class Event<TD> : INoSerializationVerificationNeeded
{
public Event(object fsmEvent, TD stateData)
{
StateData = stateData;
FsmEvent = fsmEvent;
}
public object FsmEvent { get; }
public TD StateData { get; }
public override string ToString()
{
return $"Event: <{FsmEvent}>, StateData: <{StateData}>";
}
}
We allocate millions of these per
second in busy networks
public readonly struct Event<TD> : INoSerializationVerificationNeeded
{
public Event(object fsmEvent, TD stateData)
{
StateData = stateData;
FsmEvent = fsmEvent;
}
public object FsmEvent { get; }
public TD StateData { get; }
public override string ToString()
{
return $"Event: <{FsmEvent}>, StateData: <{StateData}>";
}
}
Value Type: FSM Events
Change to value type
Reduction of ~30mb
Minor throughput
improvement
Value Types: Boxing Allocations
• Boxing occurs implicitly – when a
struct is cast into an object
• The struct will be wrapped
into an object and placed on
the managed heap.
• Unboxing happens explicitly –
when the object is cast back
into its associated value type.
• Can create a lot of allocations!
StateName is usually an enum (value
type) – is the object.Equals call
boxing?
Value Types: Boxing Allocations
// avoid boxing
if (!EqualityComparer<TState>.Default.Equals(_currentState.StateName, nextState.StateName) || nextState.Notifies)
{
_nextState = nextState;
HandleTransition(_currentState.StateName, nextState.StateName);
Listeners.Gossip(new Transition<TState>(Self, _currentState.StateName, nextState.StateName));
_nextState = default;
}
Used generic comparer to avoid casting
value types into object – removed 100%
of boxing allocations at this callsite.
Value Type: Message Envelope
/// <summary>
/// Envelope class, represents a message and the sender of the message.
/// </summary>
public readonly struct Envelope
{
public Envelope(object message, IActorRef sender)
{
Message = message;
Sender = sender;
}
public IActorRef Sender { get; }
public object Message { get; }
}
Used millions of times per
second in Akka.NET
readonly struct? Value
type? Should be “zero
allocations”
Reference Type: Message Envelope
/// <summary>
/// Envelope class, represents a message and the sender of the message.
/// </summary>
public sealed class Envelope
{
public Envelope(object message, IActorRef sender)
{
Message = message;
Sender = sender;
}
public IActorRef Sender { get; }
public object Message { get; }
}
What if we change to a
reference type? Will this reduce
allocations?
394kb  264kb
3.15mb  2.1mb
215 us  147 us
1860 us  1332 us
Value Type Pitfalls
• Copy-by-Value
• References to value types in other scopes requires copying
• ref parameters can work, but in narrowly defined contexts
• Excessive copying can be more expensive than allocating a reference
• Use reference types when semantics are “referential”
• Value types are not magic – work best in “tight” scopes
• Use the right tool for the job
NET Systems Programming Learned the Hard Way.pptx
Reference Type: Message Envelope
• What happens when we benchmark with significantly increased
cross-thread message traffic?
• Now if we convert Envelope back into a struct again…
• Thread access makes a difference!
Threads, Memory,
Synchronization, and Pain
Threads Hate You and Your Code
ThreadStatic and ThreadLocal<T>
• Allocates objects directly into thread local storage
• Objects stay there and are available each time thread is used
• Ideal for caching and pooling
• No synchronization
• Data and work all performed adjacent to stack memory
• Downside: thread-local data structures aren’t synchronized
• Variants!
Thread Local Storage & Context Switching
• Reference types passed between
threads often age into older
generations of GC
• Value types passed between
threads are copied (no GC)
• Thread-local state is copied into
CPU’s L1/L2 cache from memory
typically during execution
• Context switching occurs when
threads get scheduled onto
different CPUs or work is moves
onto different threads.
Thread Locality & Context Switching
Each thread gets
~30ms of execution
time before yielding
Thread Locality & Context Switching
Current quantum is
over – time for
other threads to
have a turn
Thread Locality & Context Switching
Context switch! Thread
0 now executing on CPU
1 – memory and state
will have to be
transferred.
Context Switching: High Latency Impact
/// <summary>
/// An asynchronous operation will be executed by
a <see cref="MessageDispatcher"/>.
/// </summary>
#if NETSTANDARD
public interface IRunnable
#else
public interface IRunnable : IThreadPoolWorkItem
#endif
{
/// <summary>
/// Executes the task.
/// </summary>
void Run();
}
// use native .NET 6 APIs here to reduce
allocations
// preferLocal to help reduce context switching
ThreadPool.UnsafeQueueUserWorkItem(run,
true);
IThreadPoolWorkItem interface
added in .NET Core 3.0 – avoids delegate
allocations for executing on ThreadPool
Consume IThreadPoolWorkItem
with preferLocal=true – tells the
ThreadPool to attempt to reschedule
work on current thread / CPU.
Performance Comparison
Before After
~3x improvement
~50% improvement
Thread Locality w/o Context Switching
No context switch –
same thread will have a
chance to execute on
same CPU. Might be
able to benefit from
L1/L2 cache, locality of
memory access, etc.
Data Structures & Synchronization
/// <summary> An unbounded mailbox message queue. </summary>
public class UnboundedMessageQueue : IMessageQueue, IUnboundedMessageQueueSemantics
{
private readonly ConcurrentQueue<Envelope> _queue = new ConcurrentQueue<Envelope>();
/// <inheritdoc cref="IMessageQueue"/>
public bool HasMessages
{
get { return !_queue.IsEmpty; }
}
/// <inheritdoc cref="IMessageQueue"/>
public int Count
{
get { return _queue.Count; }
}
….
}
Could, in theory, improve
memory performance by
replacing with a LinkedList (no
array segment allocations from
resizing)
Data Structures & Synchronization
/// <summary> An unbounded mailbox message queue. </summary>
public class UnboundedMessageQueue : IMessageQueue, IUnboundedMessageQueueSemantics
{
private readonly object s_lock = new object();
private readonly LinkedList<Envelope> _linkedList = new LinkedList<Envelope>();
public bool HasMessages
{
get
{
return Count > 0;
}
}
public int Count
{
get
{
lock (s_lock)
{
return _linkedList.Count;
}
}
}
….
Not a thread-safe data
structure, has to be synced-
with lock
Should offer better memory
performance than
ConcurrentQueue<T>
Wooooooof 🤮
Data Structures & Synchronization
• What went wrong there?
• ConcurrentQueue<T> is lock-free
• Uses volatile and atomic compare-and-swap operations
• i.e. Interlocked.CompareExchange
• Significantly less expensive, even on a single thread, than lock
• LinkedList<T> may not be all that memory efficient
• Internal data structure allocations per-insert rather than array block
allocations
• Better off rolling your own, probably
Learn More
• https://getakka.net/ - Akka.NET website, Discord, and source
• https://aaronstannard.com/ - my blog
Ad

More Related Content

What's hot (20)

関数プログラミング入門
関数プログラミング入門関数プログラミング入門
関数プログラミング入門
Hideyuki Tanaka
 
Deep Dive async/await in Unity with UniTask(UniRx.Async)
Deep Dive async/await in Unity with UniTask(UniRx.Async)Deep Dive async/await in Unity with UniTask(UniRx.Async)
Deep Dive async/await in Unity with UniTask(UniRx.Async)
Yoshifumi Kawai
 
Osc2015北海道 札幌my sql勉強会_波多野_r3
Osc2015北海道 札幌my sql勉強会_波多野_r3Osc2015北海道 札幌my sql勉強会_波多野_r3
Osc2015北海道 札幌my sql勉強会_波多野_r3
Nobuhiro Hatano
 
関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐり関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐり
Kazuyuki TAKASE
 
HTTP/2で 速くなるとき ならないとき
HTTP/2で 速くなるとき ならないときHTTP/2で 速くなるとき ならないとき
HTTP/2で 速くなるとき ならないとき
Kazuho Oku
 
代数的実数とCADの実装紹介
代数的実数とCADの実装紹介代数的実数とCADの実装紹介
代数的実数とCADの実装紹介
Masahiro Sakai
 
SwiftのDI方法につい て最近考えてた話
SwiftのDI方法につい て最近考えてた話SwiftのDI方法につい て最近考えてた話
SwiftのDI方法につい て最近考えてた話
Yahoo!デベロッパーネットワーク
 
GitLab から GitLab に移行したときの思い出
GitLab から GitLab に移行したときの思い出GitLab から GitLab に移行したときの思い出
GitLab から GitLab に移行したときの思い出
富士通クラウドテクノロジーズ株式会社
 
Topology Managerについて / Kubernetes Meetup Tokyo 50
Topology Managerについて / Kubernetes Meetup Tokyo 50Topology Managerについて / Kubernetes Meetup Tokyo 50
Topology Managerについて / Kubernetes Meetup Tokyo 50
Preferred Networks
 
Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Domain Driven Design with the F# type System -- F#unctional Londoners 2014Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Scott Wlaschin
 
技術勉強会(楕円曲線暗号)資料
技術勉強会(楕円曲線暗号)資料技術勉強会(楕円曲線暗号)資料
技術勉強会(楕円曲線暗号)資料
Tetsuyuki Oishi
 
Apache Avro vs Protocol Buffers
Apache Avro vs Protocol BuffersApache Avro vs Protocol Buffers
Apache Avro vs Protocol Buffers
Seiya Mizuno
 
KafkaとPulsar
KafkaとPulsarKafkaとPulsar
KafkaとPulsar
Yahoo!デベロッパーネットワーク
 
FIDO認証によるパスワードレスログイン実装入門
FIDO認証によるパスワードレスログイン実装入門FIDO認証によるパスワードレスログイン実装入門
FIDO認証によるパスワードレスログイン実装入門
Yahoo!デベロッパーネットワーク
 
事例で学ぶApache Cassandra
事例で学ぶApache Cassandra事例で学ぶApache Cassandra
事例で学ぶApache Cassandra
Yuki Morishita
 
Reactを使ったYahoo!地図の技術刷新への挑戦 #yjbonfire
Reactを使ったYahoo!地図の技術刷新への挑戦 #yjbonfireReactを使ったYahoo!地図の技術刷新への挑戦 #yjbonfire
Reactを使ったYahoo!地図の技術刷新への挑戦 #yjbonfire
Yahoo!デベロッパーネットワーク
 
デザイン思考および周辺 - ユーザビリティ、UX、アジャイル開発を含めて-
デザイン思考および周辺 - ユーザビリティ、UX、アジャイル開発を含めて-デザイン思考および周辺 - ユーザビリティ、UX、アジャイル開発を含めて-
デザイン思考および周辺 - ユーザビリティ、UX、アジャイル開発を含めて-
Hironori Washizaki
 
Introduction to Rust language programming
Introduction to Rust language programmingIntroduction to Rust language programming
Introduction to Rust language programming
Rodolfo Finochietti
 
非同期処理の基礎
非同期処理の基礎非同期処理の基礎
非同期処理の基礎
信之 岩永
 
Rust で RTOS を考える
Rust で RTOS を考えるRust で RTOS を考える
Rust で RTOS を考える
ryuz88
 
関数プログラミング入門
関数プログラミング入門関数プログラミング入門
関数プログラミング入門
Hideyuki Tanaka
 
Deep Dive async/await in Unity with UniTask(UniRx.Async)
Deep Dive async/await in Unity with UniTask(UniRx.Async)Deep Dive async/await in Unity with UniTask(UniRx.Async)
Deep Dive async/await in Unity with UniTask(UniRx.Async)
Yoshifumi Kawai
 
Osc2015北海道 札幌my sql勉強会_波多野_r3
Osc2015北海道 札幌my sql勉強会_波多野_r3Osc2015北海道 札幌my sql勉強会_波多野_r3
Osc2015北海道 札幌my sql勉強会_波多野_r3
Nobuhiro Hatano
 
関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐり関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐり
Kazuyuki TAKASE
 
HTTP/2で 速くなるとき ならないとき
HTTP/2で 速くなるとき ならないときHTTP/2で 速くなるとき ならないとき
HTTP/2で 速くなるとき ならないとき
Kazuho Oku
 
代数的実数とCADの実装紹介
代数的実数とCADの実装紹介代数的実数とCADの実装紹介
代数的実数とCADの実装紹介
Masahiro Sakai
 
Topology Managerについて / Kubernetes Meetup Tokyo 50
Topology Managerについて / Kubernetes Meetup Tokyo 50Topology Managerについて / Kubernetes Meetup Tokyo 50
Topology Managerについて / Kubernetes Meetup Tokyo 50
Preferred Networks
 
Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Domain Driven Design with the F# type System -- F#unctional Londoners 2014Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Scott Wlaschin
 
技術勉強会(楕円曲線暗号)資料
技術勉強会(楕円曲線暗号)資料技術勉強会(楕円曲線暗号)資料
技術勉強会(楕円曲線暗号)資料
Tetsuyuki Oishi
 
Apache Avro vs Protocol Buffers
Apache Avro vs Protocol BuffersApache Avro vs Protocol Buffers
Apache Avro vs Protocol Buffers
Seiya Mizuno
 
事例で学ぶApache Cassandra
事例で学ぶApache Cassandra事例で学ぶApache Cassandra
事例で学ぶApache Cassandra
Yuki Morishita
 
デザイン思考および周辺 - ユーザビリティ、UX、アジャイル開発を含めて-
デザイン思考および周辺 - ユーザビリティ、UX、アジャイル開発を含めて-デザイン思考および周辺 - ユーザビリティ、UX、アジャイル開発を含めて-
デザイン思考および周辺 - ユーザビリティ、UX、アジャイル開発を含めて-
Hironori Washizaki
 
Introduction to Rust language programming
Introduction to Rust language programmingIntroduction to Rust language programming
Introduction to Rust language programming
Rodolfo Finochietti
 
非同期処理の基礎
非同期処理の基礎非同期処理の基礎
非同期処理の基礎
信之 岩永
 
Rust で RTOS を考える
Rust で RTOS を考えるRust で RTOS を考える
Rust で RTOS を考える
ryuz88
 

Similar to NET Systems Programming Learned the Hard Way.pptx (20)

Lambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter LawreyLambdas puzzler - Peter Lawrey
Lambdas puzzler - Peter Lawrey
JAXLondon_Conference
 
Kerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-Malla
Kerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-MallaKerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-Malla
Kerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-Malla
Spark Summit
 
.NET Multithreading/Multitasking
.NET Multithreading/Multitasking.NET Multithreading/Multitasking
.NET Multithreading/Multitasking
Sasha Kravchuk
 
Hadoop Integration in Cassandra
Hadoop Integration in CassandraHadoop Integration in Cassandra
Hadoop Integration in Cassandra
Jairam Chandar
 
A New Chapter of Data Processing with CDK
A New Chapter of Data Processing with CDKA New Chapter of Data Processing with CDK
A New Chapter of Data Processing with CDK
Shu-Jeng Hsieh
 
Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New Tricks
MongoDB
 
Hazelcast and MongoDB at Cloud CMS
Hazelcast and MongoDB at Cloud CMSHazelcast and MongoDB at Cloud CMS
Hazelcast and MongoDB at Cloud CMS
uzquiano
 
Kerberizing spark. Spark Summit east
Kerberizing spark. Spark Summit eastKerberizing spark. Spark Summit east
Kerberizing spark. Spark Summit east
Jorge Lopez-Malla
 
Shooting the Rapids
Shooting the RapidsShooting the Rapids
Shooting the Rapids
Maurice Naftalin
 
Dragoncraft Architectural Overview
Dragoncraft Architectural OverviewDragoncraft Architectural Overview
Dragoncraft Architectural Overview
jessesanford
 
Beyond Map/Reduce: Getting Creative With Parallel Processing
Beyond Map/Reduce: Getting Creative With Parallel ProcessingBeyond Map/Reduce: Getting Creative With Parallel Processing
Beyond Map/Reduce: Getting Creative With Parallel Processing
Ed Kohlwey
 
Scope Stack Allocation
Scope Stack AllocationScope Stack Allocation
Scope Stack Allocation
Electronic Arts / DICE
 
Kappa Architecture on Apache Kafka and Querona: datamass.io
Kappa Architecture on Apache Kafka and Querona: datamass.ioKappa Architecture on Apache Kafka and Querona: datamass.io
Kappa Architecture on Apache Kafka and Querona: datamass.io
Piotr Czarnas
 
Real-Time Spark: From Interactive Queries to Streaming
Real-Time Spark: From Interactive Queries to StreamingReal-Time Spark: From Interactive Queries to Streaming
Real-Time Spark: From Interactive Queries to Streaming
Databricks
 
NoSQL Endgame DevoxxUA Conference 2020
NoSQL Endgame DevoxxUA Conference 2020NoSQL Endgame DevoxxUA Conference 2020
NoSQL Endgame DevoxxUA Conference 2020
Thodoris Bais
 
4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)
4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)
4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)
PROIDEA
 
Data Pipeline at Tapad
Data Pipeline at TapadData Pipeline at Tapad
Data Pipeline at Tapad
Toby Matejovsky
 
New Features Of JDK 7
New Features Of JDK 7New Features Of JDK 7
New Features Of JDK 7
Deniz Oguz
 
Server side JavaScript: going all the way
Server side JavaScript: going all the wayServer side JavaScript: going all the way
Server side JavaScript: going all the way
Oleg Podsechin
 
Real-Time Streaming with Apache Spark Streaming and Apache Storm
Real-Time Streaming with Apache Spark Streaming and Apache StormReal-Time Streaming with Apache Spark Streaming and Apache Storm
Real-Time Streaming with Apache Spark Streaming and Apache Storm
Davorin Vukelic
 
Kerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-Malla
Kerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-MallaKerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-Malla
Kerberizing Spark: Spark Summit East talk by Abel Rincon and Jorge Lopez-Malla
Spark Summit
 
.NET Multithreading/Multitasking
.NET Multithreading/Multitasking.NET Multithreading/Multitasking
.NET Multithreading/Multitasking
Sasha Kravchuk
 
Hadoop Integration in Cassandra
Hadoop Integration in CassandraHadoop Integration in Cassandra
Hadoop Integration in Cassandra
Jairam Chandar
 
A New Chapter of Data Processing with CDK
A New Chapter of Data Processing with CDKA New Chapter of Data Processing with CDK
A New Chapter of Data Processing with CDK
Shu-Jeng Hsieh
 
Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New Tricks
MongoDB
 
Hazelcast and MongoDB at Cloud CMS
Hazelcast and MongoDB at Cloud CMSHazelcast and MongoDB at Cloud CMS
Hazelcast and MongoDB at Cloud CMS
uzquiano
 
Kerberizing spark. Spark Summit east
Kerberizing spark. Spark Summit eastKerberizing spark. Spark Summit east
Kerberizing spark. Spark Summit east
Jorge Lopez-Malla
 
Dragoncraft Architectural Overview
Dragoncraft Architectural OverviewDragoncraft Architectural Overview
Dragoncraft Architectural Overview
jessesanford
 
Beyond Map/Reduce: Getting Creative With Parallel Processing
Beyond Map/Reduce: Getting Creative With Parallel ProcessingBeyond Map/Reduce: Getting Creative With Parallel Processing
Beyond Map/Reduce: Getting Creative With Parallel Processing
Ed Kohlwey
 
Kappa Architecture on Apache Kafka and Querona: datamass.io
Kappa Architecture on Apache Kafka and Querona: datamass.ioKappa Architecture on Apache Kafka and Querona: datamass.io
Kappa Architecture on Apache Kafka and Querona: datamass.io
Piotr Czarnas
 
Real-Time Spark: From Interactive Queries to Streaming
Real-Time Spark: From Interactive Queries to StreamingReal-Time Spark: From Interactive Queries to Streaming
Real-Time Spark: From Interactive Queries to Streaming
Databricks
 
NoSQL Endgame DevoxxUA Conference 2020
NoSQL Endgame DevoxxUA Conference 2020NoSQL Endgame DevoxxUA Conference 2020
NoSQL Endgame DevoxxUA Conference 2020
Thodoris Bais
 
4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)
4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)
4Developers 2018: Ile (nie) wiesz o strukturach w .NET (Łukasz Pyrzyk)
PROIDEA
 
New Features Of JDK 7
New Features Of JDK 7New Features Of JDK 7
New Features Of JDK 7
Deniz Oguz
 
Server side JavaScript: going all the way
Server side JavaScript: going all the wayServer side JavaScript: going all the way
Server side JavaScript: going all the way
Oleg Podsechin
 
Real-Time Streaming with Apache Spark Streaming and Apache Storm
Real-Time Streaming with Apache Spark Streaming and Apache StormReal-Time Streaming with Apache Spark Streaming and Apache Storm
Real-Time Streaming with Apache Spark Streaming and Apache Storm
Davorin Vukelic
 
Ad

More from petabridge (20)

Diagnosing Production Akka.NET Problems with OpenTelemetry.pptx
Diagnosing Production Akka.NET Problems with OpenTelemetry.pptxDiagnosing Production Akka.NET Problems with OpenTelemetry.pptx
Diagnosing Production Akka.NET Problems with OpenTelemetry.pptx
petabridge
 
Leveraging AI for Software Developer Productivity.pptx
Leveraging AI for Software Developer Productivity.pptxLeveraging AI for Software Developer Productivity.pptx
Leveraging AI for Software Developer Productivity.pptx
petabridge
 
DotNext 2020 - When and How to Use the Actor Model and Akka.NET
DotNext 2020 - When and How to Use the Actor Model and Akka.NETDotNext 2020 - When and How to Use the Actor Model and Akka.NET
DotNext 2020 - When and How to Use the Actor Model and Akka.NET
petabridge
 
.NET Conf 2019 When and How to Use the Actor Model: an Introduction to Akka...
.NET Conf 2019   When and How to Use the Actor Model: an Introduction to Akka....NET Conf 2019   When and How to Use the Actor Model: an Introduction to Akka...
.NET Conf 2019 When and How to Use the Actor Model: an Introduction to Akka...
petabridge
 
Continuous Deployment with Akka.Cluster and Kubernetes (Akka.NET)
Continuous Deployment with Akka.Cluster and Kubernetes (Akka.NET)Continuous Deployment with Akka.Cluster and Kubernetes (Akka.NET)
Continuous Deployment with Akka.Cluster and Kubernetes (Akka.NET)
petabridge
 
Introduction to Distributed Tracing
Introduction to Distributed TracingIntroduction to Distributed Tracing
Introduction to Distributed Tracing
petabridge
 
Akka.NET: Concurrency without the Pain
Akka.NET: Concurrency without the PainAkka.NET: Concurrency without the Pain
Akka.NET: Concurrency without the Pain
petabridge
 
Introduction to Akka.NET and Akka.Cluster
Introduction to Akka.NET and Akka.ClusterIntroduction to Akka.NET and Akka.Cluster
Introduction to Akka.NET and Akka.Cluster
petabridge
 
Automed .NET Performance Testing with NBench
Automed .NET Performance Testing with NBenchAutomed .NET Performance Testing with NBench
Automed .NET Performance Testing with NBench
petabridge
 
We're all distributed systems devs now: a crash course in distributed program...
We're all distributed systems devs now: a crash course in distributed program...We're all distributed systems devs now: a crash course in distributed program...
We're all distributed systems devs now: a crash course in distributed program...
petabridge
 
The New .NET Enterprise Stack
The New .NET Enterprise StackThe New .NET Enterprise Stack
The New .NET Enterprise Stack
petabridge
 
Full-Stack, Message-oriented Programming w/ Akka.NET Actors
Full-Stack, Message-oriented Programming w/ Akka.NET ActorsFull-Stack, Message-oriented Programming w/ Akka.NET Actors
Full-Stack, Message-oriented Programming w/ Akka.NET Actors
petabridge
 
OSS From the Outside In - A Personal Journey With Akka.NET
OSS From the Outside In - A Personal Journey With Akka.NETOSS From the Outside In - A Personal Journey With Akka.NET
OSS From the Outside In - A Personal Journey With Akka.NET
petabridge
 
Concurrency, Without the Pain: An Intro to Akka.NET @ Bay.NET
Concurrency, Without the Pain: An Intro to Akka.NET @ Bay.NETConcurrency, Without the Pain: An Intro to Akka.NET @ Bay.NET
Concurrency, Without the Pain: An Intro to Akka.NET @ Bay.NET
petabridge
 
Syncromatics Akka.NET Case Study
Syncromatics Akka.NET Case StudySyncromatics Akka.NET Case Study
Syncromatics Akka.NET Case Study
petabridge
 
Akka.NET @ London.NET
Akka.NET @ London.NETAkka.NET @ London.NET
Akka.NET @ London.NET
petabridge
 
Akka.NET Fundamentals — #ProgNet15
Akka.NET Fundamentals — #ProgNet15Akka.NET Fundamentals — #ProgNet15
Akka.NET Fundamentals — #ProgNet15
petabridge
 
Slides - Intro to Akka.Cluster
Slides - Intro to Akka.ClusterSlides - Intro to Akka.Cluster
Slides - Intro to Akka.Cluster
petabridge
 
Akka.NET: Concurrency Without the Pain (Intro to the Actor Model)
Akka.NET: Concurrency Without the Pain (Intro to the Actor Model)Akka.NET: Concurrency Without the Pain (Intro to the Actor Model)
Akka.NET: Concurrency Without the Pain (Intro to the Actor Model)
petabridge
 
Distributed Transactions in Akka.NET
Distributed Transactions in Akka.NETDistributed Transactions in Akka.NET
Distributed Transactions in Akka.NET
petabridge
 
Diagnosing Production Akka.NET Problems with OpenTelemetry.pptx
Diagnosing Production Akka.NET Problems with OpenTelemetry.pptxDiagnosing Production Akka.NET Problems with OpenTelemetry.pptx
Diagnosing Production Akka.NET Problems with OpenTelemetry.pptx
petabridge
 
Leveraging AI for Software Developer Productivity.pptx
Leveraging AI for Software Developer Productivity.pptxLeveraging AI for Software Developer Productivity.pptx
Leveraging AI for Software Developer Productivity.pptx
petabridge
 
DotNext 2020 - When and How to Use the Actor Model and Akka.NET
DotNext 2020 - When and How to Use the Actor Model and Akka.NETDotNext 2020 - When and How to Use the Actor Model and Akka.NET
DotNext 2020 - When and How to Use the Actor Model and Akka.NET
petabridge
 
.NET Conf 2019 When and How to Use the Actor Model: an Introduction to Akka...
.NET Conf 2019   When and How to Use the Actor Model: an Introduction to Akka....NET Conf 2019   When and How to Use the Actor Model: an Introduction to Akka...
.NET Conf 2019 When and How to Use the Actor Model: an Introduction to Akka...
petabridge
 
Continuous Deployment with Akka.Cluster and Kubernetes (Akka.NET)
Continuous Deployment with Akka.Cluster and Kubernetes (Akka.NET)Continuous Deployment with Akka.Cluster and Kubernetes (Akka.NET)
Continuous Deployment with Akka.Cluster and Kubernetes (Akka.NET)
petabridge
 
Introduction to Distributed Tracing
Introduction to Distributed TracingIntroduction to Distributed Tracing
Introduction to Distributed Tracing
petabridge
 
Akka.NET: Concurrency without the Pain
Akka.NET: Concurrency without the PainAkka.NET: Concurrency without the Pain
Akka.NET: Concurrency without the Pain
petabridge
 
Introduction to Akka.NET and Akka.Cluster
Introduction to Akka.NET and Akka.ClusterIntroduction to Akka.NET and Akka.Cluster
Introduction to Akka.NET and Akka.Cluster
petabridge
 
Automed .NET Performance Testing with NBench
Automed .NET Performance Testing with NBenchAutomed .NET Performance Testing with NBench
Automed .NET Performance Testing with NBench
petabridge
 
We're all distributed systems devs now: a crash course in distributed program...
We're all distributed systems devs now: a crash course in distributed program...We're all distributed systems devs now: a crash course in distributed program...
We're all distributed systems devs now: a crash course in distributed program...
petabridge
 
The New .NET Enterprise Stack
The New .NET Enterprise StackThe New .NET Enterprise Stack
The New .NET Enterprise Stack
petabridge
 
Full-Stack, Message-oriented Programming w/ Akka.NET Actors
Full-Stack, Message-oriented Programming w/ Akka.NET ActorsFull-Stack, Message-oriented Programming w/ Akka.NET Actors
Full-Stack, Message-oriented Programming w/ Akka.NET Actors
petabridge
 
OSS From the Outside In - A Personal Journey With Akka.NET
OSS From the Outside In - A Personal Journey With Akka.NETOSS From the Outside In - A Personal Journey With Akka.NET
OSS From the Outside In - A Personal Journey With Akka.NET
petabridge
 
Concurrency, Without the Pain: An Intro to Akka.NET @ Bay.NET
Concurrency, Without the Pain: An Intro to Akka.NET @ Bay.NETConcurrency, Without the Pain: An Intro to Akka.NET @ Bay.NET
Concurrency, Without the Pain: An Intro to Akka.NET @ Bay.NET
petabridge
 
Syncromatics Akka.NET Case Study
Syncromatics Akka.NET Case StudySyncromatics Akka.NET Case Study
Syncromatics Akka.NET Case Study
petabridge
 
Akka.NET @ London.NET
Akka.NET @ London.NETAkka.NET @ London.NET
Akka.NET @ London.NET
petabridge
 
Akka.NET Fundamentals — #ProgNet15
Akka.NET Fundamentals — #ProgNet15Akka.NET Fundamentals — #ProgNet15
Akka.NET Fundamentals — #ProgNet15
petabridge
 
Slides - Intro to Akka.Cluster
Slides - Intro to Akka.ClusterSlides - Intro to Akka.Cluster
Slides - Intro to Akka.Cluster
petabridge
 
Akka.NET: Concurrency Without the Pain (Intro to the Actor Model)
Akka.NET: Concurrency Without the Pain (Intro to the Actor Model)Akka.NET: Concurrency Without the Pain (Intro to the Actor Model)
Akka.NET: Concurrency Without the Pain (Intro to the Actor Model)
petabridge
 
Distributed Transactions in Akka.NET
Distributed Transactions in Akka.NETDistributed Transactions in Akka.NET
Distributed Transactions in Akka.NET
petabridge
 
Ad

Recently uploaded (20)

HCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-UmgebungenHCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
panagenda
 
How analogue intelligence complements AI
How analogue intelligence complements AIHow analogue intelligence complements AI
How analogue intelligence complements AI
Paul Rowe
 
AI EngineHost Review: Revolutionary USA Datacenter-Based Hosting with NVIDIA ...
AI EngineHost Review: Revolutionary USA Datacenter-Based Hosting with NVIDIA ...AI EngineHost Review: Revolutionary USA Datacenter-Based Hosting with NVIDIA ...
AI EngineHost Review: Revolutionary USA Datacenter-Based Hosting with NVIDIA ...
SOFTTECHHUB
 
Generative Artificial Intelligence (GenAI) in Business
Generative Artificial Intelligence (GenAI) in BusinessGenerative Artificial Intelligence (GenAI) in Business
Generative Artificial Intelligence (GenAI) in Business
Dr. Tathagat Varma
 
Build Your Own Copilot & Agents For Devs
Build Your Own Copilot & Agents For DevsBuild Your Own Copilot & Agents For Devs
Build Your Own Copilot & Agents For Devs
Brian McKeiver
 
Dev Dives: Automate and orchestrate your processes with UiPath Maestro
Dev Dives: Automate and orchestrate your processes with UiPath MaestroDev Dives: Automate and orchestrate your processes with UiPath Maestro
Dev Dives: Automate and orchestrate your processes with UiPath Maestro
UiPathCommunity
 
AI and Data Privacy in 2025: Global Trends
AI and Data Privacy in 2025: Global TrendsAI and Data Privacy in 2025: Global Trends
AI and Data Privacy in 2025: Global Trends
InData Labs
 
Complete Guide to Advanced Logistics Management Software in Riyadh.pdf
Complete Guide to Advanced Logistics Management Software in Riyadh.pdfComplete Guide to Advanced Logistics Management Software in Riyadh.pdf
Complete Guide to Advanced Logistics Management Software in Riyadh.pdf
Software Company
 
Quantum Computing Quick Research Guide by Arthur Morgan
Quantum Computing Quick Research Guide by Arthur MorganQuantum Computing Quick Research Guide by Arthur Morgan
Quantum Computing Quick Research Guide by Arthur Morgan
Arthur Morgan
 
What is Model Context Protocol(MCP) - The new technology for communication bw...
What is Model Context Protocol(MCP) - The new technology for communication bw...What is Model Context Protocol(MCP) - The new technology for communication bw...
What is Model Context Protocol(MCP) - The new technology for communication bw...
Vishnu Singh Chundawat
 
Technology Trends in 2025: AI and Big Data Analytics
Technology Trends in 2025: AI and Big Data AnalyticsTechnology Trends in 2025: AI and Big Data Analytics
Technology Trends in 2025: AI and Big Data Analytics
InData Labs
 
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
BookNet Canada
 
Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.
hpbmnnxrvb
 
Special Meetup Edition - TDX Bengaluru Meetup #52.pptx
Special Meetup Edition - TDX Bengaluru Meetup #52.pptxSpecial Meetup Edition - TDX Bengaluru Meetup #52.pptx
Special Meetup Edition - TDX Bengaluru Meetup #52.pptx
shyamraj55
 
Procurement Insights Cost To Value Guide.pptx
Procurement Insights Cost To Value Guide.pptxProcurement Insights Cost To Value Guide.pptx
Procurement Insights Cost To Value Guide.pptx
Jon Hansen
 
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptxDevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
Justin Reock
 
Into The Box Conference Keynote Day 1 (ITB2025)
Into The Box Conference Keynote Day 1 (ITB2025)Into The Box Conference Keynote Day 1 (ITB2025)
Into The Box Conference Keynote Day 1 (ITB2025)
Ortus Solutions, Corp
 
TrsLabs - Fintech Product & Business Consulting
TrsLabs - Fintech Product & Business ConsultingTrsLabs - Fintech Product & Business Consulting
TrsLabs - Fintech Product & Business Consulting
Trs Labs
 
Electronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploitElectronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploit
niftliyevhuseyn
 
How Can I use the AI Hype in my Business Context?
How Can I use the AI Hype in my Business Context?How Can I use the AI Hype in my Business Context?
How Can I use the AI Hype in my Business Context?
Daniel Lehner
 
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-UmgebungenHCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
panagenda
 
How analogue intelligence complements AI
How analogue intelligence complements AIHow analogue intelligence complements AI
How analogue intelligence complements AI
Paul Rowe
 
AI EngineHost Review: Revolutionary USA Datacenter-Based Hosting with NVIDIA ...
AI EngineHost Review: Revolutionary USA Datacenter-Based Hosting with NVIDIA ...AI EngineHost Review: Revolutionary USA Datacenter-Based Hosting with NVIDIA ...
AI EngineHost Review: Revolutionary USA Datacenter-Based Hosting with NVIDIA ...
SOFTTECHHUB
 
Generative Artificial Intelligence (GenAI) in Business
Generative Artificial Intelligence (GenAI) in BusinessGenerative Artificial Intelligence (GenAI) in Business
Generative Artificial Intelligence (GenAI) in Business
Dr. Tathagat Varma
 
Build Your Own Copilot & Agents For Devs
Build Your Own Copilot & Agents For DevsBuild Your Own Copilot & Agents For Devs
Build Your Own Copilot & Agents For Devs
Brian McKeiver
 
Dev Dives: Automate and orchestrate your processes with UiPath Maestro
Dev Dives: Automate and orchestrate your processes with UiPath MaestroDev Dives: Automate and orchestrate your processes with UiPath Maestro
Dev Dives: Automate and orchestrate your processes with UiPath Maestro
UiPathCommunity
 
AI and Data Privacy in 2025: Global Trends
AI and Data Privacy in 2025: Global TrendsAI and Data Privacy in 2025: Global Trends
AI and Data Privacy in 2025: Global Trends
InData Labs
 
Complete Guide to Advanced Logistics Management Software in Riyadh.pdf
Complete Guide to Advanced Logistics Management Software in Riyadh.pdfComplete Guide to Advanced Logistics Management Software in Riyadh.pdf
Complete Guide to Advanced Logistics Management Software in Riyadh.pdf
Software Company
 
Quantum Computing Quick Research Guide by Arthur Morgan
Quantum Computing Quick Research Guide by Arthur MorganQuantum Computing Quick Research Guide by Arthur Morgan
Quantum Computing Quick Research Guide by Arthur Morgan
Arthur Morgan
 
What is Model Context Protocol(MCP) - The new technology for communication bw...
What is Model Context Protocol(MCP) - The new technology for communication bw...What is Model Context Protocol(MCP) - The new technology for communication bw...
What is Model Context Protocol(MCP) - The new technology for communication bw...
Vishnu Singh Chundawat
 
Technology Trends in 2025: AI and Big Data Analytics
Technology Trends in 2025: AI and Big Data AnalyticsTechnology Trends in 2025: AI and Big Data Analytics
Technology Trends in 2025: AI and Big Data Analytics
InData Labs
 
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
BookNet Canada
 
Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.Greenhouse_Monitoring_Presentation.pptx.
Greenhouse_Monitoring_Presentation.pptx.
hpbmnnxrvb
 
Special Meetup Edition - TDX Bengaluru Meetup #52.pptx
Special Meetup Edition - TDX Bengaluru Meetup #52.pptxSpecial Meetup Edition - TDX Bengaluru Meetup #52.pptx
Special Meetup Edition - TDX Bengaluru Meetup #52.pptx
shyamraj55
 
Procurement Insights Cost To Value Guide.pptx
Procurement Insights Cost To Value Guide.pptxProcurement Insights Cost To Value Guide.pptx
Procurement Insights Cost To Value Guide.pptx
Jon Hansen
 
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptxDevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
DevOpsDays Atlanta 2025 - Building 10x Development Organizations.pptx
Justin Reock
 
Into The Box Conference Keynote Day 1 (ITB2025)
Into The Box Conference Keynote Day 1 (ITB2025)Into The Box Conference Keynote Day 1 (ITB2025)
Into The Box Conference Keynote Day 1 (ITB2025)
Ortus Solutions, Corp
 
TrsLabs - Fintech Product & Business Consulting
TrsLabs - Fintech Product & Business ConsultingTrsLabs - Fintech Product & Business Consulting
TrsLabs - Fintech Product & Business Consulting
Trs Labs
 
Electronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploitElectronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploit
niftliyevhuseyn
 
How Can I use the AI Hype in my Business Context?
How Can I use the AI Hype in my Business Context?How Can I use the AI Hype in my Business Context?
How Can I use the AI Hype in my Business Context?
Daniel Lehner
 

NET Systems Programming Learned the Hard Way.pptx

  • 1. .NET Systems Programming Learned the Hard Way By Aaron Stannard (@Aaronontheweb) CEO, Petabridge Creator, Akka.NET
  • 2. About Me • .NET developer since 2005 (college internship) • Built large-scale SaaS on top of .NET • Creator and maintainer of Akka.NET since 2013 • Canonical actor model implementation in .NET • Highly concurrent, low-latency, and distributed • Used to build mission-critical real time applications • Performance is a feature
  • 3. Garbage Collection Perf Loss, GC Modes, and GC Generations
  • 5. GC Generations The higher the generation, the most expensive the GC: • Memory is more fragmented (access is random, not contiguous) • Compaction takes longer (bigger gaps, more stuff to move, longer GC pauses)
  • 6. .NET Memory Model private readonly Random myRandom = Random.Shared; private void DoThing() { var i = myRandom.Next(); var j = myRandom.Next(i); var b = i + j; var str = b.ToString(); Console.WriteLine(str); } Stack 0xAEDC DoThing_vtable 0xFFBD ref(Random.Shared) 0x11CD i = 10; 0x11CE j = 5; 0x11CF b = 15; 0xADDE ref(string) Managed Heap 0xAEDC class Thing_DoThing mthd 0xFFBD Random.Shared [1024b] … … … 0xADDE string “15”
  • 7. GC Considerations • If you can: keep allocations in Gen 0 / 1 • Value types (no GC) • Less memory fragmentation, compaction • Less impact on latency, throughput • If you can’t: keep Gen 2 objects in Gen 2 forever • No GC if they’re still rooted!
  • 8. GC Practice: Object Pools • Microsoft.Extensions.ObjectPool<T> - great option for long-lived Gen2 objects • Best candidates are “reusable” types • StringBuilder • byte[](there are separate MemoryPool types for this) • Use pre-allocated object, return to pool upon completion • Doesn’t cause allocations so long as pool capacity isn’t exceeded
  • 9. GC Practice: Object Pools StringBuilder sb = null; try { sb = _sbPool.Get(); using (var tw = new StringWriter(sb, CultureInfo.InvariantCulture)) { var ser = JsonSerializer.CreateDefault(Settings); ser.Formatting = Formatting.None; using (var jw = new JsonTextWriter(tw)) { ser.Serialize(jw, obj); } return Encoding.UTF8.GetBytes(tw.ToString()); } } finally { if (sb != null) { _sbPool.Return(sb); } } Rent an instance from the ObjectPool<StringBuilder> Do our work Return to the pool
  • 10. GC Practice: Object Pools • Pooling StringBuilder inside Newtonsoft.Json ~30% memory savings, eliminated 100% of Gen 1 GC ~28% throughput improvement in concurrent use cases
  • 12. Workstation GC vs. Server GC <Project Sdk="Microsoft.NET.Sdk"> <Import Project="....common.props" /> <PropertyGroup> <Description>Akka.Remote x-plat performance benchmark</Description> <Copyright>Copyright (c) Akka.NET Team</Copyright> <AssemblyTitle>RemotePingPong</AssemblyTitle> <AssemblyName>RemotePingPong</AssemblyName> <Authors>Akka.NET Team</Authors> <TargetFrameworks>$(NetFrameworkTestVersion);$(NetTestVersion);$(NetCoreTestVersion)</TargetFrameworks> <OutputType>Exe</OutputType> </PropertyGroup> <PropertyGroup> <PlatformTarget>x64</PlatformTarget> </PropertyGroup> <PropertyGroup> <ServerGarbageCollection>true</ServerGarbageCollection> </PropertyGroup> <ItemGroup> <ProjectReference Include="....coreAkka.RemoteAkka.Remote.csproj" /> </ItemGroup> </Project> Not enabled by default!
  • 13. Workstation GC vs. Server GC Workstation GC Server GC
  • 14. Memory Allocations Hidden Sources of Allocations and Eliminating Them
  • 15. Allocations: Delegates and Closures /// <summary> /// Processes the contents of the mailbox /// </summary> public void Run() { try { if (!IsClosed()) // Volatile read, needed here { Actor.UseThreadContext(() => { ProcessAllSystemMessages(); // First, deal with any system messages ProcessMailbox(); // Then deal with messages }); } } finally { SetAsIdle(); // Volatile write, needed here Dispatcher.RegisterForExecution(this, false, false); // schedule to run again if there are more messages, possibly } } Critical path of actor msg processing Closes over ‘this’, allocates delegate each time
  • 16. Eliminate Delegate: Inlining /// <summary> /// Processes the contents of the mailbox /// </summary> public void Run() { try { if (!IsClosed()) // Volatile read, needed here { var tmp = InternalCurrentActorCellKeeper.Current; InternalCurrentActorCellKeeper.Current = Actor; try { ProcessAllSystemMessages(); // First, deal with any system messages ProcessMailbox(); // Then deal with messages } finally { //ensure we set back the old context InternalCurrentActorCellKeeper.Current = tmp; } } } finally { SetAsIdle(); // Volatile write, needed here Dispatcher.RegisterForExecution(this, false, false); // schedule to run again if there are more messages, possibly } } Eliminate delegate by inlining function From 21kb & 203kb to ~1kb Throughput improvement of ~10%
  • 17. Other Delegate Allocation Removal Methods • C#9: declare `static` delegates • Cache delegates / use expression compiler • ValueDelegates
  • 18. Value Delegates private readonly struct RequestWorkerTask : IRunnable { private readonly DedicatedThreadPoolTaskScheduler _scheduler; public RequestWorkerTask(DedicatedThreadPoolTaskScheduler scheduler) { _scheduler = scheduler; } public void Run() { // do work } } private void RequestWorker() { _pool.QueueUserWorkItem(new RequestWorkerTask(this)); } Implement our “delegate interface” using a value type Runs just the same as a reference type Execute the work (might cause a boxing allocation!)
  • 19. Allocations: “Empty” Collections public State(TS stateName, TD stateData, TimeSpan? timeout = null, Reason stopReason = null, IReadOnlyList<object> replies = null, bool notifies = true) { Replies = replies ?? new List<object>(); StopReason = stopReason; Timeout = timeout; StateData = stateData; StateName = stateName; Notifies = notifies; } Allocates a new, non-empty array (32 bytes) Suspicious…
  • 20. Allocations: “Empty” Collections public State(TS stateName, TD stateData, TimeSpan? timeout = null, Reason stopReason = null, IReadOnlyList<object> replies = null, bool notifies = true) { Replies = replies ?? Array.Empty<object>(); StopReason = stopReason; Timeout = timeout; StateData = stateData; StateName = stateName; Notifies = notifies; } Creates an empty, non- null collection
  • 21. Value Types Not Always Preferable Over Reference Types
  • 22. Reference Type: FSM Events public sealed class Event<TD> : INoSerializationVerificationNeeded { public Event(object fsmEvent, TD stateData) { StateData = stateData; FsmEvent = fsmEvent; } public object FsmEvent { get; } public TD StateData { get; } public override string ToString() { return $"Event: <{FsmEvent}>, StateData: <{StateData}>"; } } We allocate millions of these per second in busy networks
  • 23. public readonly struct Event<TD> : INoSerializationVerificationNeeded { public Event(object fsmEvent, TD stateData) { StateData = stateData; FsmEvent = fsmEvent; } public object FsmEvent { get; } public TD StateData { get; } public override string ToString() { return $"Event: <{FsmEvent}>, StateData: <{StateData}>"; } } Value Type: FSM Events Change to value type Reduction of ~30mb Minor throughput improvement
  • 24. Value Types: Boxing Allocations • Boxing occurs implicitly – when a struct is cast into an object • The struct will be wrapped into an object and placed on the managed heap. • Unboxing happens explicitly – when the object is cast back into its associated value type. • Can create a lot of allocations! StateName is usually an enum (value type) – is the object.Equals call boxing?
  • 25. Value Types: Boxing Allocations // avoid boxing if (!EqualityComparer<TState>.Default.Equals(_currentState.StateName, nextState.StateName) || nextState.Notifies) { _nextState = nextState; HandleTransition(_currentState.StateName, nextState.StateName); Listeners.Gossip(new Transition<TState>(Self, _currentState.StateName, nextState.StateName)); _nextState = default; } Used generic comparer to avoid casting value types into object – removed 100% of boxing allocations at this callsite.
  • 26. Value Type: Message Envelope /// <summary> /// Envelope class, represents a message and the sender of the message. /// </summary> public readonly struct Envelope { public Envelope(object message, IActorRef sender) { Message = message; Sender = sender; } public IActorRef Sender { get; } public object Message { get; } } Used millions of times per second in Akka.NET readonly struct? Value type? Should be “zero allocations”
  • 27. Reference Type: Message Envelope /// <summary> /// Envelope class, represents a message and the sender of the message. /// </summary> public sealed class Envelope { public Envelope(object message, IActorRef sender) { Message = message; Sender = sender; } public IActorRef Sender { get; } public object Message { get; } } What if we change to a reference type? Will this reduce allocations? 394kb  264kb 3.15mb  2.1mb 215 us  147 us 1860 us  1332 us
  • 28. Value Type Pitfalls • Copy-by-Value • References to value types in other scopes requires copying • ref parameters can work, but in narrowly defined contexts • Excessive copying can be more expensive than allocating a reference • Use reference types when semantics are “referential” • Value types are not magic – work best in “tight” scopes • Use the right tool for the job
  • 30. Reference Type: Message Envelope • What happens when we benchmark with significantly increased cross-thread message traffic? • Now if we convert Envelope back into a struct again… • Thread access makes a difference!
  • 31. Threads, Memory, Synchronization, and Pain Threads Hate You and Your Code
  • 32. ThreadStatic and ThreadLocal<T> • Allocates objects directly into thread local storage • Objects stay there and are available each time thread is used • Ideal for caching and pooling • No synchronization • Data and work all performed adjacent to stack memory • Downside: thread-local data structures aren’t synchronized • Variants!
  • 33. Thread Local Storage & Context Switching • Reference types passed between threads often age into older generations of GC • Value types passed between threads are copied (no GC) • Thread-local state is copied into CPU’s L1/L2 cache from memory typically during execution • Context switching occurs when threads get scheduled onto different CPUs or work is moves onto different threads.
  • 34. Thread Locality & Context Switching Each thread gets ~30ms of execution time before yielding
  • 35. Thread Locality & Context Switching Current quantum is over – time for other threads to have a turn
  • 36. Thread Locality & Context Switching Context switch! Thread 0 now executing on CPU 1 – memory and state will have to be transferred.
  • 37. Context Switching: High Latency Impact /// <summary> /// An asynchronous operation will be executed by a <see cref="MessageDispatcher"/>. /// </summary> #if NETSTANDARD public interface IRunnable #else public interface IRunnable : IThreadPoolWorkItem #endif { /// <summary> /// Executes the task. /// </summary> void Run(); } // use native .NET 6 APIs here to reduce allocations // preferLocal to help reduce context switching ThreadPool.UnsafeQueueUserWorkItem(run, true); IThreadPoolWorkItem interface added in .NET Core 3.0 – avoids delegate allocations for executing on ThreadPool Consume IThreadPoolWorkItem with preferLocal=true – tells the ThreadPool to attempt to reschedule work on current thread / CPU.
  • 38. Performance Comparison Before After ~3x improvement ~50% improvement
  • 39. Thread Locality w/o Context Switching No context switch – same thread will have a chance to execute on same CPU. Might be able to benefit from L1/L2 cache, locality of memory access, etc.
  • 40. Data Structures & Synchronization /// <summary> An unbounded mailbox message queue. </summary> public class UnboundedMessageQueue : IMessageQueue, IUnboundedMessageQueueSemantics { private readonly ConcurrentQueue<Envelope> _queue = new ConcurrentQueue<Envelope>(); /// <inheritdoc cref="IMessageQueue"/> public bool HasMessages { get { return !_queue.IsEmpty; } } /// <inheritdoc cref="IMessageQueue"/> public int Count { get { return _queue.Count; } } …. } Could, in theory, improve memory performance by replacing with a LinkedList (no array segment allocations from resizing)
  • 41. Data Structures & Synchronization /// <summary> An unbounded mailbox message queue. </summary> public class UnboundedMessageQueue : IMessageQueue, IUnboundedMessageQueueSemantics { private readonly object s_lock = new object(); private readonly LinkedList<Envelope> _linkedList = new LinkedList<Envelope>(); public bool HasMessages { get { return Count > 0; } } public int Count { get { lock (s_lock) { return _linkedList.Count; } } } …. Not a thread-safe data structure, has to be synced- with lock Should offer better memory performance than ConcurrentQueue<T> Wooooooof 🤮
  • 42. Data Structures & Synchronization • What went wrong there? • ConcurrentQueue<T> is lock-free • Uses volatile and atomic compare-and-swap operations • i.e. Interlocked.CompareExchange • Significantly less expensive, even on a single thread, than lock • LinkedList<T> may not be all that memory efficient • Internal data structure allocations per-insert rather than array block allocations • Better off rolling your own, probably
  • 43. Learn More • https://getakka.net/ - Akka.NET website, Discord, and source • https://aaronstannard.com/ - my blog

Editor's Notes

  • #6: https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/large-object-heap  LOH threshold is 85,000 bytes
  • #9: See Microsoft.Extensions.ObjectPool
  • #14: Note: Background GC is enabled for both.
  • #18: Examples: https://particular.net/blog/pipeline-and-closure-allocations
  • #20: 32 bytes adds up when you allocate millions of these per-second https://stackoverflow.com/questions/16131641/memory-usage-of-an-empty-list-or-dictionary public class List<T> : IList<T>, ICollection<T>, IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable { private T[] _items; //4 bytes for x86, 8 for x64 private int _size; //4 bytes private int _version; //4 bytes [NonSerialized] private object _syncRoot; //4 bytes for x86, 8 for x64 private static readonly T[] _emptyArray; //one per type private const int _defaultCapacity = 4; //one per type ... }