SlideShare une entreprise Scribd logo
1  sur  53
Performance in
.NET Core
Gdańsk, 2019.11.21
2
Number of requests on production
Numberofrequests
3
Measurement tools
JetBrains dotTrace
JetBrains dotMemory
4
Size of objects
Namespace Allocated bytes
Allocated
objects
Collected bytes
Collected
objects
Newtonsoft
JSON
162 368 6 803 105 168 5 851
JSON.NET 68 276 2 122 39 564 1 750
5
The most allocated types
2.2
3.0
6
Allocated strings by Newtonsoft
7
Time of processing requests (smaller is better)
436
684
775 792
172
1768
282
353
581
677 720
160
1463
207
0
200
400
600
800
1000
1200
1400
1600
1800
2000
Time[ms]
ASP.NET Core 2.2 ASP .NET Core 3.0
8
What’s the gain?
ASP.NET Core 2.2
4 909 ms
ASP.NET Core 3.0
4 161 ms
748 ms
-
=
Pipes
10
Hypothetical Use Case
Company needs to report all sale
transactions quaterly for statistics purposes.
11
Hypothetical Use Case
Company needs to report all sale
transactions quaterly for statistics purposes.
Since the Company makes thousands of
transactions every day - report file is very
large.
12
Hypothetical Use Case
Company needs to report all sale
transactions quaterly for statistics purposes.
Since the Company makes thousands of
transactions every day - report file is very
large.
Let’s assume the report is a CSV file.
13
Hypothetical Use Case
Company needs to report all sale
transactions quaterly for statistics purposes.
Since the Company makes thousands of
transactions every day - report file is very
large.
Let’s assume the report is a CSV file.
14
Naïve approach 1
app.Run(context => ProcessRequestAsync(context.Request.Body));
// NAIVE APPROACH
private async Task ProcessRequestAsync(Stream stream)
{
var buffer = new byte[1024];
while(true)
{
var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
if (bytesRead == 0)
{
return; // EOF
}
ProcessRowData(buffer, bytesRead);
}
}
15
Naïve approach 2
// BETTER APPROACH
private async Task ProcessRequestAsync(Stream stream)
{
var buffer = new byte[1024];
while (true)
{
var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
if (bytesRead == 0)
{
return; // EOF
}
var newLinePos = -1;
var bytesChecked = 0;
do
{
newLinePos = Array.IndexOf(buffer, (byte)'n', bytesChecked, bytesRead - bytesChecked);
if (newLinePos >= 0)
{
var lineLength = newLinePos - bytesChecked;
ProcessRowData(buffer, bytesChecked, lineLength);
}
bytesChecked += newLinePos + 1;
}
while (newLinePos > 0);
}
}
16
CSV might be tricky
Some product; 5.0; "Amazingn
Category"; 10n
Other product; 1.0; Boring category; 2n
17
CSV might be tricky
Some product; 5.0; "Amazingn
Category"; 10n
Other product; 1.0; Boring category; 2n
18
How we can improve our approach?
We can allocate bigger buffer when we face longer line or multiline record
19
How we can improve our approach?
We can allocate bigger buffer when we face longer line or multiline record
We can create own pool of buffers, new buffer would be created when the previous gets
filled up (i.e. in 80% or more).
20
System.IO.Pipelines to the rescue
The mentioned issues can easily be solved by using Pipe.
21
System.IO.Pipelines to the rescue
The mentioned issues can easily be solved by using Pipe.
Pipe​
PipeWriter PipeReader
22
Pipes
private async Task ProcessRequestAsync(Stream stream)
{
var pipe = new Pipe();
var readFileTask = ReadFileAsync(stream, pipe.Writer);
var processFileTask = ProcessFileAsync(pipe.Reader);
await Task.WhenAll(readFileTask, processFileTask);
}
23
PipeWriter
private async Task ReadFileAsync(Stream stream, PipeWriter pipeWriter)
{
while (true)
{
Memory<byte> memory = pipeWriter.GetMemory(BufferSize);
int bytesRead = await stream.ReadAsync(memory);
if (bytesRead == 0)
{
break;
}
pipeWriter.Advance(bytesRead);
// flush data to PipeReader
FlushResult flushResult = await pipeWriter.FlushAsync();
if (flushResult.IsCompleted)
{
break;
}
}
pipeWriter.Complete(); // we are done
}
24
PipeReader
private async Task ProcessFileAsync(PipeReader pipeReader)
{
while(true)
{
ReadResult result = await pipeReader.ReadAsync();
ReadOnlySequence<byte> buffer = result.Buffer;
SequencePosition? position = null;
do
{
position = buffer.PositionOf((byte)'n'); // find position of newline character, read multiline row…
if (position != null)
{
ProcessRowData(buffer.Slice(0, position.Value));
buffer = buffer.Slice(buffer.GetPosition(1, position.Value)); // move to next line
}
}
while (position != null);
if (result.IsCompleted)
{
break;
}
pipeReader.AdvanceTo(buffer.Start, buffer.End); // let know the PipeReader how much bytes were consumed
}
pipeReader.Complete(); // we are done
}
25
Partial read
Pipe.Reader.ReadAsync() Some product; 5
Some product; 5 .PositionOf((byte)'n') null
Pipe.Reader.ReadAsync() Some product; 5.0; Some Categoryn
Some product; 5.0; Some Categoryn .PositionOf((byte)'n') SequencePosition
Pipe.Reader.AdvanceTo( SequencePosition +1)
Pipe.Reader.ReadAsync() Other product; 3.0;…
26
ReadOnlySequence<T>, SequencePosition
Pipe
ReadOnlySequence
EndStart
27
Backpressure & flow control
28
Backpressure & flow control
29
Backpressure & flow control
30
Backpressure & flow control
31
Backpressure & flow control
32
Backpressure & flow control
PauseWriterThreshold
33
Backpressure & flow control
PauseWriterThreshold
34
Backpressure & flow control
PauseWriterThreshold
35
Backpressure & flow control
PauseWriterThreshold
36
Backpressure & flow control
PauseWriterThreshold
ResumeWriterThreshold
37
Backpressure & flow control
PauseWriterThreshold
ResumeWriterThreshold
38
How is it relevant?
39
How is it relevant?
Pipes originally were introduced for internal use in Kestrel. Eventually, the’ve
evolved into a part of public API.
40
How is it relevant?
Pipes originally were introduced for internal use in Kestrel. Eventually, the’ve
evolved into a part of public API.
The body of request in ASP.NET Core 3.0 is exposed via BodyReader property of
the HttpContext. BodyReader is in fact PipeReader.
41
How is it relevant?
Pipes originally were introduced for internal use in Kestrel. Eventually, the’ve
evolved into a part of public API.
The body of request in ASP.NET Core 3.0 is exposed via BodyReader property of
the HttpContext. BodyReader is in fact PipeReader.
Response body can be written with BodyWriter (PipeWriter).
Span<T>
and Memory<T>
43
Span<T>
.NET Core 2.1
ReadOnlySpan<T>
C# 7.2
ref struct
Array Slicing
44
Span<T> - Example
N A M E @ E M A I L
45
Span<T> - Example
N A M E @ E M A I L
public ReadOnlySpan<char> GetName(ReadOnlySpan<char> email)
{
var @position = email.LastIndexOf(‘@’);
return @position == -1
? ReadOnlySpan<char>.Empty
: email.Slice(0, @position);
}
46
Span<T> - Two versions
Background vector Created by brgfx - www.freepik.com
47
Span<T> - Two versions
Method Job Mean StdDev
SpanIndexer_Get .NET 4.6 0.6054 ns 0.0007 ns
SpanIndexer_Get .NET Core 1.1 0.6047 ns 0.0008 ns
SpanIndexer_Get .NET Core 2.0 0.5333 ns 0.0006 ns
SpanIndexer_Set .NET 4.6 0.6059 ns 0.0007 ns
SpanIndexer_Set .NET Core 1.1 0.6042 ns 0.0002 ns
SpanIndexer_Set .NET Core 2.0 0.5205 ns 0.0003 ns
Source: Adam Sitnik - https://adamsitnik.com/Span/#using-span
48
Limitations of Span<T>
Heap
as generic type
argument
implement any
interfaces
No
parameter of async
method
49
Memory<T>
.NET Core 2.1
Asynchronous world
C# 7.2
ReadOnlyMemory<T>
On Heap
Wrapper of Span<T>
50
Span<T> and Memory<T> - Supported in
.NET Standard 1.0 1.1 1.2
.NET Core 1.0 1.0 1.0
.NET Framework 1 4.5 4.5 4.5.1
Mono 4.6 4.6 4.6
Xamarin.iOS 10.0 10.0 10.0
Xamarin.Mac 3.0 3.0 3.0
Xamarin.Android 7.0 7.0 7.0
Universal Windows
Platform
10.0 10.0 10.0
Unity 2018.1 2018.1 2018.1
Json.NET
52
Json.NET – High performance JSON serializer and deserializer
.NET Standard 1.6 2.0 2.1
.NET Core 1.0 2.0 3.0
.NET Framework 4.6.1 4.6.1 Won’t support
Mono 4.6 5.4 6.4
Xamarin.iOS 10.0 10.14 12.16
Xamarin.Mac 3.0 3.8 5.16
Xamarin.Android 7.0 8.0 10.0
Universal Windows
Platform
10.0.16299 10.0. 16299 TBD
Unity 2018.1 2018.1 TBD
await FlushAsync();
Questions();

