异步javascript的语义外文翻译资料

 2022-12-19 17:40:33

emantics of Asynchronous JavaScript

Matthew C. Loring

Google Inc, USA mattloring@google.com

Mark Marron

Microsoft Research, USA marron@microsoft.com

Daan Leijen

Microsoft Research, USA daan@microsoft.com

Abstract

The Node.js runtime has become a major platform for developers building cloud, mobile, or IoT applications using

JavaScript. Since the JavaScript language is single threaded, Node.js programs must make use of asynchronous callbacks and event loops managed by the runtime to ensure applications remain responsive. While conceptually simple, this programming model contains numerous subtleties and behaviors that are defined implicitly by the current Node.js implementation. This paper presents the first comprehensive formalization of the Node.js asynchronous execution model and defines a high-level notion of async-contexts to formalize fundamental relationships between asynchronous events in an application. These formalizations provide a foundation for the construction of static or dynamic program analysis tools, support the exploration of alternative Node.js event loop implementations, and provide a high-level conceptual framework for reasoning about relationships between the execution of asynchronous callbacks in a Node.js application.

CCSConceptsbull; Software and its engineering → Control structures; Semantics;

Keywords: JavaScript, Asynchrony

ACM Reference Format:

Matthew C. Loring, Mark Marron, and Daan Leijen. 2017. Semantics of Asynchronous JavaScript . In Proceedings of 13th ACM SIGPLAN International Symposium on Dynamic Languages (DLS17). ACM,

New York, NY, USA, Article 1, 12 pages. https://doi.org/10.1145/3133841.3133846

1 Introduction

JavaScript is one of the most popular programming languages in use today and is rapidly expanding beyond its traditional role of client-side scripting. Node.js is a major platform for building JavaScript applications for the server, cloud, mobile, and IoT platforms. This rapid growth in popularity and usage has resulted in a growing demand from developers for information on how to best use the many asynchronous APIs exposed by Node.js and for tools that can help develop [15], debug [4], or monitor [10, 24] the asynchronous behavior of their applications.

1.1 Semantics of Node Event Queues

A major challenge for research and tooling development for Node.js is the lack of a formal specification of the Node.js asynchronous execution model. This execution model involves multiple event queues, some implemented in the native C runtime, others in the Node.js standard library API bindings, and still others defined by the JavaScript ES6 promise language feature. These queues have different rules regarding when they are processed, how processing is interleaved, and how/where new events are added to each queue. These subtleties are often the difference between a responsive and scalable application and one that exhibits a critical

failure.

Consider the following pair of programs that differ in only the use of a single Node API – process.nextTick(cb) (in Figure 1) vs. setImmediate(cb) (in Figure 2):

var cb = function() { process.nextTick(cb); } fs.write(process.stdout.fd, hi, function() {

/*never printed*/ fs.writeSync(process.stdout.fd, done);

}); cb();

Fig. 1. nextTick starvation of fs.write callback

var cb = function() { setImmediate(cb); }; fs.write(process.stdout.fd, hi, function() { /*printed in finite time*/ fs.writeSync(process.stdout.fd, done);

}); cb();

Fig. 2. setImmediate scheduling setImmediate is fair

The first line of Figure 1 defines a function that, when called, will register itself to be executed again “once the current turn of the event loop turn runs to completion” [18]. The second line initiates an asynchronous write to stdout which, when completed, will invoke the argument callback which synchronously prints done to stdout. Finally, the function cb is invoked. At the end of this code block, Node will return to the event loop and begin dispatching from the various queues.

Based on the Node.js event loop implementation, the first callback dispatched will be cb registered by nextTick even though this was added to the event loops after fs.write callback.Further, the code will never print done to the console. Each call to nextTick inserts the cb callback in a special nextTick queue which is drained before any other I/O events. This results in the starvation of any I/O tasks including the callback that contains the fs.writeSync call.If, instead of using nextTick, we use setImmediate as shown in the code block in Figure 2, then we should see done printed in the first iteration of the event loop . This different behavior is due to the fact that setImmediate places the callbacks in another special queue that is drained after some (but perhaps not all) pending I/O based callbacks have been executed. This interleaving ensures that both the I/O and timer based callback computations will make progress thus avoiding starvation.

As can be seen in this example, it is not possible to realistically model the semantics of a Node application using a single queue or even a single queue draining rule [15]. Thus, our first goal in this work is to construct a realistic formalization of asynchronous execution in a Node application.

1.2 Asynchronous Execution Context

During the execution of a program there may be many asynchronous callbacks simultaneously queued for execution. These callbacks may be associated with different logical tasks such as requests in the case of a web server. For many applications preserving the logical identity of a distinct asynchronous execution chain is critical. For example a developer debugging their application m

剩余内容已隐藏,支付完成后下载完整资料


异步javascript的语义

马修·C·洛林

谷歌公司,美国mattloring@google.com

马克马龙

