WebAssembly,Web的新时代-程序员宅基地

在浏览器之争中,Chrome凭借JavaScript的卓越性能取得了市场主导地位,然而由于JavaScript的无类型特性,导致其运行时消耗大量的性能做为代价,这也是JavaScript的瓶颈之一。WebAssembly旨在解决这一问题。本文从WebAssembly的起源到开发实践对其做全面探究,帮助开发者对WebAssembly有全面的了解。

缘起

让我们从浏览器大战说起。微软凭借Windows系统捆绑Internet Explorer的先天优势击溃Netscape后,进入了长达数年的静默期。而Netscape则于1998年将Communicator开源,并由Mozilla基金会衍生出Firefox浏览器,在2004年发布了1.0版本。从此,第二次浏览器大战拉开帷幕。这场大战由Firefox浏览器领衔,Safari、Opera等浏览器也积极进取,Internet Explorer的主导地位首次受到挑战。2008年Google推出Chrome浏览器,不但逐步侵蚀Firefox的市场,更是压制了老迈的Internet Explorer。在此次大战之后的2012年,StatCounter的数据指出Chrome以微弱优势超越Internet Explorer成为世界上最流行的浏览器。

分析Google Chrome浏览器战胜Internet Explorer的原因,除了对Web标准更友善的支持外,卓越的性能是其中相当重要的因素,而浏览器性能之争的本质则体现在JavaScript引擎。此前,JavaScript引擎的实现方式经历了遍历语法树到字节码解释器等较为原始的方式,将每条源代码翻译成相应的机器码并执行,并不保存翻译后的机器码,使得解释执行很慢。2008年9月,Google发布了V8 JavaScript引擎。V8被设计用于提高Web浏览器中JavaScript的执行性能,通过即时编译JIT(Just-In-Time)技术,在执行时将JavaScript代码编译成更为高效的机器代码并保存,下次执行同一代码段时无需再编译,使得JavaScript获得了几十倍的性能提升。

然而,JavaScript是个无类型(untyped,变量没有类型)的语言,这直接导致表达式c=a+b有多重含义:

  • a、b均为数字,则算术运算符+表示值相加;
  • a、b为字符串,则+运算符表示字符串连接;
  •  …

表达式执行时,JIT编译器需要检查a和b的类型,确定操作行为。若a、b均为数字,JIT编译器则将a、b确认为整型,而一旦某一变量变成字符串,JIT编译器则不得不将之前编译的机器码推倒重来。由此可见,JavaScript的无类型特性建立在消耗大量性能代价的基础之上。即便JIT编译器在对变量类型发生变化时已进行相应优化,但仍然有很多情况JavaScript引擎未进行或无法优化,例如for-of、try-catch、try-finally、with语句以及复合let、const赋值的函数等。

由此可见,JavaScript的无类型是JavaScript引擎的性能瓶颈之一,改进方案有两种:一是设计一门新的强类型语言并强制开发者进行类型指定;二是给现有的JavaScript加上变量类型。

微软开发的TypeScript属于第一种改进方案。它是扩展了JavaScript特性的语言,包含了类型批注,编译时类型检查,类型推断和擦除等功能,TypeScript开发者在声明变量时指定类型,使得JavaScript引擎能够更快将这种强类型的语言编译成弱类型。

看看第二种方案:

图片描述

代码1

代码1表示带有两个参数(a和b)的JavaScript函数,和通常JavaScript代码不同的地方在于a=a | 0及b=b | 0,以及返回值后面均利用标注进行了按位OR操作。这么做的优点是使JavaScript引擎强制转换变量的值为整型执行。通过标注加上变量类型,JavaScript引擎就能更快地编译。

既然增加变量类型能够提升Web性能,有没有办法将静态类型代码例如C/C++等转换成JavaScript指令的子集呢?上面的这段代码恰恰是作为JavaScript子集的asm.js,由代码2的C语言编译而来:

图片描述

代码2

事实上,早在1995年起就已经有Netscape Plugin API(NPAPI)在内的可以使用浏览器运行C/C++程序的项目在开发。而2013年问世的asm.js是目前较为广泛的方案。asm.js是一种中间编程语言,允许用C/C++语言编写的计算机软件作为Web应用程序运行,并保持更好的性能,而Mozilla Firefox从版本22起成为第一个为asm.js特别优化的网页浏览器。