Contenu connexe

Tendances

Data Structures and Performance for Scientific Computing with Hadoop and Dumb...
Data Structures and Performance for Scientific Computing with Hadoop and Dumb...Data Structures and Performance for Scientific Computing with Hadoop and Dumb...
Data Structures and Performance for Scientific Computing with Hadoop and Dumb...Austin Benson
 
Accelerate Reed-Solomon coding for Fault-Tolerance in RAID-like system
Accelerate Reed-Solomon coding for Fault-Tolerance in RAID-like systemAccelerate Reed-Solomon coding for Fault-Tolerance in RAID-like system
Accelerate Reed-Solomon coding for Fault-Tolerance in RAID-like systemShuai Yuan
 
Building a High-Performance Distributed Task Queue on MongoDB
Building a High-Performance Distributed Task Queue on MongoDBBuilding a High-Performance Distributed Task Queue on MongoDB
Building a High-Performance Distributed Task Queue on MongoDBMongoDB
 
Cypher for Gremlin
Cypher for GremlinCypher for Gremlin
Cypher for GremlinopenCypher
 
Bigdata Presentation
Bigdata PresentationBigdata Presentation
Bigdata PresentationYonas Gidey
 
Building Scalable, Distributed Job Queues with Redis and Redis::Client
Building Scalable, Distributed Job Queues with Redis and Redis::ClientBuilding Scalable, Distributed Job Queues with Redis and Redis::Client
Building Scalable, Distributed Job Queues with Redis and Redis::ClientMike Friedman
 
Optimizing with persistent data structures (LLVM Cauldron 2016)
Optimizing with persistent data structures (LLVM Cauldron 2016)Optimizing with persistent data structures (LLVM Cauldron 2016)
Optimizing with persistent data structures (LLVM Cauldron 2016)Igalia
 
Data correlation using PySpark and HDFS
Data correlation using PySpark and HDFSData correlation using PySpark and HDFS
Data correlation using PySpark and HDFSJohn Conley
 
NoSQL and SQL Anti Patterns
NoSQL and SQL Anti PatternsNoSQL and SQL Anti Patterns
NoSQL and SQL Anti PatternsGleicon Moraes
 
InfluxDB IOx Tech Talks: The Impossible Dream: Easy-to-Use, Super Fast Softw...
InfluxDB IOx Tech Talks: The Impossible Dream:  Easy-to-Use, Super Fast Softw...InfluxDB IOx Tech Talks: The Impossible Dream:  Easy-to-Use, Super Fast Softw...
InfluxDB IOx Tech Talks: The Impossible Dream: Easy-to-Use, Super Fast Softw...InfluxData
 
Better Full Text Search in PostgreSQL
Better Full Text Search in PostgreSQLBetter Full Text Search in PostgreSQL
Better Full Text Search in PostgreSQLArtur Zakirov
 
The Ring programming language version 1.9 book - Part 17 of 210
The Ring programming language version 1.9 book - Part 17 of 210The Ring programming language version 1.9 book - Part 17 of 210
The Ring programming language version 1.9 book - Part 17 of 210Mahmoud Samir Fayed
 
Web program-peformance-optimization
Web program-peformance-optimizationWeb program-peformance-optimization
Web program-peformance-optimizationxiaojueqq12345
 
