The document discusses modern concurrency primitives like threads, thread pools, coroutines, and schedulers. It covers why asynchronous programming with async/await is preferred over traditional threading. It also discusses challenges like sharing data across threads and blocking on I/O calls. Some solutions covered include using thread pools with dedicated I/O threads, work stealing, and introducing interruption points in long-running tasks.
During this talk we'll cover the theory and practical implementation behind most common patterns in modern multi-threaded programming. How our everyday libraries and frameworks optimize use of operating system resources for maximum efficiency. We'll also try to understand differences between various approaches and what tradeoffs do they infer. Finally we'll take a look at how they are supported by various compilers and runtimes.
A few slides about asynchrnous programming in Node, from callback hell to control flows using promises, thunks and generators, providing the right amount of abstraction to write great code.
All examples available on https://github.com/troch/node-control-flow.
From Zero To Production (NixOS, Erlang) @ Erlang Factory SF 2016Susan Potter
This talk will introduce the audience to the Nix packaging, NixOS, and related ecosystem tools for Erlang/Elixir developers.
By reviewing common development, testing, and deployment problems we will look at what Nix has to offer to aid Erlang/Elixir developers in these areas.
From seamless developer environment bootstrapping to consistent CI environments and beyond.
Find out how to build decentralized, fault-tolerant, stateful application services using core concepts and techniques from the Amazon Dynamo paper using riak_core as a toolkit.
You probably know the mantra that allocation is cheap. It usually is true, but devil is in the details. In your use case object allocation may impact processor caches evicting important data; burn CPU on executing constructor code; impact rates of object promotion to old generation and most importantly increase frequency of stop the word young gen pauses.
This presentation is for you if you are working on a Java based services that need to handle more and more traffic. As number of transactions per second rises you might hit performance wall that are young generation gc stopping whole application for precious milliseconds.
This presentation focuses on optimising object creation rate when dealing with seemingly mundane tasks. I will show few examples of surprising places in JDK and other libraries where garbage is created. I will explain how New Gen GC collection works and what costs are related to it. We will se escape analysis in action. Finally we will conclude that controlling allocation is the concern of library writers so that we can easily implement performant code without doing premature optimisations.
During this talk we'll cover the theory and practical implementation behind most common patterns in modern multi-threaded programming. How our everyday libraries and frameworks optimize use of operating system resources for maximum efficiency. We'll also try to understand differences between various approaches and what tradeoffs do they infer. Finally we'll take a look at how they are supported by various compilers and runtimes.
A few slides about asynchrnous programming in Node, from callback hell to control flows using promises, thunks and generators, providing the right amount of abstraction to write great code.
All examples available on https://github.com/troch/node-control-flow.
From Zero To Production (NixOS, Erlang) @ Erlang Factory SF 2016Susan Potter
This talk will introduce the audience to the Nix packaging, NixOS, and related ecosystem tools for Erlang/Elixir developers.
By reviewing common development, testing, and deployment problems we will look at what Nix has to offer to aid Erlang/Elixir developers in these areas.
From seamless developer environment bootstrapping to consistent CI environments and beyond.
Find out how to build decentralized, fault-tolerant, stateful application services using core concepts and techniques from the Amazon Dynamo paper using riak_core as a toolkit.
You probably know the mantra that allocation is cheap. It usually is true, but devil is in the details. In your use case object allocation may impact processor caches evicting important data; burn CPU on executing constructor code; impact rates of object promotion to old generation and most importantly increase frequency of stop the word young gen pauses.
This presentation is for you if you are working on a Java based services that need to handle more and more traffic. As number of transactions per second rises you might hit performance wall that are young generation gc stopping whole application for precious milliseconds.
This presentation focuses on optimising object creation rate when dealing with seemingly mundane tasks. I will show few examples of surprising places in JDK and other libraries where garbage is created. I will explain how New Gen GC collection works and what costs are related to it. We will se escape analysis in action. Finally we will conclude that controlling allocation is the concern of library writers so that we can easily implement performant code without doing premature optimisations.
Most AWS APIs will have limits on the amount of data you can send in one request and sometimes you really need to send a lot of data! To try to maximise the amount of data you can send, while still staying within the limits, some APIs support sending gzip-compressed payloads. But how can you send a gzipped request when using the Python SDK for AWS (boto3)? Well, I needed to answer this question recently and it turned out not to be as easy as I anticipated… Let’s jump into this rabbit hole together and let’s find out the answer!
CLS & asyncListener: asynchronous observability for Node.jsForrest Norvell
Slides from my presentation at PDXNode in October 2013 before RealtimeConf. Thanks to Tracy Abrahms, Ben Acker, and the rest of the PDXNode community for accommodating and hosting me at the last minute!
Building Scalable Stateless Applications with RxJavaRick Warren
RxJava is a lightweight open-source library, originally from Netflix, that makes it easy to compose asynchronous data sources and operations. This presentation is a high-level intro to this library and how it can fit into your application.
Node has captured the attention of early adopters by clearly differentiating itself as being asynchronous from the ground up while remaining accessible. Now that server side JavaScript is at the cutting edge of the asynchronous, real time web, it is in a much better position to establish itself as the go to language for also making synchronous, CRUD webapps and gain a stronger foothold on the server.
This talk covers the current state of server side JavaScript beyond Node. It introduces Common Node, a synchronous CommonJS compatibility layer using node-fibers which bridges the gap between the different platforms. We look into Common Node's internals, compare its performance to that of other implementations such as RingoJS and go through some ideal use cases.
Most AWS APIs will have limits on the amount of data you can send in one request and sometimes you really need to send a lot of data! To try to maximise the amount of data you can send, while still staying within the limits, some APIs support sending gzip-compressed payloads. But how can you send a gzipped request when using the Python SDK for AWS (boto3)? Well, I needed to answer this question recently and it turned out not to be as easy as I anticipated… Let’s jump into this rabbit hole together and let’s find out the answer!
CLS & asyncListener: asynchronous observability for Node.jsForrest Norvell
Slides from my presentation at PDXNode in October 2013 before RealtimeConf. Thanks to Tracy Abrahms, Ben Acker, and the rest of the PDXNode community for accommodating and hosting me at the last minute!
Building Scalable Stateless Applications with RxJavaRick Warren
RxJava is a lightweight open-source library, originally from Netflix, that makes it easy to compose asynchronous data sources and operations. This presentation is a high-level intro to this library and how it can fit into your application.
Node has captured the attention of early adopters by clearly differentiating itself as being asynchronous from the ground up while remaining accessible. Now that server side JavaScript is at the cutting edge of the asynchronous, real time web, it is in a much better position to establish itself as the go to language for also making synchronous, CRUD webapps and gain a stronger foothold on the server.
This talk covers the current state of server side JavaScript beyond Node. It introduces Common Node, a synchronous CommonJS compatibility layer using node-fibers which bridges the gap between the different platforms. We look into Common Node's internals, compare its performance to that of other implementations such as RingoJS and go through some ideal use cases.
I would like to present our CI Provisioning with Openstack solution and how it improved our development. The CI provisioning is meant to replace your static CI env servers to a auto provisioned during your build stage for every commit.
Abstract:
1. CI Flow Quick view
2. Openstack CI integration maven plugin
3. Orchestration using facters
4. Openstack instance queue for faster provisioning
Container orchestration from theory to practiceDocker, Inc.
"Join Laura Frank and Stephen Day as they explain and examine technical concepts behind container orchestration systems, like distributed consensus, object models, and node topology. These concepts build the foundation of every modern orchestration system, and each technical explanation will be illustrated using SwarmKit and Kubernetes as a real-world example. Gain a deeper understanding of how orchestration systems work in practice and walk away with more insights into your production applications."
Machine learning at scale with aws sage makerPhilipBasford
The adoption of Machine Learning (ML) has boomed over the last 12 months; from initial prototypes and now into fully managed production workloads that embed ML in critical areas of both start-up and enterprise businesses. These workloads need to be highly available, elastic, have low latency, be very secure, and also cost efficient.
The corner stone of this is AWS SageMaker. AWS SageMaker offers a great platform for Machine Learning that includes one-click deployment of models for inference using AWS SageMaker Endpoints. This talk will provide advice and recommendations on how to use cases AWS SageMaker Endpoints as there is an awful lot more to AWS SageMaker Endpoints than meets the eye. During this talk we will look how to use AWS SageMaker Endpoints, how to build a custom model; look at how to scale them using Auto Scaling, look at canary style deployments, how to monitor them with CloudWatch. We will also look at how AWS SageMaker Endpoints can be used within serverless APIs with real-time observations using AWS X-Ray.
This talk was given at JSSummit 2013. Entitled "Avoiding Callback Hell with Async.js", my talk focused on common pitfalls with asynchronous functions and callbacks in JavaScript, and using the async.js library and its advanced control flows to create cleaner, more manageable code.
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)Wesley Beary
Cloud computing scared the crap out of me - the quirks and nightmares of provisioning cloud computing, dns, storage, ... on AWS, Terremark, Rackspace, ... - I mean, where do you even start?
Since I couldn't find a good answer, I undertook the (probably insane) task of creating one. fog gives you a place to start by creating abstractions that work across many different providers, greatly reducing the barrier to entry (and the cost of switching later). The abstractions are built on top of solid wrappers for each api. So if the high level stuff doesn't cut it you can dig in and get the job done. On top of that, mocks are available to simulate what clouds will do for development and testing (saving you time and money).
You'll get a whirlwind tour of basic through advanced as we create the building blocks of a highly distributed (multi-cloud) system with some simple Ruby scripts that work nearly verbatim from provider to provider. Get your feet wet working with cloud resources or just make it easier on yourself as your usage gets more complex, either way fog makes it easy to get what you need from the cloud.
The OpenStack Edition adds my concerns about OpenStack API development, including things that have already been fixed and things that we haven't yet encountered. Hopefully this consumer perspective can help shed light on some rough spots.
In a world where microservices are more and more a standard architecture for Java based applications running in the cloud, the JVM warmup time can become a limitation. Especially when you look at spinning up new instances of an app as response to changes in load, the warmup time can be a problem. Native images are one solution to solve these problems because their statically ahead of time compiled code simply doesn’t have to warmup and so has short startup time. But even with the shorter startup time and smaller footprint it doesn’t come without a drawback. The overall performance might be slower because of the missing JIT optimizations at runtime. There is a new OpenJDK project called CRaC (Coordinated Restore at Checkpoint) which goal it is to address the JVM warmup problem with a different approach. The idea is to take a snapshot of the running JVM, store it in files and restore the JVM at a later point in time (or even on another machine).
This session will give you a short overview of the CRaC project and shows some results from a proof of concept implementation.
fog or: How I Learned to Stop Worrying and Love the CloudWesley Beary
Learn how to easily get started on cloud computing with fog. If you can control your infrastructure choices, you’ll make better choices in development and get what you need in production. You'll get an overview of fog and concrete examples to give you a head start on your provisioning workflow.
Postgres indexes: how to make them work for your applicationBartosz Sypytkowski
Indexes are one of the most crucial structures of any relational database. In this talk we'll explain how to use them efficiently, how to read query plans and what do they mean for us. We'll also cover a variety of different indexing structures available in PostgreSQL database and build up some intuition about which one to pick depending on the situation.
How do databases perform live backups and point-in-time recoveryBartosz Sypytkowski
In this talk we'll talk in details on how modern databases are capable of performing backups without downtimes and how these backups later can be used to restore database to any point in time.
While the talk describes generally applicable approach, a Litestream (SQLite backup service) is used for reference implementation.
This presentation covers HyParView and Plumtree - protocols used to build highly scalable clusters of data capable of gossiping messages between thousands of clients.
In this talk we'll discuss technical foundations behind Conflict-free Replicated Data Types (CRDT), which let us create collaborative client applications - systems where no reliance on central servers and offline-first capabilities are one of the founding principles. We'll cover some of the challenges bound to this approach and how to address them. Finally we'll present Yrs - Rust library, that allows us to build rich collaborative applications on desktop and browser.
During this presentation we'll quickly cover the core principles of eventsourced systems and different approaches to scalling event log to distributed workload. We'll focus on peer-to-peer variants of such: what are their advantages and disadvantages and how we can use them.
Strongly consistent databases are dominating world of software. However, with increasing scale and global availability of our services, many developers often prefer to loose their constraints in favor of an eventual consistency.
During this presentation we'll talk about Conflict-free Replicated Data Types (CRDT) - an eventually-consistent structures, that can be found in many modern day multi-master, geo-distributed databases such as CosmosDB, DynamoDB, Riak, Cassandra or Redis: how do they work and what makes them so interesting choice in highly available systems.
This is presentation from WG.NET (May 2019), where I'm discussing different aspects of virtualization, mainly in the context of programming languages. We'll covering up what stack vs. register based virtual machines are, what is interpreter and compiler and how to build our own bytecode interpreter for a toy programming language.
This is presentiation for Lambda Days 2019, in which I describe details behind building collaborative text editing experience using Replicated Growable Array CRDTs. Later on we come to defining its issues and how to solve them.
Slides from presentation, I've made on the BuildStuff LT 2018. Here I'm talking about issues, many people have found when using RESTful APIs and how GraphQL addresses them. Also I'm trying to cover the tradeoffs made by the standard, solutions proposed by different implementations and some ideas for the future.
Immunizing Image Classifiers Against Localized Adversary Attacksgerogepatton
This paper addresses the vulnerability of deep learning models, particularly convolutional neural networks
(CNN)s, to adversarial attacks and presents a proactive training technique designed to counter them. We
introduce a novel volumization algorithm, which transforms 2D images into 3D volumetric representations.
When combined with 3D convolution and deep curriculum learning optimization (CLO), itsignificantly improves
the immunity of models against localized universal attacks by up to 40%. We evaluate our proposed approach
using contemporary CNN architectures and the modified Canadian Institute for Advanced Research (CIFAR-10
and CIFAR-100) and ImageNet Large Scale Visual Recognition Challenge (ILSVRC12) datasets, showcasing
accuracy improvements over previous techniques. The results indicate that the combination of the volumetric
input and curriculum learning holds significant promise for mitigating adversarial attacks without necessitating
adversary training.
Cosmetic shop management system project report.pdfKamal Acharya
Buying new cosmetic products is difficult. It can even be scary for those who have sensitive skin and are prone to skin trouble. The information needed to alleviate this problem is on the back of each product, but it's thought to interpret those ingredient lists unless you have a background in chemistry.
Instead of buying and hoping for the best, we can use data science to help us predict which products may be good fits for us. It includes various function programs to do the above mentioned tasks.
Data file handling has been effectively used in the program.
The automated cosmetic shop management system should deal with the automation of general workflow and administration process of the shop. The main processes of the system focus on customer's request where the system is able to search the most appropriate products and deliver it to the customers. It should help the employees to quickly identify the list of cosmetic product that have reached the minimum quantity and also keep a track of expired date for each cosmetic product. It should help the employees to find the rack number in which the product is placed.It is also Faster and more efficient way.
Hierarchical Digital Twin of a Naval Power SystemKerry Sado
A hierarchical digital twin of a Naval DC power system has been developed and experimentally verified. Similar to other state-of-the-art digital twins, this technology creates a digital replica of the physical system executed in real-time or faster, which can modify hardware controls. However, its advantage stems from distributing computational efforts by utilizing a hierarchical structure composed of lower-level digital twin blocks and a higher-level system digital twin. Each digital twin block is associated with a physical subsystem of the hardware and communicates with a singular system digital twin, which creates a system-level response. By extracting information from each level of the hierarchy, power system controls of the hardware were reconfigured autonomously. This hierarchical digital twin development offers several advantages over other digital twins, particularly in the field of naval power systems. The hierarchical structure allows for greater computational efficiency and scalability while the ability to autonomously reconfigure hardware controls offers increased flexibility and responsiveness. The hierarchical decomposition and models utilized were well aligned with the physical twin, as indicated by the maximum deviations between the developed digital twin hierarchy and the hardware.
About
Indigenized remote control interface card suitable for MAFI system CCR equipment. Compatible for IDM8000 CCR. Backplane mounted serial and TCP/Ethernet communication module for CCR remote access. IDM 8000 CCR remote control on serial and TCP protocol.
• Remote control: Parallel or serial interface.
• Compatible with MAFI CCR system.
• Compatible with IDM8000 CCR.
• Compatible with Backplane mount serial communication.
• Compatible with commercial and Defence aviation CCR system.
• Remote control system for accessing CCR and allied system over serial or TCP.
• Indigenized local Support/presence in India.
• Easy in configuration using DIP switches.
Technical Specifications
Indigenized remote control interface card suitable for MAFI system CCR equipment. Compatible for IDM8000 CCR. Backplane mounted serial and TCP/Ethernet communication module for CCR remote access. IDM 8000 CCR remote control on serial and TCP protocol.
Key Features
Indigenized remote control interface card suitable for MAFI system CCR equipment. Compatible for IDM8000 CCR. Backplane mounted serial and TCP/Ethernet communication module for CCR remote access. IDM 8000 CCR remote control on serial and TCP protocol.
• Remote control: Parallel or serial interface
• Compatible with MAFI CCR system
• Copatiable with IDM8000 CCR
• Compatible with Backplane mount serial communication.
• Compatible with commercial and Defence aviation CCR system.
• Remote control system for accessing CCR and allied system over serial or TCP.
• Indigenized local Support/presence in India.
Application
• Remote control: Parallel or serial interface.
• Compatible with MAFI CCR system.
• Compatible with IDM8000 CCR.
• Compatible with Backplane mount serial communication.
• Compatible with commercial and Defence aviation CCR system.
• Remote control system for accessing CCR and allied system over serial or TCP.
• Indigenized local Support/presence in India.
• Easy in configuration using DIP switches.
Welcome to WIPAC Monthly the magazine brought to you by the LinkedIn Group Water Industry Process Automation & Control.
In this month's edition, along with this month's industry news to celebrate the 13 years since the group was created we have articles including
A case study of the used of Advanced Process Control at the Wastewater Treatment works at Lleida in Spain
A look back on an article on smart wastewater networks in order to see how the industry has measured up in the interim around the adoption of Digital Transformation in the Water Industry.
Water scarcity is the lack of fresh water resources to meet the standard water demand. There are two type of water scarcity. One is physical. The other is economic water scarcity.
Overview of the fundamental roles in Hydropower generation and the components involved in wider Electrical Engineering.
This paper presents the design and construction of hydroelectric dams from the hydrologist’s survey of the valley before construction, all aspects and involved disciplines, fluid dynamics, structural engineering, generation and mains frequency regulation to the very transmission of power through the network in the United Kingdom.
Author: Robbie Edward Sayers
Collaborators and co editors: Charlie Sims and Connor Healey.
(C) 2024 Robbie E. Sayers
Hybrid optimization of pumped hydro system and solar- Engr. Abdul-Azeez.pdffxintegritypublishin
Advancements in technology unveil a myriad of electrical and electronic breakthroughs geared towards efficiently harnessing limited resources to meet human energy demands. The optimization of hybrid solar PV panels and pumped hydro energy supply systems plays a pivotal role in utilizing natural resources effectively. This initiative not only benefits humanity but also fosters environmental sustainability. The study investigated the design optimization of these hybrid systems, focusing on understanding solar radiation patterns, identifying geographical influences on solar radiation, formulating a mathematical model for system optimization, and determining the optimal configuration of PV panels and pumped hydro storage. Through a comparative analysis approach and eight weeks of data collection, the study addressed key research questions related to solar radiation patterns and optimal system design. The findings highlighted regions with heightened solar radiation levels, showcasing substantial potential for power generation and emphasizing the system's efficiency. Optimizing system design significantly boosted power generation, promoted renewable energy utilization, and enhanced energy storage capacity. The study underscored the benefits of optimizing hybrid solar PV panels and pumped hydro energy supply systems for sustainable energy usage. Optimizing the design of solar PV panels and pumped hydro energy supply systems as examined across diverse climatic conditions in a developing country, not only enhances power generation but also improves the integration of renewable energy sources and boosts energy storage capacities, particularly beneficial for less economically prosperous regions. Additionally, the study provides valuable insights for advancing energy research in economically viable areas. Recommendations included conducting site-specific assessments, utilizing advanced modeling tools, implementing regular maintenance protocols, and enhancing communication among system components.
5. ASYNC/AWAIT
Task.Run(async () =>
{
await using var conn = new SqlConnection(ConnectionString);
await conn.OpenAsync();
var user = await conn.QueryFirstAsync<User>(
"SELECT * FROM Users WHERE Id = @id",
new { id = 100 });
Console.WriteLine($"Received user {user.FirstName} {user.LastName}");
});
7. THREAD API
new Thread(() =>
{
var conn = new SqlConnection(ConnectionString);
conn.Open();
var user = conn.QueryFirst<User>(
"SELECT * FROM Users WHERE Id = @id",
new { id = 100 });
Console.WriteLine($"Received user {user.FirstName} {user.LastName}");
}).Start();
11. PINNING THREAD TO CPU
var threads = Process.GetCurrentProcess().Threads;
var cpuCount = Environment.ProcessorCount;
Console.WriteLine($"Using {threads.Count} threads on {cpuCount} cores.");
// => Using 10 threads on 4 cores.
for (int i = 0; i < threads.Count; i++)
{
var pthread = threads[i];
var cpuMask = (1L << (i % cpuCount));
pthread.IdealProcessor = i % cpuCount; // set preferred thread(s)
pthread.ProcessorAffinity = (IntPtr)cpuMask; // set thread affinity mask
}
NOTE: it’s not always possible (iOS) or respected.
25. WHY IS THIS
CODE BAD?
static async Task ProcessFiles(FileInfo[] files)
{
var tasks = new Task[files.Length];
for (int i = 0; i < files.Length; i++)
tasks[i] = ProcessFile(files[i]);
await Task.WhenAll(tasks);
}
static async Task ProcessFile(FileInfo file)
{
using var stream = file.OpenRead();
using var reader = new StreamReader(stream);
var text = reader.ReadToEnd();
Process(text);
}
26. WHY IS THIS
CODE BAD?
static async Task ProcessFiles(FileInfo[] files)
{
var tasks = new Task[files.Length];
for (int i = 0; i < files.Length; i++)
tasks[i] = ProcessFile(files[i]);
await Task.WhenAll(tasks);
}
static async Task ProcessFile(FileInfo file)
{
using var stream = file.OpenRead();
using var reader = new StreamReader(stream);
var text = reader.ReadToEnd();
Process(text);
}
Blocking the thread belonging
to a thread pool shared with
other tasks.
28. I/O
1. Just use async I/O API…
2. … but what when it’s not possible?
WHAT CAN WE DO
ABOUT IT?
29. I/O
1. Just use async I/O API…
2. … but what when it’s not possible?
WHAT CAN WE DO
ABOUT IT?
internal static class LmdbMethods
{
[DllImport("lmdb", CallingConvention = CallingConvention.Cdecl)]
public static extern int mdb_dbi_open(IntPtr txn, string name, DatabaseOpenFlags flags, out uint db);
[DllImport("lmdb", CallingConvention = CallingConvention.Cdecl)]
public static extern int mdb_cursor_get(IntPtr cursor, ref ValueStructure key, ref ValueStructure
data, CursorOperation op);
[DllImport("lmdb", CallingConvention = CallingConvention.Cdecl)]
public static extern int mdb_cursor_put(IntPtr cursor, ref ValueStructure key, ref ValueStructure
value, CursorPutOptions flags);
// other methods
}
41. Scheduler depends on coroutines
to return control to scheduler.
PREEMPTIVE
Scheduler is in charge of
execution. Coroutines can be
preempted.
COOPERATIVE
43. COMPAR
ING
VECTOR
CLOCKS
BUILDING
AN EXCEL
FILE
app.get('/valuations.xlsx', async (req, res) => {
var workbook = new Excel.Workbook();
var worksheet = workbook.addWorksheet("Valuations");
var valuations = await getValuations(req.params.id);
for (let valuation in valuations) {
worksheet.addRow(valuation);
}
await workbook.xlsx.write(res);
});
44. COMPAR
ING
VECTOR
CLOCKS
BUILDING
AN EXCEL
FILE
app.get('/valuations.xlsx', async (req, res) => {
var workbook = new Excel.Workbook();
var worksheet = workbook.addWorksheet("Valuations");
var valuations = await getValuations(req.params.id);
for (let valuation in valuations) {
worksheet.addRow(valuation); // 500μs
}
await workbook.xlsx.write(res);
});
45. COMPAR
ING
VECTOR
CLOCKS
BUILDING
AN EXCEL
FILE
app.get('/valuations.xlsx', async (req, res) => {
var workbook = new Excel.Workbook();
var worksheet = workbook.addWorksheet("Valuations");
var valuations = await getValuations(req.params.id);
for (let valuation in valuations) { // 20,000 items
worksheet.addRow(valuation); // 500μs
}
await workbook.xlsx.write(res);
});
46. COMPAR
ING
VECTOR
CLOCKS
BUILDING
AN EXCEL
FILE
app.get('/valuations.xlsx', async (req, res) => {
var workbook = new Excel.Workbook();
var worksheet = workbook.addWorksheet("Valuations");
var valuations = await getValuations(req.params.id);
for (let valuation in valuations) { // 20,000 items
worksheet.addRow(valuation); // 500μs
}
await workbook.xlsx.write(res);
});
Total loop execution time: 10 seconds
63. COMPAR
ING
VECTOR
CLOCKS
STACKLESS
COROUTINES
OLD CALLBACK API
app.get('/valuations.xlsx', function (req, res, next) {
var workbook = new Excel.Workbook();
var worksheet = workbook.addWorksheet("Valuations");
getValuations(req.params.id, function (err, valuations) {
for (let valuation in valuations) {
worksheet.addRow(valuation);
}
workbook.xlsx.write(res, function (err) {
next();
});
});
});
64. COMPAR
ING
VECTOR
CLOCKS
STACKLESS
COROUTINES
app.get('/valuations.xlsx', (req, res) => {
var workbook = new Excel.Workbook();
var worksheet = workbook.addWorksheet("Valuations");
return getValuations(req.params.id)
.then((valuations) => {
for (let valuation in valuations) {
worksheet.addRow(valuation);
}
return workbook.xlsx.write(res);
});
});
OLD PROMISE API
65. COMPAR
ING
VECTOR
CLOCKS
STACKLESS
COROUTINES
app.get('/valuations.xlsx', async (req, res) => {
var workbook = new Excel.Workbook();
var worksheet = workbook.addWorksheet("Valuations");
var valuations = await getValuations(req.params.id);
for (let valuation in valuations) {
worksheet.addRow(valuation);
}
await workbook.xlsx.write(res);
});
67. STACKFUL
COROUTINES
STACK
main activation
frame
function foo(a, b)
print("foo", a)
bar("foo", b)
end
function bar(caller, x)
print(“bar: ", caller)
coroutine.yield()
print(“bar", x)
end
co = coroutine.create(foo)
coroutine.resume(co, 1, 2)
print(“main”)
coroutine.resume(co)
68. STACKFUL
COROUTINES
STACK
main activation
frame
function foo(a, b)
print("foo", a)
bar("foo", b)
end
function bar(caller, x)
print(“bar: ", caller)
coroutine.yield()
print(“bar", x)
end
co = coroutine.create(foo)
coroutine.resume(co, 1, 2)
print(“main”)
coroutine.resume(co)
foo activation
frame
Start of
coroutine
stack
69. STACKFUL
COROUTINES
STACK
main activation
frame
function foo(a, b)
print("foo", a)
bar("foo", b)
end
function bar(caller, x)
print(“bar: ", caller)
coroutine.yield()
print(“bar", x)
end
co = coroutine.create(foo)
coroutine.resume(co, 1, 2)
print(“main”)
coroutine.resume(co)
foo activation
frame
print activation
frame
70. STACKFUL
COROUTINES
STACK
main activation
frame
function foo(a, b)
print("foo", a)
bar("foo", b)
end
function bar(caller, x)
print(“bar: ", caller)
coroutine.yield()
print(“bar", x)
end
co = coroutine.create(foo)
coroutine.resume(co, 1, 2)
print(“main”)
coroutine.resume(co)
foo activation
frame
bar activation
frame
71. STACKFUL
COROUTINES
STACK
main activation
frame
function foo(a, b)
print("foo", a)
bar("foo", b)
end
function bar(caller, x)
print(“bar: ", caller)
coroutine.yield()
print(“bar", x)
end
co = coroutine.create(foo)
coroutine.resume(co, 1, 2)
print(“main”)
coroutine.resume(co)
foo activation
frame
bar activation
frame
print activation
frame
72. STACKFUL
COROUTINES
STACK
main activation
frame
function foo(a, b)
print("foo", a)
bar("foo", b)
end
function bar(caller, x)
print(“bar: ", caller)
coroutine.yield()
print(“bar", x)
end
co = coroutine.create(foo)
coroutine.resume(co, 1, 2)
print(“main”)
coroutine.resume(co)
foo activation
frame
bar activation
frame
Park
coroutine
stack
73. STACKFUL
COROUTINES
STACK
main activation
frame
function foo(a, b)
print("foo", a)
bar("foo", b)
end
function bar(caller, x)
print(“bar: ", caller)
coroutine.yield()
print(“bar", x)
end
co = coroutine.create(foo)
coroutine.resume(co, 1, 2)
print(“main”)
coroutine.resume(co)
foo activation
frame
bar activation
frame
Park
coroutine
stack
74. STACKFUL
COROUTINES
STACK
main activation
frame
function foo(a, b)
print("foo", a)
bar("foo", b)
end
function bar(caller, x)
print(“bar: ", caller)
coroutine.yield()
print(“bar", x)
end
co = coroutine.create(foo)
coroutine.resume(co, 1, 2)
print(“main”)
coroutine.resume(co)
foo activation
frame
bar activation
frame
75. STACKFUL
COROUTINES
STACK
main activation
frame
function foo(a, b)
print("foo", a)
bar("foo", b)
end
function bar(caller, x)
print(“bar: ", caller)
coroutine.yield()
print(“bar", x)
end
co = coroutine.create(foo)
coroutine.resume(co, 1, 2)
print(“main”)
coroutine.resume(co)
foo activation
frame
bar activation
frame
print activation
frame
76. STACKFUL
COROUTINES
STACK
main activation
frame
function foo(a, b)
print("foo", a)
bar("foo", b)
end
function bar(caller, x)
print(“bar: ", caller)
coroutine.yield()
print(“bar", x)
end
co = coroutine.create(foo)
coroutine.resume(co, 1, 2)
print(“main”)
coroutine.resume(co)
foo activation
frame
bar activation
frame
Resume
coroutine
stack
77. STACKFUL
COROUTINES
STACK
main activation
frame
function foo(a, b)
print("foo", a)
bar("foo", b)
end
function bar(caller, x)
print(“bar: ", caller)
coroutine.yield()
print(“bar", x)
end
co = coroutine.create(foo)
coroutine.resume(co, 1, 2)
print(“main”)
coroutine.resume(co)
foo activation
frame
bar activation
frame
78. STACKFUL
COROUTINES
STACK
main activation
frame
function foo(a, b)
print("foo", a)
bar("foo", b)
end
function bar(caller, x)
print(“bar: ", caller)
coroutine.yield()
print(“bar", x)
end
co = coroutine.create(foo)
coroutine.resume(co, 1, 2)
print(“main”)
coroutine.resume(co)
foo activation
frame
bar activation
frame
print activation
frame
79. WHAT IS THE CORRECT STACK SIZE FOR EACH
COROUTINE?
82. ASYNC/AWAIT UNITY COROUTINES
IEnumerable WaitAndPrint()
{
print("Starting at " + Time.time);
yield return new WaitForSeconds(0.1f);
print("Ending at " + Time.time);
}
async Task WaitAndPrint()
{
Console.WriteLine("Starting at " + DateTime.Now);
await Task.Delay(100);
Console.WriteLine("Ending at " + DateTime.Now);
}
83. INTEGRATING TPL AND LINQ
public static class TaskExtensions
{
public static Task<T3> SelectMany<T1, T2, T3>(
this Task<T1> task,
Func<T1, Task<T2>> binding,
Func<T1, T2, T3> combine)
{
var tcs = new TaskCompletionSource<T3>();
task.ContinueWith(t1 =>
{
if (t1.IsFaulted) tcs.SetException(t1.Exception);
else if (t1.IsCanceled) tcs.SetCanceled();
else binding(t1.Result).ContinueWith(t2 =>
{
if (t2.IsFaulted) tcs.SetException(t2.Exception);
else if (t2.IsCanceled) tcs.SetCanceled();
else tcs.SetResult(combine(t1.Result, t2.Result));
});
});
return tcs.Task;
}
}
public static Task Rename(int userId, string name)
{
return from user in GetUser(userId)
from _ in SaveUser(user with { Name = name })
select 0;
}
85. WHAT YOU SEE WHAT YOU DON’T SEE
static class Program {
static async Task Foo(int a, int b) {
Console.WriteLine("Foo", a);
await Task.Yield();
Console.WriteLine("Foo", b);
}
}
struct Foo__0 : IStateMachine {
AsyncTaskMethodBuilder builder;
int state;
int a;
int b;
public void MoveNext() {
switch (this.state) {
case -1:
Console.WriteLine("Foo", this.a);
var awaiter = Taks.Yield().GetAwaiter();
this.state = 0;
this.builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
// ^ awaiter.OnComplete(() =>
// ThreadPool.QueueUserWorkItem(this.MoveNext));
return;
case 0:
Console.WriteLine("Foo", this.b);
builder.SetResult();
return;
}
}
}
static class Program {
static Task Foo(int a, int b) {
var builder = AsyncTaskMethodBuilder.Create();
var stateMachine = new Foo__0();
// initialize state machine fields
stateMachine.a = a;
stateMachine.b = b;
stateMachine.state = -1;
stateMachine.builder = builder;
builder.Start(ref stateMachine);
// ^ similar to: ThreadPool.QueueUserWorkItem(this.MoveNext);
return builder.Task;
}
}
86. WHAT YOU SEE WHAT YOU DON’T SEE
static class Program {
static async Task Foo(int a, int b) {
Console.WriteLine("Foo", a);
await Task.Yield();
Console.WriteLine("Foo", b);
}
}
struct Foo__0 : IStateMachine {
AsyncTaskMethodBuilder builder;
int state;
int a;
int b;
public void MoveNext() {
switch (this.state) {
case -1:
Console.WriteLine("Foo", this.a);
var awaiter = Taks.Yield().GetAwaiter();
this.state = 0;
this.builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
// ^ awaiter.OnComplete(() =>
// ThreadPool.QueueUserWorkItem(this.MoveNext));
return;
case 0:
Console.WriteLine("Foo", this.b);
builder.SetResult();
return;
}
}
}
static class Program {
static Task Foo(int a, int b) {
var builder = AsyncTaskMethodBuilder.Create();
var stateMachine = new Foo__0();
// initialize state machine fields
stateMachine.a = a;
stateMachine.b = b;
stateMachine.state = -1;
stateMachine.builder = builder;
builder.Start(ref stateMachine);
// ^ similar to: ThreadPool.QueueUserWorkItem(this.MoveNext);
return builder.Task;
}
}
87. WHAT YOU SEE WHAT YOU DON’T SEE
static class Program {
static async Task Foo(int a, int b) {
Console.WriteLine("Foo", a);
await Task.Yield();
Console.WriteLine("Foo", b);
}
}
struct Foo__0 : IStateMachine {
AsyncTaskMethodBuilder builder;
int state;
int a;
int b;
public void MoveNext() {
switch (this.state) {
case -1:
Console.WriteLine("Foo", this.a);
var awaiter = Taks.Yield().GetAwaiter();
this.state = 0;
this.builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
// ^ awaiter.OnComplete(() =>
// ThreadPool.QueueUserWorkItem(this.MoveNext));
return;
case 0:
Console.WriteLine("Foo", this.b);
builder.SetResult();
return;
}
}
}
static class Program {
static Task Foo(int a, int b) {
var builder = AsyncTaskMethodBuilder.Create();
var stateMachine = new Foo__0();
// initialize state machine fields
stateMachine.a = a;
stateMachine.b = b;
stateMachine.state = -1;
stateMachine.builder = builder;
builder.Start(ref stateMachine);
// ^ similar to: ThreadPool.QueueUserWorkItem(this.MoveNext);
return builder.Task;
}
}
88. WHAT YOU SEE WHAT YOU DON’T SEE
static class Program {
static async Task Foo(int a, int b) {
Console.WriteLine("Foo", a);
await Task.Yield();
Console.WriteLine("Foo", b);
}
}
struct Foo__0 : IStateMachine {
AsyncTaskMethodBuilder builder;
int state;
int a;
int b;
public void MoveNext() {
switch (this.state) {
case -1:
Console.WriteLine("Foo", this.a);
var awaiter = Taks.Yield().GetAwaiter();
this.state = 0;
this.builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
// ^ awaiter.OnComplete(() =>
// ThreadPool.QueueUserWorkItem(this.MoveNext));
return;
case 0:
Console.WriteLine("Foo", this.b);
builder.SetResult();
return;
}
}
}
static class Program {
static Task Foo(int a, int b) {
var builder = AsyncTaskMethodBuilder.Create();
var stateMachine = new Foo__0();
// initialize state machine fields
stateMachine.a = a;
stateMachine.b = b;
stateMachine.state = -1;
stateMachine.builder = builder;
builder.Start(ref stateMachine);
// ^ similar to: ThreadPool.QueueUserWorkItem(this.MoveNext);
return builder.Task;
}
}
89. WHAT YOU SEE WHAT YOU DON’T SEE
static class Program {
static async Task Foo(int a, int b) {
Console.WriteLine("Foo", a);
await Task.Yield();
Console.WriteLine("Foo", b);
}
}
struct Foo__0 : IStateMachine {
AsyncTaskMethodBuilder builder;
int state;
int a;
int b;
public void MoveNext() {
switch (this.state) {
case -1:
Console.WriteLine("Foo", this.a);
var awaiter = Taks.Yield().GetAwaiter();
this.state = 0;
this.builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
// ^ awaiter.OnComplete(() =>
// ThreadPool.QueueUserWorkItem(this.MoveNext));
return;
case 0:
Console.WriteLine("Foo", this.b);
builder.SetResult();
return;
}
}
}
static class Program {
static Task Foo(int a, int b) {
var builder = AsyncTaskMethodBuilder.Create();
var stateMachine = new Foo__0();
// initialize state machine fields
stateMachine.a = a;
stateMachine.b = b;
stateMachine.state = -1;
stateMachine.builder = builder;
builder.Start(ref stateMachine);
// ^ similar to: ThreadPool.QueueUserWorkItem(this.MoveNext);
return builder.Task;
}
}
90. WHAT YOU SEE WHAT YOU DON’T SEE
static class Program {
static async Task Foo(int a, int b) {
Console.WriteLine("Foo", a);
await Task.Yield();
Console.WriteLine("Foo", b);
}
}
struct Foo__0 : IStateMachine {
AsyncTaskMethodBuilder builder;
int state;
int a;
int b;
public void MoveNext() {
switch (this.state) {
case -1:
Console.WriteLine("Foo", this.a);
var awaiter = Taks.Yield().GetAwaiter();
this.state = 0;
this.builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
// ^ awaiter.OnComplete(() =>
// ThreadPool.QueueUserWorkItem(this.MoveNext));
return;
case 0:
Console.WriteLine("Foo", this.b);
builder.SetResult();
return;
}
}
}
static class Program {
static Task Foo(int a, int b) {
var builder = AsyncTaskMethodBuilder.Create();
var stateMachine = new Foo__0();
// initialize state machine fields
stateMachine.a = a;
stateMachine.b = b;
stateMachine.state = -1;
stateMachine.builder = builder;
builder.Start(ref stateMachine);
// ^ similar to: ThreadPool.QueueUserWorkItem(this.MoveNext);
return builder.Task;
}
}
91. WHAT YOU SEE WHAT YOU DON’T SEE
static class Program {
static async Task Foo(int a, int b) {
Console.WriteLine("Foo", a);
await Task.Yield();
Console.WriteLine("Foo", b);
}
}
struct Foo__0 : IStateMachine {
AsyncTaskMethodBuilder builder;
int state;
int a;
int b;
public void MoveNext() {
switch (this.state) {
case -1:
Console.WriteLine("Foo", this.a);
var awaiter = Taks.Yield().GetAwaiter();
this.state = 0;
this.builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
// ^ awaiter.OnComplete(() =>
// ThreadPool.QueueUserWorkItem(this.MoveNext));
return;
case 0:
Console.WriteLine("Foo", this.b);
builder.SetResult();
return;
}
}
}
static class Program {
static Task Foo(int a, int b) {
var builder = AsyncTaskMethodBuilder.Create();
var stateMachine = new Foo__0();
// initialize state machine fields
stateMachine.a = a;
stateMachine.b = b;
stateMachine.state = -1;
stateMachine.builder = builder;
builder.Start(ref stateMachine);
// ^ similar to: ThreadPool.QueueUserWorkItem(this.MoveNext);
return builder.Task;
}
}
92. WHAT YOU SEE WHAT YOU DON’T SEE
static class Program {
static async Task Foo(int a, int b) {
Console.WriteLine("Foo", a);
await Task.Yield();
Console.WriteLine("Foo", b);
}
}
struct Foo__0 : IStateMachine {
AsyncTaskMethodBuilder builder;
int state;
int a;
int b;
public void MoveNext() {
switch (this.state) {
case -1:
Console.WriteLine("Foo", this.a);
var awaiter = Taks.Yield().GetAwaiter();
this.state = 0;
this.builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
// ^ awaiter.OnComplete(() =>
// ThreadPool.QueueUserWorkItem(this.MoveNext));
return;
case 0:
Console.WriteLine("Foo", this.b);
builder.SetResult();
return;
}
}
}
static class Program {
static Task Foo(int a, int b) {
var builder = AsyncTaskMethodBuilder.Create();
var stateMachine = new Foo__0();
// initialize state machine fields
stateMachine.a = a;
stateMachine.b = b;
stateMachine.state = -1;
stateMachine.builder = builder;
builder.Start(ref stateMachine);
// ^ similar to: ThreadPool.QueueUserWorkItem(this.MoveNext);
return builder.Task;
}
}
93. WHAT YOU SEE WHAT YOU DON’T SEE
static class Program {
static async Task Foo(int a, int b) {
Console.WriteLine("Foo", a);
await Task.Yield();
Console.WriteLine("Foo", b);
}
}
struct Foo__0 : IStateMachine {
AsyncTaskMethodBuilder builder;
int state;
int a;
int b;
public void MoveNext() {
switch (this.state) {
case -1:
Console.WriteLine("Foo", this.a);
var awaiter = Taks.Yield().GetAwaiter();
this.state = 0;
this.builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
// ^ awaiter.OnComplete(() =>
// ThreadPool.QueueUserWorkItem(this.MoveNext));
return;
case 0:
Console.WriteLine("Foo", this.b);
builder.SetResult();
return;
}
}
}
static class Program {
static Task Foo(int a, int b) {
var builder = AsyncTaskMethodBuilder.Create();
var stateMachine = new Foo__0();
// initialize state machine fields
stateMachine.a = a;
stateMachine.b = b;
stateMachine.state = -1;
stateMachine.builder = builder;
builder.Start(ref stateMachine);
// ^ similar to: ThreadPool.QueueUserWorkItem(this.MoveNext);
return builder.Task;
}
}
94. WHAT YOU SEE WHAT YOU DON’T SEE
static class Program {
static async Task Foo(int a, int b) {
Console.WriteLine("Foo", a);
await Task.Yield();
Console.WriteLine("Foo", b);
}
}
struct Foo__0 : IStateMachine {
AsyncTaskMethodBuilder builder;
int state;
int a;
int b;
public void MoveNext() {
switch (this.state) {
case -1:
Console.WriteLine("Foo", this.a);
var awaiter = Taks.Yield().GetAwaiter();
this.state = 0;
this.builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
// ^ awaiter.OnComplete(() =>
// ThreadPool.QueueUserWorkItem(this.MoveNext));
return;
case 0:
Console.WriteLine("Foo", this.b);
builder.SetResult();
return;
}
}
}
static class Program {
static Task Foo(int a, int b) {
var builder = AsyncTaskMethodBuilder.Create();
var stateMachine = new Foo__0();
// initialize state machine fields
stateMachine.a = a;
stateMachine.b = b;
stateMachine.state = -1;
stateMachine.builder = builder;
builder.Start(ref stateMachine);
// ^ similar to: ThreadPool.QueueUserWorkItem(this.MoveNext);
return builder.Task;
}
}
95. WHAT YOU SEE WHAT YOU DON’T SEE
static class Program {
static async Task Foo(int a, int b) {
Console.WriteLine("Foo", a);
await Task.Yield();
Console.WriteLine("Foo", b);
}
}
struct Foo__0 : IStateMachine {
AsyncTaskMethodBuilder builder;
int state;
int a;
int b;
public void MoveNext() {
switch (this.state) {
case -1:
Console.WriteLine("Foo", this.a);
var awaiter = Taks.Yield().GetAwaiter();
this.state = 0;
this.builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
// ^ awaiter.OnComplete(() =>
// ThreadPool.QueueUserWorkItem(this.MoveNext));
return;
case 0:
Console.WriteLine("Foo", this.b);
builder.SetResult();
return;
}
}
}
static class Program {
static Task Foo(int a, int b) {
var builder = AsyncTaskMethodBuilder.Create();
var stateMachine = new Foo__0();
// initialize state machine fields
stateMachine.a = a;
stateMachine.b = b;
stateMachine.state = -1;
stateMachine.builder = builder;
builder.Start(ref stateMachine);
// ^ similar to: ThreadPool.QueueUserWorkItem(this.MoveNext);
return builder.Task;
}
}
96. WHAT YOU SEE WHAT YOU DON’T SEE
static class Program {
static async Task Foo(int a, int b) {
Console.WriteLine("Foo", a);
await Task.Yield();
Console.WriteLine("Foo", b);
}
}
struct Foo__0 : IStateMachine {
AsyncTaskMethodBuilder builder;
int state;
int a;
int b;
public void MoveNext() {
switch (this.state) {
case -1:
Console.WriteLine("Foo", this.a);
var awaiter = Taks.Yield().GetAwaiter();
this.state = 0;
this.builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
// ^ awaiter.OnComplete(() =>
// ThreadPool.QueueUserWorkItem(this.MoveNext));
return;
case 0:
Console.WriteLine("Foo", this.b);
builder.SetResult();
return;
}
}
}
static class Program {
static Task Foo(int a, int b) {
var builder = AsyncTaskMethodBuilder.Create();
var stateMachine = new Foo__0();
// initialize state machine fields
stateMachine.a = a;
stateMachine.b = b;
stateMachine.state = -1;
stateMachine.builder = builder;
builder.Start(ref stateMachine);
// ^ similar to: ThreadPool.QueueUserWorkItem(this.MoveNext);
return builder.Task;
}
}
97. WHAT YOU SEE WHAT YOU DON’T SEE
static class Program {
static async Task Foo(int a, int b) {
Console.WriteLine("Foo", a);
await Task.Yield();
Console.WriteLine("Foo", b);
}
}
struct Foo__0 : IStateMachine {
AsyncTaskMethodBuilder builder;
int state;
int a;
int b;
public void MoveNext() {
switch (this.state) {
case -1:
Console.WriteLine("Foo", this.a);
var awaiter = Taks.Yield().GetAwaiter();
this.state = 0;
this.builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
// ^ awaiter.OnComplete(() =>
// ThreadPool.QueueUserWorkItem(this.MoveNext));
return;
case 0:
Console.WriteLine("Foo", this.b);
builder.SetResult();
return;
}
}
}
static class Program {
static Task Foo(int a, int b) {
var builder = AsyncTaskMethodBuilder.Create();
var stateMachine = new Foo__0();
// initialize state machine fields
stateMachine.a = a;
stateMachine.b = b;
stateMachine.state = -1;
stateMachine.builder = builder;
builder.Start(ref stateMachine);
// ^ similar to: ThreadPool.QueueUserWorkItem(this.MoveNext);
return builder.Task;
}
}
98. WHAT YOU SEE WHAT YOU DON’T SEE
static class Program {
static async Task Foo(int a, int b) {
Console.WriteLine("Foo", a);
await Task.Yield();
Console.WriteLine("Foo", b);
}
}
struct Foo__0 : IStateMachine {
AsyncTaskMethodBuilder builder;
int state;
int a;
int b;
public void MoveNext() {
switch (this.state) {
case -1:
Console.WriteLine("Foo", this.a);
var awaiter = Taks.Yield().GetAwaiter();
this.state = 0;
this.builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
// ^ awaiter.OnComplete(() =>
// ThreadPool.QueueUserWorkItem(this.MoveNext));
return;
case 0:
Console.WriteLine("Foo", this.b);
builder.SetResult();
return;
}
}
}
static class Program {
static Task Foo(int a, int b) {
var builder = AsyncTaskMethodBuilder.Create();
var stateMachine = new Foo__0();
// initialize state machine fields
stateMachine.a = a;
stateMachine.b = b;
stateMachine.state = -1;
stateMachine.builder = builder;
builder.Start(ref stateMachine);
// ^ similar to: ThreadPool.QueueUserWorkItem(this.MoveNext);
return builder.Task;
}
}
99. WHAT YOU SEE WHAT YOU DON’T SEE
static class Program {
static async Task Foo(int a, int b) {
Console.WriteLine("Foo", a);
await Task.Yield();
Console.WriteLine("Foo", b);
}
}
struct Foo__0 : IStateMachine {
AsyncTaskMethodBuilder builder;
int state;
int a;
int b;
public void MoveNext() {
switch (this.state) {
case -1:
Console.WriteLine("Foo", this.a);
var awaiter = Taks.Yield().GetAwaiter();
this.state = 0;
this.builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
// ^ awaiter.OnComplete(() =>
// ThreadPool.QueueUserWorkItem(this.MoveNext));
return;
case 0:
Console.WriteLine("Foo", this.b);
builder.SetResult();
return;
}
}
}
static class Program {
static Task Foo(int a, int b) {
var builder = AsyncTaskMethodBuilder.Create();
var stateMachine = new Foo__0();
// initialize state machine fields
stateMachine.a = a;
stateMachine.b = b;
stateMachine.state = -1;
stateMachine.builder = builder;
builder.Start(ref stateMachine);
// ^ similar to: ThreadPool.QueueUserWorkItem(this.MoveNext);
return builder.Task;
}
}
100. AWAITER PATTERN
Custom awaitable objects
public readonly struct PromiseAwaiter<T> : INotifyCompletion
{
private readonly Promise<T> promise;
public PromiseAwaiter(Promise<T> promise)
{
this.promise = promise;
}
#region mandatory awaiter methods
public bool IsCompleted => promise.IsCompleted;
public T GetResult() => promise.Result;
public void OnCompleted(Action continuation) => promise.RegisterContinuation(continuation);
#endregion
}
101. ASYNC METHOD BUILDER
Custom async methods
public struct PromiseAsyncMethodBuilder<T>
{
private Promise<T>? promise;
#region mandatory methods for async state machine builder
public static PromiseAsyncMethodBuilder<T> Create() => default;
public Promise<T> Task => promise ??= new Promise<T>();
public void SetException(Exception e) => Task.TrySetException(e);
public void SetResult(T result) => Task.TrySetResult(result);
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : INotifyCompletion
where TStateMachine : IAsyncStateMachine { }
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : ICriticalNotifyCompletion
where TStateMachine : IAsyncStateMachine { }
public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine { }
public void SetStateMachine(IAsyncStateMachine stateMachine) { }
#endregion
}
104. Custom AsyncMethodBuilder “docs”: https://github.com/dotnet/roslyn/blob/master/docs/features/task-types.md
Building custom (affine) thread pool: https://bartoszsypytkowski.com/thread-safety-with-affine-thread-pools/
What color is your function?: https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/
How Go scheduler works: https://www.youtube.com/watch?v=-K11rY57K7k
Thread per core architecture: https://www.datadoghq.com/blog/engineering/introducing-glommio/
REFERENCES