Google也同样在为原生代码运行在Web端而努力。Google Native Client(NaCl)采用沙盒技术,让Intel x86、ARM或MIPS子集的机器码直接在沙盒上运行。它能够在无需安装插件的情况下从浏览器直接运行原生可执行代码,使Web应用程序可以用接近于机器码运作的速度来运行。而Google Portable Native Client(PNaCl)则稍有变化,通过一些前端编译器将C/C++源代码编译成LLVM的中间字节码而不是x86或ARM代码,并且进行优化以及链接(如表1所示)。

图片描述

有了类型支持,第二种方案性能提升潜力远远大于第一种。

然而,无论是asm.js或现有PNaCl的解决方案,都面临着一些缺陷(例如1KB的C源码编译生成asm.js后的大小有480KB)或其他浏览器不支持的窘境,而2016年10月对Chromium问题跟踪代码的评论更是表明,Google Native Client小组已被关闭。

作为Web浏览器性能和代码重用的解决方案,asm.js及PNaCl都没能被普遍接受,那么有没有上述表格中的特性全部占优,且跨厂商的解决方案呢?

WebAssembly旨在解决这个问题。

新时代

WebAssembly(简称Wasm)是一种新的适合于编译到Web的,可移植的,大小和加载时间高效的格式。这是一个新的与平台无关的二进制代码格式,目标是解决JavaScript性能问题。这个新的二进制格式远小于JavaScript,可由浏览器的JavaScript引擎直接加载和执行,这样可节省从JavaScript到字节码,从字节码到执行前的机器码所花费的即时编译JIT(Just-In-Time)时间。 作为一种低级语言,它定义了一个抽象语法树(Abstract Syntax Tree,AST),开发人员可以以文本格式进行调试。

WebAssembly描述了一个内存安全的沙箱执行环境,可以在现有的JavaScript虚拟机中实现。 当嵌入到Web中时,WebAssembly将强制执行浏览器的同源和权限安全策略。因此,和经常出现安全漏洞的Flash插件相比,WebAssembly是一个更加安全的解决方案。

WebAssembly可由C/C++等语言编译而来。此外,WebAssembly由Google、Mozilla、微软以及苹果公司牵头的W3C社区组共同努力,基本覆盖主流的浏览器厂商,因此其可移植性相较Silverlight等有极大提升,平台兼容问题将不复出现。

在Web平台的很多项目中,对于原生新功能的支持需要Web浏览器或Runtime提供复杂的标准化的API来实现,但是JavaScript API往往较慢。使用WebAssembly,这些标准API可以更简单,并且操作在更低的水平。例如,对于一个面部识别的Web项目,对于访问数据流我们可以由简单的JavaScript API实现,而把面部识别原生SDK做的事情交由WebAssembly实现。

需要了解的是,WebAssembly不是将C/C++等其他语言编译到JavaScript,更不是一种新的编程语言。

探究

asm.js

上文的C语言求和代码经由编译器生成asm.js后如代码3所示。

图片描述

代码3

上述代码转换为WebAssembly的文本格式稍显复杂,为了理解方便,我们从精简的asm.js开始(见代码4)。

图片描述

代码4

wast文本文件

将asm.js代码转换为WebAssembly的文本格式 add.wast(转换工具见本文工具链章节,如代码5所示)。

图片描述

代码4

WebAssembly中代码的可装载和可执行单元被称为一个模块(module)。在运行时,一个模块可以被一组import值实例化,多个模块实例能够访问相同的共享状态。目前文本格式中的module主要用S表达式来表示。虽然S表达格式不是正式的文本格式,但它易于表示AST。WebAssembly也被设计为与ES6的modules集成。

一个单一的逻辑函数定义包含两个部分:功能部分声明在模块中每个内部函数定义的签名,代码段部分包含由功能部分声明的每个函数的函数体。WebAssembly是带有返回值的静态类型,并且所有参数都含有类型。上面的add.wast可以解读为:

  • 声明了一个名为$add的函数;
  • 包含两个参数 a b,两者都是32位整型;
  • 结果是一个32位整型;
  • 函数体是一个32位的加法:
  • 上面是局部变量$a得到的值;
  • 下面是局部变量$b得到的值;
  • 由于没有明确的返回节点,因此return是该加法函数的最后加载指令。

二进制Wasm文件

如图1所示,由C语言求和代码经过编译生成二进制文件,通读文件可以找到相应的头部、类型、导入、函数以及代码段等。通过JavaScript API载入Wasm二进制文件后,最终转换到机器码执行。

图片描述

图1 经过编译的二进制文件

工具链