Fast Insight from Fast Data: Integrating ClickHouse and Apache Kafka
Fast Insight from Fast Data: Integrating ClickHouse and Apache KafkaFast Insight from Fast Data: Integrating ClickHouse and Apache Kafka
Fast Insight from Fast Data: Integrating ClickHouse and Apache KafkaAltinity Ltd
 
Wayfair Use Case: The four R's of Metrics Delivery
Wayfair Use Case: The four R's of Metrics DeliveryWayfair Use Case: The four R's of Metrics Delivery
Wayfair Use Case: The four R's of Metrics DeliveryInfluxData
 
Sessionization with Spark streaming
Sessionization with Spark streamingSessionization with Spark streaming
Sessionization with Spark streamingRamūnas Urbonas
 

Tendances (20)

Data Structures and Performance for Scientific Computing with Hadoop and Dumb...
Data Structures and Performance for Scientific Computing with Hadoop and Dumb...Data Structures and Performance for Scientific Computing with Hadoop and Dumb...
Data Structures and Performance for Scientific Computing with Hadoop and Dumb...
 
Accelerate Reed-Solomon coding for Fault-Tolerance in RAID-like system
Accelerate Reed-Solomon coding for Fault-Tolerance in RAID-like systemAccelerate Reed-Solomon coding for Fault-Tolerance in RAID-like system
Accelerate Reed-Solomon coding for Fault-Tolerance in RAID-like system
 
Building a High-Performance Distributed Task Queue on MongoDB
Building a High-Performance Distributed Task Queue on MongoDBBuilding a High-Performance Distributed Task Queue on MongoDB
Building a High-Performance Distributed Task Queue on MongoDB
 
Cypher for Gremlin
Cypher for GremlinCypher for Gremlin
Cypher for Gremlin
 
Why learn Internals?
Why learn Internals?Why learn Internals?
Why learn Internals?
 
Bigdata Presentation
Bigdata PresentationBigdata Presentation
Bigdata Presentation
 
Building Scalable, Distributed Job Queues with Redis and Redis::Client
Building Scalable, Distributed Job Queues with Redis and Redis::ClientBuilding Scalable, Distributed Job Queues with Redis and Redis::Client
Building Scalable, Distributed Job Queues with Redis and Redis::Client
 
Optimizing with persistent data structures (LLVM Cauldron 2016)
Optimizing with persistent data structures (LLVM Cauldron 2016)Optimizing with persistent data structures (LLVM Cauldron 2016)
Optimizing with persistent data structures (LLVM Cauldron 2016)
 
Data correlation using PySpark and HDFS
Data correlation using PySpark and HDFSData correlation using PySpark and HDFS
Data correlation using PySpark and HDFS
 
NoSQL and SQL Anti Patterns
NoSQL and SQL Anti PatternsNoSQL and SQL Anti Patterns
NoSQL and SQL Anti Patterns
 
InfluxDB IOx Tech Talks: The Impossible Dream: Easy-to-Use, Super Fast Softw...
InfluxDB IOx Tech Talks: The Impossible Dream:  Easy-to-Use, Super Fast Softw...InfluxDB IOx Tech Talks: The Impossible Dream:  Easy-to-Use, Super Fast Softw...
InfluxDB IOx Tech Talks: The Impossible Dream: Easy-to-Use, Super Fast Softw...
 
Better Full Text Search in PostgreSQL
Better Full Text Search in PostgreSQLBetter Full Text Search in PostgreSQL
Better Full Text Search in PostgreSQL
 
DaWaK'07
DaWaK'07DaWaK'07
DaWaK'07
 
The Ring programming language version 1.9 book - Part 17 of 210
The Ring programming language version 1.9 book - Part 17 of 210The Ring programming language version 1.9 book - Part 17 of 210
The Ring programming language version 1.9 book - Part 17 of 210
 
Web program-peformance-optimization
Web program-peformance-optimizationWeb program-peformance-optimization
Web program-peformance-optimization
 
Fun421 stephens
Fun421 stephensFun421 stephens
Fun421 stephens
 
Fast Insight from Fast Data: Integrating ClickHouse and Apache Kafka
Fast Insight from Fast Data: Integrating ClickHouse and Apache KafkaFast Insight from Fast Data: Integrating ClickHouse and Apache Kafka
Fast Insight from Fast Data: Integrating ClickHouse and Apache Kafka
 
Wayfair Use Case: The four R's of Metrics Delivery
Wayfair Use Case: The four R's of Metrics DeliveryWayfair Use Case: The four R's of Metrics Delivery
Wayfair Use Case: The four R's of Metrics Delivery
 
Supporting HDF5 in GrADS
Supporting HDF5 in GrADSSupporting HDF5 in GrADS
Supporting HDF5 in GrADS
 
Sessionization with Spark streaming
Sessionization with Spark streamingSessionization with Spark streaming
Sessionization with Spark streaming
 

Similaire à Performance .NET Core - M. Terech, P. Janowski

Workshop "Can my .NET application use less CPU / RAM?", Yevhen Tatarynov
Workshop "Can my .NET application use less CPU / RAM?", Yevhen TatarynovWorkshop "Can my .NET application use less CPU / RAM?", Yevhen Tatarynov
Workshop "Can my .NET application use less CPU / RAM?", Yevhen TatarynovFwdays
 
[ACNA2022] Hadoop Vectored IO_ your data just got faster!.pdf
[ACNA2022] Hadoop Vectored IO_ your data just got faster!.pdf[ACNA2022] Hadoop Vectored IO_ your data just got faster!.pdf
[ACNA2022] Hadoop Vectored IO_ your data just got faster!.pdfMukundThakur22
 
Runtime Bytecode Transformation for Smalltalk
Runtime Bytecode Transformation for SmalltalkRuntime Bytecode Transformation for Smalltalk
Runtime Bytecode Transformation for SmalltalkESUG
 
H2O World - What's New in H2O with Cliff Click
H2O World - What's New in H2O with Cliff ClickH2O World - What's New in H2O with Cliff Click
H2O World - What's New in H2O with Cliff ClickSri Ambati
 
あなたのScalaを爆速にする7つの方法
あなたのScalaを爆速にする7つの方法あなたのScalaを爆速にする7つの方法
あなたのScalaを爆速にする7つの方法x1 ichi
 
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 CDKShu-Jeng Hsieh
 
Heading for a Record: Chromium, the 5th Check
Heading for a Record: Chromium, the 5th CheckHeading for a Record: Chromium, the 5th Check
Heading for a Record: Chromium, the 5th CheckPVS-Studio
 