Microsoft Research,美国marron@microsoft.com

大安雷人

微软研究,美国daan@microsoft.com

摘要

JS运行时已经成为开发人员使用JavaScript构建云、移动或物联网应用程序的主要平台。由于javascript语言是单线程的,node.js程序必须使用由运行时管理的异步回调和事件循环,以确保应用程序保持响应。虽然概念上很简单,但是这个编程模型包含许多由当前node.js实现隐式定义的微妙之处和行为。本文介绍了node.js异步执行模型的第一个全面形式化,并定义了异步上下文的高级概念,以形式化应用程序中异步事件之间的基本关系。这些形式化为静态或动态程序分析工具的构建提供了基础,支持探索替代NoDE.JS事件循环实现,并提供了一个高层概念框架,用于推理NoDE.JS应用程序中异步回调的执行之间的关系。

CCSS概念bull;软件及其工程设计→control结构;语义;

关键字:javascript,异步

ACM参考格式:Matthew C. Loring, Mark Marron, and Daan Leijen. 2017. Semantics of Asynchronous JavaScript . In Proceedings of 13th ACM SIGPLAN International Symposium on Dynamic Languages (DLS17). ACM,

New York, NY, USA, Article 1, 12 pages. https://doi.org/10.1145/3133841.3133846

1引言

JavaScript是当今最流行的编程语言之一,它正在迅速扩展,超越其传统的客户端脚本功能。node.js是为服务器、云、移动和物联网平台构建JavaScript应用程序的主要平台。这种普及率和使用率的快速增长导致了开发人员对如何最好地使用大量信息的需求不断增长。node.js和可以帮助开发[15]、调试[4]或监视[10,24]应用程序异步行为的工具公开了异步API。

1.1节点事件队列的语义

node.js研究和工具开发的一个主要挑战是缺少node.js异步执行模型的正式规范。这个执行模型涉及多个事件队列,一些在本地C 运行时实现,另一些在NoDE.JS标准库API绑定中执行,还有一些由JavaScript ES6承诺语言特征定义。这些队列在处理它们的时间、如何交错处理以及如何/在何处向每个队列添加新事件方面有不同的规则。这些微妙之处通常是响应性和可扩展性应用程序与显示关键失败。

考虑以下两种程序,它们仅在使用单节点api-process.nextick(cb)(图1)与setimmediate(cb)(图2)时有所不同:

var cb = function() { process.nextTick(cb); } fs.write(process.stdout.fd, hi, function() {

/*never printed*/ fs.writeSync(process.stdout.fd, done);

}); cb();

图1.fs.write回调的nextick匮乏

var cb = function() { setImmediate(cb); }; fs.write(process.stdout.fd, hi, function() { /*printed in finite time*/ fs.writeSync(process.stdout.fd, done);

}); cb();

图2.setimmediate调度setimmediate是公平的

图1的第一行定义了一个函数,当调用它时,它将注册自己以便“一旦事件循环的当前循环运行到完成时”再次执行[18]。第二行启动对stdout的异步写入,完成后,将调用参数回调,该回调将“done”同步打印到stdout。最后,调用函数cb。在该代码块的末尾,节点将返回到事件循环,并开始从各个队列进行调度。

基于node.js事件循环实现,发送的第一个回调将由nextick注册,即使它是在fs.write回调之后添加到事件循环中的。此外,代码将永远不会打印“完成”到控制台。对nextick的每个调用都将cb回调插入到一个特殊的nextick队列中,该队列先于其他队列排出。

输入输出事件。这会导致任何I/O任务(包括包含fs.writeSync调用的回调)不足。

如果不使用nextick,而是使用setimmediate,如图2中的代码块所示,那么我们应该看到“完成”。

在事件循环的第一个迭代中打印。这种不同的行为是由于setimmediate将回调放在另一个特殊队列中,该队列在执行了一些(但可能不是全部)基于I/O的挂起回调之后被排出。这种交错确保了I/O和基于计时器的回调计算都将取得进展,从而避免了饥饿。

如本例所示,不可能使用单个队列甚至单个队列排出规则对节点应用程序的语义进行实际建模[15]。因此,本文的第一个目标是在节点应用程序中构造异步执行的实际形式化。

1.2异步执行上下文

在程序执行期间,可能会有许多异步回调同时排队等待执行。这些回调可能与不同的逻辑任务相关联,例如Web服务器的请求。对于许多应用程序来说,保留不同异步执行链的逻辑标识至关重要。例如,开发人员

调试他们的应用程序可能只希望看到与处理感兴趣的单个HTTP请求相关联的日志输出,或者了解响应请求所花费的时间以及专门处理请求所花费的周期(而不是在I/O上被阻塞或等待其他工作完成)。