开发人员现在可以使用相应的工具链从C / C ++源文件编译WebAssembly模块。WebAssembly由许多工具支持,以帮助开发人员构建和处理源文件和生成的二进制内容。

Emscripten

Emscripten是其中无法回避的工具之一,如图2所示。在图2中,Emscripten SDK管理器(emsdk)用于管理多个SDK和工具,并且指定当前正被使用到编译代码的特定SDK和工具集。

图片描述

图2 Emscripten工具链流程图及生成JavaScript(asm.js)流程

Emscripten的主要工具是Emscripten编译器前端(emcc),它是例如GCC的标准编译器的简易替代实现。

Emcc使用Clang将C/C++文件转换为LLVM(源自于底层虚拟机Low Level Virtual Machine)字节码,使用Fastcomp(Emscripten的编译器核心,一个LLVM后端)把字节码编译成JavaScript。输出的JavaScript可以由Node.js执行,或者嵌入HTML在浏览器中运行。这带来的直接结果就是,C和C++程序经过编译后可在JavaScript上运行,无需任何插件。

WABT和Binaryen

除此之外,对于想要使用由其他工具(如Emscripten)生成的WebAssembly二进制文件感兴趣的开发者,目前http://webassembly.org/官方额外提供了另外两组不同的工具:

  • WABT ——WebAssembly二进制工具包;
  • Binaryen——编译器和工具链。

WABT工具包支持将二进制WebAssembly格式转换为可读的文本格式。其中wasm2wast命令行工具可以将WebAssembly二进制文件转换为可读的S表达式文本文件。而wast2wasm命令行工具则执行完全相反的过程。

Binaryen则是一套更为全面的工具链,是用C++编写成用于WebAssembly的编译器和工具链基础结构库(如图3所示)。WebAssembly是二进制格式(Binary Format)并且和Emscripten集成,因此该工具以Binary和Emscript-en的末尾合并命名为Binaryen。它旨在使编译WebAssembly容易、快速、有效。它包含且不仅仅包含下面的几个工具。

图片描述

图3 Binaryen生成WebAssembly流程

  • wasm-as:将WebAssembly由文本格式(当前为S表达式格式)编译成二进制格式;
  • wasm-dis:将二进制格式的WebAssembly反编译成文本格式;
  • asm2wasm:将asm.js编译到WebAssembly文本格式,使用Emscripten的asm优化器;
  • s2wasm:在LLVM中开发,由新WebAssembly后端产生的.s格式的编译器;
  • wasm.js:包含编译为JavaScript的Binaryen组件,包括解释器、asm2wasm、S表达式解析器等。

Binaryen目前提供了两个生成WebAssembly的流程,由于emscripten的asm.js生成已经非常稳定,并且asm2wasm是一个相当简单的过程,所以这种将C/C ++编译为WebAssembly的方法已经可用(如图4所示)。

图片描述

图4 Emscripten+Binaryen生成WebAssembly的完整流程

由此可见,Emscripten以及Binaryen提供了完整的C/C++到WebAssembly的解决方案。而Binaryen则帮助提升了WebAssembly的工具链生态。

提示

由于WebAssembly正处于活跃开发阶段,各项编译步骤和编译工具会有大幅变更和改进,相信最终的编译工具和步骤会趋于便捷,开发者需要留意官方网站的最新动态。

实战

Linux和mac OS平台编译原生代码到WebAssembly可由如下步骤实现。

编译环境准备

操作系统必须有可以工作的编译器工具链,因此需要安装GCC、cmake环境,此外Python、Node.js及Java环境也是需要的(其中Java为可选,如图5所示)。

图片描述

图5 编译环境安装

如果是以其他方式安装了Node.js,可能需要更新~/.emscripten文件的NODE_JS属性。

安装正确的emscripten分支

要编译原生代码到WebAssembly,我们需要emscripten的incoming分支。由于emscripten不仅仅是用于WebAssembly的编译工具链,选择正确的分支尤为重要(如图6所示)。

图片描述

图6 安装emscripten的incoming分支

其中URLTO具体的URL是https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz

处理安装异常

可运行emcc -v命令进行验证安装。如果遇到如图7所示的错误,表明带有JavaScript后端的LLVM编译器并未被生成。

图片描述

图7 emcc -v命令报错

图片描述

图8 emcc -v命令报错解决方案

通过图8步骤,可以解决该问题,并且在~/.emscripten 文件中修改如下配置:

图片描述

开始编译程序