Perly Parallel Processing of Fixed Width Data Records
Perly Parallel Processing of Fixed Width Data RecordsPerly Parallel Processing of Fixed Width Data Records
Perly Parallel Processing of Fixed Width Data RecordsWorkhorse Computing
 
XDP in Practice: DDoS Mitigation @Cloudflare
XDP in Practice: DDoS Mitigation @CloudflareXDP in Practice: DDoS Mitigation @Cloudflare
XDP in Practice: DDoS Mitigation @CloudflareC4Media
 
Quantifying Container Runtime Performance: OSCON 2017 Open Container Day
Quantifying Container Runtime Performance: OSCON 2017 Open Container DayQuantifying Container Runtime Performance: OSCON 2017 Open Container Day
Quantifying Container Runtime Performance: OSCON 2017 Open Container DayPhil Estes
 
Mass Report Generation Using REST APIs
Mass Report Generation Using REST APIsMass Report Generation Using REST APIs
Mass Report Generation Using REST APIsSalesforce Developers
 
Полнотекстовый поиск в PostgreSQL за миллисекунды (Олег Бартунов, Александр К...
Полнотекстовый поиск в PostgreSQL за миллисекунды (Олег Бартунов, Александр К...Полнотекстовый поиск в PostgreSQL за миллисекунды (Олег Бартунов, Александр К...
Полнотекстовый поиск в PostgreSQL за миллисекунды (Олег Бартунов, Александр К...Ontico
 
The CppCat Analyzer Checks TortoiseGit
The CppCat Analyzer Checks TortoiseGitThe CppCat Analyzer Checks TortoiseGit
The CppCat Analyzer Checks TortoiseGitAndrey Karpov
 
Node.js - Advanced Basics
Node.js - Advanced BasicsNode.js - Advanced Basics
Node.js - Advanced BasicsDoug Jones
 
JDK1.7 features
JDK1.7 featuresJDK1.7 features
JDK1.7 featuresindia_mani
 
Apache Big Data EU 2015 - Phoenix
Apache Big Data EU 2015 - PhoenixApache Big Data EU 2015 - Phoenix
Apache Big Data EU 2015 - PhoenixNick Dimiduk
 
Linux Kernel, tested by the Linux-version of PVS-Studio
Linux Kernel, tested by the Linux-version of PVS-StudioLinux Kernel, tested by the Linux-version of PVS-Studio
Linux Kernel, tested by the Linux-version of PVS-StudioPVS-Studio
 

Similaire à Performance .NET Core - M. Terech, P. Janowski (20)

Workshop "Can my .NET application use less CPU / RAM?", Yevhen Tatarynov
Workshop "Can my .NET application use less CPU / RAM?", Yevhen TatarynovWorkshop "Can my .NET application use less CPU / RAM?", Yevhen Tatarynov
Workshop "Can my .NET application use less CPU / RAM?", Yevhen Tatarynov
 
Exploitation Crash Course
Exploitation Crash CourseExploitation Crash Course
Exploitation Crash Course
 
[ACNA2022] Hadoop Vectored IO_ your data just got faster!.pdf
[ACNA2022] Hadoop Vectored IO_ your data just got faster!.pdf[ACNA2022] Hadoop Vectored IO_ your data just got faster!.pdf
[ACNA2022] Hadoop Vectored IO_ your data just got faster!.pdf
 
Runtime Bytecode Transformation for Smalltalk
Runtime Bytecode Transformation for SmalltalkRuntime Bytecode Transformation for Smalltalk
Runtime Bytecode Transformation for Smalltalk
 
H2O World - What's New in H2O with Cliff Click
H2O World - What's New in H2O with Cliff ClickH2O World - What's New in H2O with Cliff Click
H2O World - What's New in H2O with Cliff Click
 
Lp seminar
Lp seminarLp seminar
Lp seminar
 
あなたのScalaを爆速にする7つの方法
あなたのScalaを爆速にする7つの方法あなたのScalaを爆速にする7つの方法
あなたのScalaを爆速にする7つの方法
 
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
 
Heading for a Record: Chromium, the 5th Check
Heading for a Record: Chromium, the 5th CheckHeading for a Record: Chromium, the 5th Check
Heading for a Record: Chromium, the 5th Check
 
Perly Parallel Processing of Fixed Width Data Records
Perly Parallel Processing of Fixed Width Data RecordsPerly Parallel Processing of Fixed Width Data Records
Perly Parallel Processing of Fixed Width Data Records
 
XDP in Practice: DDoS Mitigation @Cloudflare
XDP in Practice: DDoS Mitigation @CloudflareXDP in Practice: DDoS Mitigation @Cloudflare
XDP in Practice: DDoS Mitigation @Cloudflare
 
Data Pipeline at Tapad
Data Pipeline at TapadData Pipeline at Tapad
Data Pipeline at Tapad
 
Quantifying Container Runtime Performance: OSCON 2017 Open Container Day
Quantifying Container Runtime Performance: OSCON 2017 Open Container DayQuantifying Container Runtime Performance: OSCON 2017 Open Container Day
Quantifying Container Runtime Performance: OSCON 2017 Open Container Day
 
Mass Report Generation Using REST APIs
Mass Report Generation Using REST APIsMass Report Generation Using REST APIs
Mass Report Generation Using REST APIs
 
Полнотекстовый поиск в PostgreSQL за миллисекунды (Олег Бартунов, Александр К...
Полнотекстовый поиск в PostgreSQL за миллисекунды (Олег Бартунов, Александр К...Полнотекстовый поиск в PostgreSQL за миллисекунды (Олег Бартунов, Александр К...
Полнотекстовый поиск в PostgreSQL за миллисекунды (Олег Бартунов, Александр К...
 
The CppCat Analyzer Checks TortoiseGit
The CppCat Analyzer Checks TortoiseGitThe CppCat Analyzer Checks TortoiseGit
The CppCat Analyzer Checks TortoiseGit
 
Node.js - Advanced Basics
Node.js - Advanced BasicsNode.js - Advanced Basics
Node.js - Advanced Basics
 
JDK1.7 features
JDK1.7 featuresJDK1.7 features
JDK1.7 features
 
Apache Big Data EU 2015 - Phoenix
Apache Big Data EU 2015 - PhoenixApache Big Data EU 2015 - Phoenix
Apache Big Data EU 2015 - Phoenix
 
Linux Kernel, tested by the Linux-version of PVS-Studio
Linux Kernel, tested by the Linux-version of PVS-StudioLinux Kernel, tested by the Linux-version of PVS-Studio
Linux Kernel, tested by the Linux-version of PVS-Studio
 

Dernier

Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Orbitshub
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyKhushali Kathiriya
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Victor Rentea
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MIND CTI
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistandanishmna97
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusZilliz
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...apidays
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vázquez
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfOverkill Security
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...Zilliz
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamUiPathCommunity
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Zilliz
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 

Dernier (20)

Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdf
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 

Performance .NET Core - M. Terech, P. Janowski

  • 2. 2 Number of requests on production Numberofrequests
  • 4. 4 Size of objects Namespace Allocated bytes Allocated objects Collected bytes Collected objects Newtonsoft JSON 162 368 6 803 105 168 5 851 JSON.NET 68 276 2 122 39 564 1 750
  • 5. 5 The most allocated types 2.2 3.0
  • 7. 7 Time of processing requests (smaller is better) 436 684 775 792 172 1768 282 353 581 677 720 160 1463 207 0 200 400 600 800 1000 1200 1400 1600 1800 2000 Time[ms] ASP.NET Core 2.2 ASP .NET Core 3.0
  • 8. 8 What’s the gain? ASP.NET Core 2.2 4 909 ms ASP.NET Core 3.0 4 161 ms 748 ms - =
  • 10. 10 Hypothetical Use Case Company needs to report all sale transactions quaterly for statistics purposes.
  • 11. 11 Hypothetical Use Case Company needs to report all sale transactions quaterly for statistics purposes. Since the Company makes thousands of transactions every day - report file is very large.
  • 12. 12 Hypothetical Use Case Company needs to report all sale transactions quaterly for statistics purposes. Since the Company makes thousands of transactions every day - report file is very large. Let’s assume the report is a CSV file.
  • 13. 13 Hypothetical Use Case Company needs to report all sale transactions quaterly for statistics purposes. Since the Company makes thousands of transactions every day - report file is very large. Let’s assume the report is a CSV file.
  • 14. 14 Naïve approach 1 app.Run(context => ProcessRequestAsync(context.Request.Body)); // NAIVE APPROACH private async Task ProcessRequestAsync(Stream stream) { var buffer = new byte[1024]; while(true) { var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length); if (bytesRead == 0) { return; // EOF } ProcessRowData(buffer, bytesRead); } }
  • 15. 15 Naïve approach 2 // BETTER APPROACH private async Task ProcessRequestAsync(Stream stream) { var buffer = new byte[1024]; while (true) { var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length); if (bytesRead == 0) { return; // EOF } var newLinePos = -1; var bytesChecked = 0; do { newLinePos = Array.IndexOf(buffer, (byte)'n', bytesChecked, bytesRead - bytesChecked); if (newLinePos >= 0) { var lineLength = newLinePos - bytesChecked; ProcessRowData(buffer, bytesChecked, lineLength); } bytesChecked += newLinePos + 1; } while (newLinePos > 0); } }
  • 16. 16 CSV might be tricky Some product; 5.0; "Amazingn Category"; 10n Other product; 1.0; Boring category; 2n
  • 17. 17 CSV might be tricky Some product; 5.0; "Amazingn Category"; 10n Other product; 1.0; Boring category; 2n
  • 18. 18 How we can improve our approach? We can allocate bigger buffer when we face longer line or multiline record
  • 19. 19 How we can improve our approach? We can allocate bigger buffer when we face longer line or multiline record We can create own pool of buffers, new buffer would be created when the previous gets filled up (i.e. in 80% or more).
  • 20. 20 System.IO.Pipelines to the rescue The mentioned issues can easily be solved by using Pipe.
  • 21. 21 System.IO.Pipelines to the rescue The mentioned issues can easily be solved by using Pipe. Pipe​ PipeWriter PipeReader
  • 22. 22 Pipes private async Task ProcessRequestAsync(Stream stream) { var pipe = new Pipe(); var readFileTask = ReadFileAsync(stream, pipe.Writer); var processFileTask = ProcessFileAsync(pipe.Reader); await Task.WhenAll(readFileTask, processFileTask); }
  • 23. 23 PipeWriter private async Task ReadFileAsync(Stream stream, PipeWriter pipeWriter) { while (true) { Memory<byte> memory = pipeWriter.GetMemory(BufferSize); int bytesRead = await stream.ReadAsync(memory); if (bytesRead == 0) { break; } pipeWriter.Advance(bytesRead); // flush data to PipeReader FlushResult flushResult = await pipeWriter.FlushAsync(); if (flushResult.IsCompleted) { break; } } pipeWriter.Complete(); // we are done }
  • 24. 24 PipeReader private async Task ProcessFileAsync(PipeReader pipeReader) { while(true) { ReadResult result = await pipeReader.ReadAsync(); ReadOnlySequence<byte> buffer = result.Buffer; SequencePosition? position = null; do { position = buffer.PositionOf((byte)'n'); // find position of newline character, read multiline row… if (position != null) { ProcessRowData(buffer.Slice(0, position.Value)); buffer = buffer.Slice(buffer.GetPosition(1, position.Value)); // move to next line } } while (position != null); if (result.IsCompleted) { break; } pipeReader.AdvanceTo(buffer.Start, buffer.End); // let know the PipeReader how much bytes were consumed } pipeReader.Complete(); // we are done }
  • 25. 25 Partial read Pipe.Reader.ReadAsync() Some product; 5 Some product; 5 .PositionOf((byte)'n') null Pipe.Reader.ReadAsync() Some product; 5.0; Some Categoryn Some product; 5.0; Some Categoryn .PositionOf((byte)'n') SequencePosition Pipe.Reader.AdvanceTo( SequencePosition +1) Pipe.Reader.ReadAsync() Other product; 3.0;…
  • 32. 32 Backpressure & flow control PauseWriterThreshold
  • 33. 33 Backpressure & flow control PauseWriterThreshold
  • 34. 34 Backpressure & flow control PauseWriterThreshold
  • 35. 35 Backpressure & flow control PauseWriterThreshold
  • 36. 36 Backpressure & flow control PauseWriterThreshold ResumeWriterThreshold
  • 37. 37 Backpressure & flow control PauseWriterThreshold ResumeWriterThreshold
  • 38. 38 How is it relevant?
  • 39. 39 How is it relevant? Pipes originally were introduced for internal use in Kestrel. Eventually, the’ve evolved into a part of public API.
  • 40. 40 How is it relevant? Pipes originally were introduced for internal use in Kestrel. Eventually, the’ve evolved into a part of public API. The body of request in ASP.NET Core 3.0 is exposed via BodyReader property of the HttpContext. BodyReader is in fact PipeReader.
  • 41. 41 How is it relevant? Pipes originally were introduced for internal use in Kestrel. Eventually, the’ve evolved into a part of public API. The body of request in ASP.NET Core 3.0 is exposed via BodyReader property of the HttpContext. BodyReader is in fact PipeReader. Response body can be written with BodyWriter (PipeWriter).
  • 43. 43 Span<T> .NET Core 2.1 ReadOnlySpan<T> C# 7.2 ref struct Array Slicing
  • 44. 44 Span<T> - Example N A M E @ E M A I L
  • 45. 45 Span<T> - Example N A M E @ E M A I L public ReadOnlySpan<char> GetName(ReadOnlySpan<char> email) { var @position = email.LastIndexOf(‘@’); return @position == -1 ? ReadOnlySpan<char>.Empty : email.Slice(0, @position); }
  • 46. 46 Span<T> - Two versions Background vector Created by brgfx - www.freepik.com
  • 47. 47 Span<T> - Two versions Method Job Mean StdDev SpanIndexer_Get .NET 4.6 0.6054 ns 0.0007 ns SpanIndexer_Get .NET Core 1.1 0.6047 ns 0.0008 ns SpanIndexer_Get .NET Core 2.0 0.5333 ns 0.0006 ns SpanIndexer_Set .NET 4.6 0.6059 ns 0.0007 ns SpanIndexer_Set .NET Core 1.1 0.6042 ns 0.0002 ns SpanIndexer_Set .NET Core 2.0 0.5205 ns 0.0003 ns Source: Adam Sitnik - https://adamsitnik.com/Span/#using-span
  • 48. 48 Limitations of Span<T> Heap as generic type argument implement any interfaces No parameter of async method
  • 49. 49 Memory<T> .NET Core 2.1 Asynchronous world C# 7.2 ReadOnlyMemory<T> On Heap Wrapper of Span<T>
  • 50. 50 Span<T> and Memory<T> - Supported in .NET Standard 1.0 1.1 1.2 .NET Core 1.0 1.0 1.0 .NET Framework 1 4.5 4.5 4.5.1 Mono 4.6 4.6 4.6 Xamarin.iOS 10.0 10.0 10.0 Xamarin.Mac 3.0 3.0 3.0 Xamarin.Android 7.0 7.0 7.0 Universal Windows Platform 10.0 10.0 10.0 Unity 2018.1 2018.1 2018.1
  • 52. 52 Json.NET – High performance JSON serializer and deserializer .NET Standard 1.6 2.0 2.1 .NET Core 1.0 2.0 3.0 .NET Framework 4.6.1 4.6.1 Won’t support Mono 4.6 5.4 6.4 Xamarin.iOS 10.0 10.14 12.16 Xamarin.Mac 3.0 3.8 5.16 Xamarin.Android 7.0 8.0 10.0 Universal Windows Platform 10.0.16299 10.0. 16299 TBD Unity 2018.1 2018.1 TBD

Notes de l'éditeur

  1. Tu myślałem wyjść od jakiegoś use-case'u. Np mamy jakiś duży plik CSV który chcemy sparsować. Prezentujemy stare podejście na streamach, płynnie przechodząc do System.IO.Pipelines i potem BodyReadera/Writera
  2. Tu myślałem wyjść od jakiegoś use-case'u. Np mamy jakiś duży plik CSV który chcemy sparsować. Prezentujemy stare podejście na streamach, płynnie przechodząc do System.IO.Pipelines i potem BodyReadera/Writera
  3. Tu myślałem wyjść od jakiegoś use-case'u. Np mamy jakiś duży plik CSV który chcemy sparsować. Prezentujemy stare podejście na streamach, płynnie przechodząc do System.IO.Pipelines i potem BodyReadera/Writera
  4. KOD!
  5. Możemy zaalokować większy bufor, jeżeli natrafimy na dłuższą linię lub rekord zawierający kilka linii. Przy okazji można stosować inne sztuczki, np. ArrayPool w celu minimalizowania liczby alokowanych buforów itp. Itd.. No ok. tylko wtedy przy zwiększaniu bufora kopiujemy pamięć. Dodatkowo warto by było potem zmniejszać ten bufor, żeby nie zajmować niepotrzebnie pamięci….pomysł nie do końca trafiony – generuje duże wykorzystanie pamięci. Możemy poprzedni pomysł rozszerzyć o dodawanie dodatkowych buforów tylko wtedy, kiedy poprzedni zostanie wykorzystany. Potrzebujemy wtedy logiki do odczytywania fragmentów pojedynczego rekordu z wielu buforów, oznaczania zwolnionych już buforów (takich z których odczytaliśmy już dane rekordu) itp. Itd. Całość robi się bardzo skomplikowana… A i tak nie jest do końca efektywnie, bo: Odczyt danych ze strumienia jest uzależniony od szybkości parsowania. Wykorzystanie zwykłej zarządzanej tablicy bajtów może mieć impact na GC – pinned memory, może prowadzić do fragmentacji pamięci.
  6. Możemy zaalokować większy bufor, jeżeli natrafimy na dłuższą linię lub rekord zawierający kilka linii. Przy okazji można stosować inne sztuczki, np. ArrayPool w celu minimalizowania liczby alokowanych buforów itp. Itd.. No ok. tylko wtedy przy zwiększaniu bufora kopiujemy pamięć. Dodatkowo warto by było potem zmniejszać ten bufor, żeby nie zajmować niepotrzebnie pamięci….pomysł nie do końca trafiony – generuje duże wykorzystanie pamięci. Możemy poprzedni pomysł rozszerzyć o dodawanie dodatkowych buforów tylko wtedy, kiedy poprzedni zostanie wykorzystany. Potrzebujemy wtedy logiki do odczytywania fragmentów pojedynczego rekordu z wielu buforów, oznaczania zwolnionych już buforów (takich z których odczytaliśmy już dane rekordu) itp. Itd. Całość robi się bardzo skomplikowana… A i tak nie jest do końca efektywnie, bo: Odczyt danych ze strumienia jest uzależniony od szybkości parsowania. Wykorzystanie zwykłej zarządzanej tablicy bajtów może mieć impact na GC – pinned memory, może prowadzić do fragmentacji pamięci.
  7. Pipe składa się z dwóch części: PipeWriter – który zapisuje do naszej „rury” oraz PipeReader, który z tej „rury” czyta. Mamy ładnie podzielony proces na 2 składowe – załadowanie danych ze strumienia oraz parsowanie tych danych. Task.WhenAll wskazuje, że obie składowe będą wykonywały się asynchronicznie.
  8. Pipe składa się z dwóch części: PipeWriter – który zapisuje do naszej „rury” oraz PipeReader, który z tej „rury” czyta. Mamy ładnie podzielony proces na 2 składowe – załadowanie danych ze strumienia oraz parsowanie tych danych. Task.WhenAll wskazuje, że obie składowe będą wykonywały się asynchronicznie. KOD
  9. Jedną z największych zalet wykorzystanie Pipe’ów jest Partial Read – możemy w zasadzie pracować na danych bez ich „skonsumowania”. Przykład ilustruje przykładowy parser HTTP.
  10. Pod maską Pipe zarządza (linked) listą zaalokowanych buforów, które są wykorzystywane przez PipeWritera/PipeReadera. PipeReader.ReadAsync zwraca ReadOnlySequence<T>. Za jego pomocą możemy uzyskać dostęp do jednego lub więcej segmentów pamięci (ReadOnlyMemory<T>) – analogicznie do Span<T> i Memory<T> i stringów. Pipe przechowuje informację o położeniu Writera i Readera w kontekście zaalokowanych danych z wykorzystaniem SequencePosition. SequencePosition to nic innego jak wskaźnik na konkretne miejsce we wspomnianej linked liście. ReadOnlySequence<T> i Sequence position to struktury.
  11. W idealnym przypadku to co przychodzi do serwera jest odczytywane przez jeden z wątków i jednocześnie parsowane i przetwarzane przez inny wątek. Samo parsowanie może jednak trwać znacznie dłużej niż ładowanie danych ze strumienia. W tej sytuacji wątek ładujący dane ze strumienia może albo alokować więcej pamięci, albo wstrzymać pracę na jakiś czas - należy znaleźć odpowiedni balans w celu zapewnienia optymalnej wydajności. Do rozwiązania wspomnianego problemu Pipy zostały wyposażone w 2 właściwości – PauseWriterThreshold i ResumeWriterThreshold. Pierwsza definiuje ile danych powinno zostać zbuforowanych zanim wywołanie metody FlushAsync (PipeWriter) spowoduje wstrzymanie pracy Writera. Druga z kolei kontroluje ilość danych którą może zostać skonsumowanych przez PipeReadera zanim praca PipeWritera zostanie wznowiona.
  12. W idealnym przypadku to co przychodzi do serwera jest odczytywane przez jeden z wątków i jednocześnie parsowane i przetwarzane przez inny wątek. Samo parsowanie może jednak trwać znacznie dłużej niż ładowanie danych ze strumienia. W tej sytuacji wątek ładujący dane ze strumienia może albo alokować więcej pamięci, albo wstrzymać pracę na jakiś czas - należy znaleźć odpowiedni balans w celu zapewnienia optymalnej wydajności. Do rozwiązania wspomnianego problemu Pipy zostały wyposażone w 2 właściwości – PauseWriterThreshold i ResumeWriterThreshold. Pierwsza definiuje ile danych powinno zostać zbuforowanych zanim wywołanie metody FlushAsync (PipeWriter) spowoduje wstrzymanie pracy Writera. Druga z kolei kontroluje ilość danych którą może zostać skonsumowanych przez PipeReadera zanim praca PipeWritera zostanie wznowiona.
  13. W idealnym przypadku to co przychodzi do serwera jest odczytywane przez jeden z wątków i jednocześnie parsowane i przetwarzane przez inny wątek. Samo parsowanie może jednak trwać znacznie dłużej niż ładowanie danych ze strumienia. W tej sytuacji wątek ładujący dane ze strumienia może albo alokować więcej pamięci, albo wstrzymać pracę na jakiś czas - należy znaleźć odpowiedni balans w celu zapewnienia optymalnej wydajności. Do rozwiązania wspomnianego problemu Pipy zostały wyposażone w 2 właściwości – PauseWriterThreshold i ResumeWriterThreshold. Pierwsza definiuje ile danych powinno zostać zbuforowanych zanim wywołanie metody FlushAsync (PipeWriter) spowoduje wstrzymanie pracy Writera. Druga z kolei kontroluje ilość danych którą może zostać skonsumowanych przez PipeReadera zanim praca PipeWritera zostanie wznowiona.
  14. W idealnym przypadku to co przychodzi do serwera jest odczytywane przez jeden z wątków i jednocześnie parsowane i przetwarzane przez inny wątek. Samo parsowanie może jednak trwać znacznie dłużej niż ładowanie danych ze strumienia. W tej sytuacji wątek ładujący dane ze strumienia może albo alokować więcej pamięci, albo wstrzymać pracę na jakiś czas - należy znaleźć odpowiedni balans w celu zapewnienia optymalnej wydajności. Do rozwiązania wspomnianego problemu Pipy zostały wyposażone w 2 właściwości – PauseWriterThreshold i ResumeWriterThreshold. Pierwsza definiuje ile danych powinno zostać zbuforowanych zanim wywołanie metody FlushAsync (PipeWriter) spowoduje wstrzymanie pracy Writera. Druga z kolei kontroluje ilość danych którą może zostać skonsumowanych przez PipeReadera zanim praca PipeWritera zostanie wznowiona.
  15. W idealnym przypadku to co przychodzi do serwera jest odczytywane przez jeden z wątków i jednocześnie parsowane i przetwarzane przez inny wątek. Samo parsowanie może jednak trwać znacznie dłużej niż ładowanie danych ze strumienia. W tej sytuacji wątek ładujący dane ze strumienia może albo alokować więcej pamięci, albo wstrzymać pracę na jakiś czas - należy znaleźć odpowiedni balans w celu zapewnienia optymalnej wydajności. Do rozwiązania wspomnianego problemu Pipy zostały wyposażone w 2 właściwości – PauseWriterThreshold i ResumeWriterThreshold. Pierwsza definiuje ile danych powinno zostać zbuforowanych zanim wywołanie metody FlushAsync (PipeWriter) spowoduje wstrzymanie pracy Writera. Druga z kolei kontroluje ilość danych którą może zostać skonsumowanych przez PipeReadera zanim praca PipeWritera zostanie wznowiona.
  16. W idealnym przypadku to co przychodzi do serwera jest odczytywane przez jeden z wątków i jednocześnie parsowane i przetwarzane przez inny wątek. Samo parsowanie może jednak trwać znacznie dłużej niż ładowanie danych ze strumienia. W tej sytuacji wątek ładujący dane ze strumienia może albo alokować więcej pamięci, albo wstrzymać pracę na jakiś czas - należy znaleźć odpowiedni balans w celu zapewnienia optymalnej wydajności. Do rozwiązania wspomnianego problemu Pipy zostały wyposażone w 2 właściwości – PauseWriterThreshold i ResumeWriterThreshold. Pierwsza definiuje ile danych powinno zostać zbuforowanych zanim wywołanie metody FlushAsync (PipeWriter) spowoduje wstrzymanie pracy Writera. Druga z kolei kontroluje ilość danych którą może zostać skonsumowanych przez PipeReadera zanim praca PipeWritera zostanie wznowiona.
  17. W idealnym przypadku to co przychodzi do serwera jest odczytywane przez jeden z wątków i jednocześnie parsowane i przetwarzane przez inny wątek. Samo parsowanie może jednak trwać znacznie dłużej niż ładowanie danych ze strumienia. W tej sytuacji wątek ładujący dane ze strumienia może albo alokować więcej pamięci, albo wstrzymać pracę na jakiś czas - należy znaleźć odpowiedni balans w celu zapewnienia optymalnej wydajności. Do rozwiązania wspomnianego problemu Pipy zostały wyposażone w 2 właściwości – PauseWriterThreshold i ResumeWriterThreshold. Pierwsza definiuje ile danych powinno zostać zbuforowanych zanim wywołanie metody FlushAsync (PipeWriter) spowoduje wstrzymanie pracy Writera. Druga z kolei kontroluje ilość danych którą może zostać skonsumowanych przez PipeReadera zanim praca PipeWritera zostanie wznowiona.
  18. W idealnym przypadku to co przychodzi do serwera jest odczytywane przez jeden z wątków i jednocześnie parsowane i przetwarzane przez inny wątek. Samo parsowanie może jednak trwać znacznie dłużej niż ładowanie danych ze strumienia. W tej sytuacji wątek ładujący dane ze strumienia może albo alokować więcej pamięci, albo wstrzymać pracę na jakiś czas - należy znaleźć odpowiedni balans w celu zapewnienia optymalnej wydajności. Do rozwiązania wspomnianego problemu Pipy zostały wyposażone w 2 właściwości – PauseWriterThreshold i ResumeWriterThreshold. Pierwsza definiuje ile danych powinno zostać zbuforowanych zanim wywołanie metody FlushAsync (PipeWriter) spowoduje wstrzymanie pracy Writera. Druga z kolei kontroluje ilość danych którą może zostać skonsumowanych przez PipeReadera zanim praca PipeWritera zostanie wznowiona.
  19. W idealnym przypadku to co przychodzi do serwera jest odczytywane przez jeden z wątków i jednocześnie parsowane i przetwarzane przez inny wątek. Samo parsowanie może jednak trwać znacznie dłużej niż ładowanie danych ze strumienia. W tej sytuacji wątek ładujący dane ze strumienia może albo alokować więcej pamięci, albo wstrzymać pracę na jakiś czas - należy znaleźć odpowiedni balans w celu zapewnienia optymalnej wydajności. Do rozwiązania wspomnianego problemu Pipy zostały wyposażone w 2 właściwości – PauseWriterThreshold i ResumeWriterThreshold. Pierwsza definiuje ile danych powinno zostać zbuforowanych zanim wywołanie metody FlushAsync (PipeWriter) spowoduje wstrzymanie pracy Writera. Druga z kolei kontroluje ilość danych którą może zostać skonsumowanych przez PipeReadera zanim praca PipeWritera zostanie wznowiona.
  20. W idealnym przypadku to co przychodzi do serwera jest odczytywane przez jeden z wątków i jednocześnie parsowane i przetwarzane przez inny wątek. Samo parsowanie może jednak trwać znacznie dłużej niż ładowanie danych ze strumienia. W tej sytuacji wątek ładujący dane ze strumienia może albo alokować więcej pamięci, albo wstrzymać pracę na jakiś czas - należy znaleźć odpowiedni balans w celu zapewnienia optymalnej wydajności. Do rozwiązania wspomnianego problemu Pipy zostały wyposażone w 2 właściwości – PauseWriterThreshold i ResumeWriterThreshold. Pierwsza definiuje ile danych powinno zostać zbuforowanych zanim wywołanie metody FlushAsync (PipeWriter) spowoduje wstrzymanie pracy Writera. Druga z kolei kontroluje ilość danych którą może zostać skonsumowanych przez PipeReadera zanim praca PipeWritera zostanie wznowiona.
  21. W idealnym przypadku to co przychodzi do serwera jest odczytywane przez jeden z wątków i jednocześnie parsowane i przetwarzane przez inny wątek. Samo parsowanie może jednak trwać znacznie dłużej niż ładowanie danych ze strumienia. W tej sytuacji wątek ładujący dane ze strumienia może albo alokować więcej pamięci, albo wstrzymać pracę na jakiś czas - należy znaleźć odpowiedni balans w celu zapewnienia optymalnej wydajności. Do rozwiązania wspomnianego problemu Pipy zostały wyposażone w 2 właściwości – PauseWriterThreshold i ResumeWriterThreshold. Pierwsza definiuje ile danych powinno zostać zbuforowanych zanim wywołanie metody FlushAsync (PipeWriter) spowoduje wstrzymanie pracy Writera. Druga z kolei kontroluje ilość danych którą może zostać skonsumowanych przez PipeReadera zanim praca PipeWritera zostanie wznowiona.
  22. Oczywiście w 99% przypadków wgl nie będziemy zajmowali się samodzielnym parsowaniem treści Body. Warto jednak wiedzieć jak to działa pod maską.
  23. Oczywiście w 99% przypadków wgl nie będziemy zajmowali się samodzielnym parsowaniem treści Body. Warto jednak wiedzieć jak to działa pod maską.
  24. Oczywiście w 99% przypadków wgl nie będziemy zajmowali się samodzielnym parsowaniem treści Body. Warto jednak wiedzieć jak to działa pod maską.
  25. Oczywiście w 99% przypadków wgl nie będziemy zajmowali się samodzielnym parsowaniem treści Body. Warto jednak wiedzieć jak to działa pod maską.