考虑到理解和跟踪node.js应用程序中异步执行上下文的重要性,社区开发了几个跟踪异步回调的框架,例如区域[26]、异步挂钩[12]和堆栈[25]。从根本上讲,每个系统都基于一个非正式定义的关系,该关系将异步回调添加到工作列表的点和回调出列和调用的点关联起来。

尽管异步上下文的概念很重要,并且有许多工具提供了这种上下文的一些变化,但是目前工具之间对于异步事件链中的链接的构成没有广泛的共识。这种情况因缺乏对什么是异步上下文进行形式化,如果相同的上下文定义对所有应用程序都足够,或者实际上对上下文有多个有用的定义。因此,本文的第二个目标是以独立于特定工作列表实现(如当前节点实现)的方式形式化异步上下文的概念,并展示如何根据高级语言和API定义计算此上下文。

总之,本文作出了以下贡献:

bull;我们引入了lambda;async,它用Promise语义和微任务队列/事件循环扩展了lambda;js,以实现node.js异步执行语义的形式化。

bull;在lambda;异步语义的基础上,我们定义了因果上下文的概念,并将上下文与理性联系起来。-

关于应用程序中的异步上下文,并提供用于计算它们的上下文传播规则。

bull;我们用race检测和调试示例说明这些概念和形式化如何支持现有应用程序。

bull;我们展示了事件循环语义和异步上下文的形式化如何进一步研究node.js的资源感知优先级调度程序的设计和开发。

2 node.js异步事件循环

为了精确定义异步上下文的语义,我们必须首先为node.js中可用的异步原语的运行时行为提供一个准确的模型。为了解决这个问题,我们定义了使用异步原语扩展lambda;js[11]的lambda;async。特别是,我们在优先级承诺方面统一定义node.js和javascript承诺的异步回调。优先权Promise具有JavaScriptPromise的核心语义,并用优先级值进行了扩展。在本文中,我们还省略了真实JavaScript承诺的许多特性,比如异常处理和链接,这些特性可以用我们所建模的原语表示。同样,我们也不讨论新的ES2017异步/等待语法,因为这些操作也可以用常规的承诺来表示。

2.1语法

图3定义了lambda;async的扩展语法。为了简洁起见,我们只呈现在lambda;js上添加的额外构造。

值v是常规的javascript值或优先级承诺。这个。。。代表[11]中所述的lambda;js中的定义,基本上是常数、函数和记录。新的优先级承诺是三重的(n,r,fs),优先级级别为n,值为r,对于未解决的承诺为unrest,或者对于已解决的承诺为res(v),以及一个待定回调fs列表。

visin; Val

::=

...

|

(n,r,fs)

promise tuple

r

::=

unres

unresolved

|

res(v)

resolved to v

fs

::=

[f1, ...,fm]

callbacks

n

priority levels

eisin; Exp

::=

...

|

Promise()

create a promise

|

e.resolve(e)

resolve a promise

|

e.then(e)

add a listener

|

bull;

the event loop

图3.lambda;async的语法。

表达式e扩展为三个操作,用于实现承诺:

bull;()创造了一个新的承诺(优先级为0)。许诺

bull;1.解决(e2)将承诺e1解决为e2的值。e

bull;1.然后(e2)在承诺e1解决后,安排e2执行。e

此接口与常规承诺不同,其中解析方法(通常)是隐藏的,并且Promise的构造函数函数将函数作为参数:javascript Promise(f)创建一个异步执行f的新Promise,当它返回值时,Promise解析为该值。在我们的模型中,这可以表示为:

function Promise(f) {

var p = Promise(); process.nextTick( function() {

p.resolve(f());

}); return p;

}

最后,使用特殊的bull;表达式允许执行与异步计算关联的回调。javascript具有“运行到完成”的语义,这意味着一旦调用了一个javascript函数,该函数以及同步调用的任何其他函数都将在终止之前不被抢先运行。当到达特殊的bull;表达式时,控件返回到运行时,允许它根据第2.3节中描述的语义刷新其工作队列。

2.2重点

我们使用优先级在node.js中使用单个抽象实现异步语义的建模。我们对常规承诺的行为特别感兴趣,.then,settimeout,setimmediate,regular asynchronous I/O,and process.nextick。事实证明我们可以模拟所有这些行为。

使用单一优先级机制的概念。我们将以下优先事项分配给各种操作:

0. 对于process.nextick和常规承诺,即微任务排队;

1. 为了西米替米特;

2. 对于StimTimeUT;

3. 对于所有其他异步I/O,例如readfile等。

为了将所有操作建模为优先级承诺,我们假设一个初始堆h0,其中包含以下始

剩余内容已隐藏,支付完成后下载完整资料


资料编号:[19826],资料为PDF文档或Word文档,PDF文档可免费转换为Word

原文和译文剩余内容已隐藏,您需要先支付 30元 才能查看原文和译文全部内容!立即支付

以上是毕业论文外文翻译,课题毕业论文、任务书、文献综述、开题报告、程序设计、图纸设计等资料可联系客服协助查找。