现在一个完整的工具链已经具备,我们可以使用它来编译简单的程序到WebAssembly。但是,还有一些其他注意事项:

  • 必须通过参数-s Wasm=1到emcc(否则默认emcc将编译出asm.js);
  • 除了Wasm二进制文件和JavaScript wrapper外,如果还希望emscripten生成一个可直接运行的程序的HTML页面,则必须指定一个扩展名为.html的输出文件。

在编译之前,首先准备一个最基本的add.c程序,见代码6。

图片描述

代码6

按代码7所示的命令编辑好add.c程序并编译:

图片描述

运行WebAssembly应用

以Chrome浏览器为例,如果直接在浏览器内本地打开HTML文件,会有图9所示的错误: 
图片描述

图9 XMLHttpRequest本地访问的跨域请求错误

由于XMLHttpRequest跨域请求不支持file://协议,必须经由HTTP实际输出,可以由Python的SimplHTTPServer改进,见代码8:

图片描述

代码8

在浏览器中输入http://127.0.0.1:8080并打开add.html,就能直接看到转换成WebAssembly的应用程序输出结果。

创建独立WebAssembly

默认情况下,emcc会创建JavaScript文件和WebAssembly的组合,其中JS加载包含编译代码的WebAssembly。对于C/C++开发人员,他们可能更倾向于创建独立的WebAssembly,用于JavaScript开发人员调用,见代码9。

图片描述

代码9

上述命令运行后,我们可以得到独立的Wasm文件。需要说明的是,该参数仍然在开发中,可能随时发生规范和实现变更。

JavaScript API调用

从C/C++程序编译获得一个.wasm模块之后,JavaScript开发人员可以通过如下方式进行载入.wasm文件并执行。WebAssembly社区组也有计划通过Streams使用streaming以及异步编译,见代码10。

图片描述

代码10

最后一行调用导出的WebAssembly函数,它反过来调用我们导入的JS函数,最终执行add(201700, 2),并且在控制台获得期望的结果输出(如图10所示)。

图片描述

图10 WebAssembly求和函数在控制台的输出

性能

那么,WebAssembly的真实性能如何呢?首先我们用一直被用来作为CPU基准测试的斐波那契 (Fibonacci)数列来进行对比,这里使用的是性能较差的递归算法,在Node.js v7.2.1环境下,能够看到WebAssembly性能优势越发明显(如图11所示)。

图片描述

图11 CPU基准测试反应WebAssembly的真实性能

再看看最基本的1000毫秒时间内,求和计算的运算量统计,在同一台计算机的Firefox 50.1.0版本的运算结果如图12所示。

图片描述

图12 1000毫秒内求和计算的运算量统计

尽管重复测试时结果不尽相同,重启浏览器并多次测试取平均值后依然可以看到WebAssembly的运算量比JavaScript快了近一个量级。

Demo

图13展示了Angry Bots Demo,它是由WebAssembly项目发布的一个Demo,由Unity游戏移植而来。

图片描述

图13 Angry Bots Demo / Google Chrome 55.0.2883.87

通过如下方式可以体验WebAssembly在浏览器中的强大性能。即便Google Chrome较新的稳定版也已支持WebAssembly,还是推荐使用canary版及Firefox的nightly版进行测试。

  1. 下载浏览器: 
    1-1. Google Chrome; 
    1-2. Mozilla Firefox; 
    1-3. Opera; 
    1-4. Vivaldi。
  2. 打开 WebAssembly支持 : 
    2-1. Google Chrome:chrome://flags/#enable-webassembly; 
    2-2. Mozilla Firefox:about:config→接受→搜索javascript.options.wasm→设置为true; 
    2-3. Opera:opera://flags/#enable-webassembly; 
    2-4. Vivaldi:vivaldi://flags#enable-webassembly。

访问:http://webassembly.org/demo/

使用W、A、S、D等键实现移动操作,点击鼠标进行射击。该WebAssembly游戏在浏览器中运行相当流畅,媲美原生性能。

除了最新的浏览器开始对WebAssembly逐步支持外,Intel开源技术中心开发的Crosswalk项目(https://crosswalk-project.org/)早在2016年11月初的Crosswalk 22稳定版(Windows及Android 平台)即已加入对WebAssembly实验性的支持,开发者可以使用该版本体验Angry Bots Demo。

开发者

WebAssembly对于Web有显著的性能提升,对于开发者尤其是前端或者JavaScript开发人员而言,并不意味着WebAssembly将会取代JavaScript(如图14所示)。

图片描述

图14 WebAssembly与JavaScript引擎的关系

WebAssembly被设计为对JavaScript的补充,而不是替代,是为了提供一种方法来获得应用程序的关键部分接近原生性能。随着时间的推移,虽然WebAssembly将允许多种语言(不仅仅是C/C++)被编译到Web,但是JavaScript的发展势头不会因此被削弱,并且仍然将保持Web的单一动态语言。此外,由于WebAssembly构建在JavaScript引擎的基础架构上,JavaScript和WebAssembly将在许多场景中配合使用。

那么WebAssembly是不是仅仅面向C/C++开发者呢?答案依旧是否定的。WebAssembly最初实现的重点是C/C++,由Mozilla主导开发的注重高效、安全和并行的Rust也能在2016年末被成功编译到WebAssembly了,未来还会继续增加其他语言的支持,见代码11。 
图片描述

代码11

在未来,通过ES6模块接口与JavaScript集成,Web开发人员并不需要编写C++,而是可以直接利用其他人编写的库,重用模块化C++库可以像使用JavaScript中的modules一样简单。

进展

依据开发路线图,2016年10月31日,WebAssembly到达浏览器预览的里程碑。Google Chrome V8引擎及Mozilla Firefox SpiderMonkey引擎都已经在trunk上支持WebAssembly浏览器预览。2016年12月下旬,Microsoft Edge浏览器使用的JavaScript引擎ChakraCore v1.4.0启用了WebAssembly浏览器预览支持。而Webkit JavaScriptCore引擎对于该支持也在积极进行中。

目前,WebAssembly社区组已经有初始(MVP)二进制格式发布候选和JavaScript API在多个浏览器中实现。作为浏览器预览期间的一部分,WebAssembly社区组(WebAssembly Community Group)现在正在征求更广泛的社区反馈。社区组的初步目标是浏览器预览在2017年第一季度结束,但在浏览器预览期间的重大发现可能会延长该周期。当浏览器预览结束时,社区组将产生WebAssembly的草案规范,并且浏览器厂商可以开始默认提供符合规范的实现。预计在2017年上半年,四大主流浏览器对原生的WebAssembly支持将到达稳定版。

具体到Google V8引擎的最新进展,asm.js代码将不再通过Turbofan JavaScript编译器而是编译到WebAssembly后,在WebAssembly的原生执行环境中执行最终的机器码。这种改变带来的好处有,为asm.js将预先编译(AOT,Ahead Of Time Compilation)带到了Chrome,且完全向后兼容。新的WebAssembly编译渠道重用了一些Turbofan JavaScript编译器后端部分,因此能够在少了很多编译和优化消耗的前提下,产生类似的代码。在Google Chrome中,WebAssembly将很快在Canary版中默认启用,开发团队也期望能够发布到2017年第一季度末的稳定版中。

社区

包含所有主要浏览器厂商代表的W3C Web——Assembly社区组于2015年4月底成立。该小组的任务是,在编译到适用于Web的新的、便携的、大小和加载时间高效的格式上,促进早期的跨浏览器协作。该社区组也正在将WebAssembly设计为W3C开放标准。目前,除了文中所述主流浏览器厂商Mozilla、Google、微软、及苹果公司之外,Opera CTO及Intel的8位该领域专家均参与了该社区组。当然,并不是只有社区组成员才能参与标准的制定,任何人都可以在https://github.com/WebAssembly做出贡献。

展望

由于主要的浏览器厂商对WebAssembly支持表现积极,并且都在实现WebAssembly的各项功能,因此在Web中高性能需求的应用例如在线游戏、音乐、视频流、AR/VR、平台模拟、虚拟机、远程桌面、压缩及加密等都能够获得接近于原生的性能。相信WebAssembly将会开创Web的新时代。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/hopesky23/article/details/78248732

智能推荐

Mac下如何生成ssh key_mac 生成ssh key-程序员宅基地

git是分布式的代码管理工具,远程的代码管理是基于ssh的,所以要使用远程的git则需要ssh的配置。简单的说,Git - 版本控制工具;Github是一个网站,提供给用户空间创建git仓储,保存用户的一些数据文档或者代码等;GitLab是基于Git的项目管理软件 首先,使用代码管理工具把本地的代码上传到服务器时需要加密处理,加密传输的算法有很多种,git可使用rsa,rsa要..._mac 生成ssh key

python 网络编程 day02_s.fileno()-程序员宅基地

2018.8.7目录tcp粘包基于udp的服务端编程socket模块和套接字属性udp套接字应用---》广播tcp应用--》http传输:http请求(Request)http响应(response)day01回顾1,osi七层模型---》四层 五层2,三次握手,四次挥手 3,tcp和udp区别网络概念:主机 端口 ip 协议服务端:..._s.fileno()

datax 高级_大数据学习路线攻略-程序员宅基地

自己想往大数据方向发展,该学哪些技术,学习路线是什么样的,觉得大数据很火,就业很好,薪资很高。如果自己很迷茫,为了这些原因想往大数据方向发展,也可以,那么我就想问一下,你的专业是什么,对于计算机/软件,你的兴趣是什么?是计算机专业,对操作系统、硬件、网络、服务器感兴趣?是软件专业,对软件开发、编程、写代码感兴趣?还是数学、统计学专业,对数据和数字特别感兴趣。其实这就是想告诉你的大数据的三个发展方向...

ros下安装gazebo提示错误_gazebo unmet dependency-程序员宅基地

安装gazebo时sudo apt-get install ros-kinetic-gazebo-ros-pkgs ros-kinetic-gazebo-ros-control提示如下:Some packages could not be installed. This may mean that you haverequested an impossible situation or ..._gazebo unmet dependency

Unity系列之Play模式设置颜色,避免忘记运行时编辑白费功夫!_unity 界面点开后 颜色设置起作用-程序员宅基地

1、打开设置里面的Color2、选择淡红色3、运行时的颜色就会提醒自己了_unity 界面点开后 颜色设置起作用

一份程序猿单词列表(updating)-程序员宅基地

以下单词是个人平时阅读英文文档时遇到的一些“生”单词,该文档将持续更新,可以持续关注https://github.com/hylinux1024/word-list-for-programmerhierarchy 等级制度;层级;n;coroutines 协同程序;n;backend 后端;n; backend developer 后端开发人员;..._后端开发人员英文怎么说

随便推点

三向振动台的计算机辅助测试实验分析原因,传感器技术测技术实验指导书201201版.doc...-程序员宅基地

《测试技术》实验指导书蒋 平南京工程学院二○一二年一月目 录实验1 测试装置的特性实验1实验1—1 指针式电表的静、动态特性1实验1—2 电阻应变仪的静、动态特性4实验2 电桥和差特性实验7实验3 信号分析实验11实验3—1 基于信号分析工具箱的信号分析实验12实验3—2 基于虚拟仪器的信号分析实验15实验4 三向振动台的计算机辅助测试实验17实 验 报 告1实验1 测试装置的..._三向振动台的计算机辅助测试实验分析原因

ffmpeg混音以及音视频混合_[0:a][1:a]amix-程序员宅基地

Duration = MAX(input a, v)0. 前言本文包括以下内容: (1)混音:多个音频混合 采用amerge, amix对多个音频进行混音(而非拼接) (2)音视频混合——muxing (3)修改音频音量1. Audio merge1.1 amerge-ac 2 speed upffmpeg -i test.mp4 -i test._[0:a][1:a]amix

linux的可执行文件存放位置_debian 可执行文件路径_All_Will_Be_Fine噻的博客-程序员宅基地

用户自定义的文件pip管理的包~/.local/lib/python3.6/site-packages #可能有一些不同conda管理的包conda安装位置/binconda安装位置/envs/binapt管理的包apt-get install安装目录是包的维护者确定的,不是用户apt-get 下载后,软件所在路径是:/var/cache/apt/archives系统安装软件一般在/usr/share,可执行的文件在/usr/bin,配置文件可能安装到了/etc下等。.._debian 可执行文件路径

Linux内核分析课程-- 理解进程调度时机跟踪分析进程调度与进程切换的过程-程序员宅基地

齐昱博 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 1、课上总结(1)进程的第一种分类:不同类型的进程有不同的调度需求(如有i/o密集型和cpu密集型)。(2)进程的第二种分类:批处理进程、实时进程、交互式进程。(3)调度策略:是一组规则,决定什么时候以什么样的方

数据结构---快速排序---java与c++实现-程序员宅基地

快速排序:首先选定一组的第一个元素为基准数,第一次排后实现基准数前面的数都小于它,后面的数都大于它,分成两组后,每组再递归。 举例如下(排一次): (1)原始数据:6 2 7 3 8 9 i=0, j=5 (2)以6为基准,将j减小,比6小就交换:3 2 7 6 8 9 i=0, j=3 (3)以6为基准,将i增大,比6大就交换:3 2 6 7 8 9 i=2, j=3/