无法扩展该卷 因为群集的数量将超过文件系统_浏览器将支持Python项目!Mozilla发布Pyodide...

c2d4052f1b4711c1340f505bb58ce6ae.png 作者|Michael Droettboom 编译|王强、覃云

近日,Mozilla 发布了一个实验项目 Pyodide,旨在浏览器内运行一个完整的 Python 数据科学堆栈。

链接:

https://github.com/iodide-project/pyodide/

Pyodide 的创意起源于 Mozilla 的另一个项目 Iodide,Iodide 是一款基于最先进 Web 技术的数据科学实验和通信工具。值得注意的是,它是设计用于在浏览器中,而不是在远程内核上执行数据科学计算的。

不幸的是,浏览器中“人人都有的语言”JavaScript,不仅没有成熟的数据科学库,还缺少许多对数值计算有用的功能,例如运算符重载。一方面我们认为业界应该改变这一现状,并推动 JavaScript 数据科学生态系统向前发展;另一方面我们找到了一条捷径:那就是将流行且成熟的 Python 科学栈引入浏览器来满足数据科学家的需求。

此外还有更多人认为,Python 语言面临的一种生存威胁就是无法在浏览器内运行,当下有如此多的用户交互是在网络或移动设备上发生的,Python 要么融入其中,要么就会逐渐落伍。因此,尽管 Pyodide 首先是要满足 Iodide 的需求,但它独立工作时也是由自己用武之地的:

https://github.com/iodide-project/pyodide/blob/master/docs/using_pyodide_from_javascript.md

from js import document, iodide

canvas = iodide.output.element('canvas')
canvas.setAttribute('width', 450)
canvas.setAttribute('height', 300)
context = canvas.getContext("2d")
context.strokeStyle = "#df4b26"
context.lineJoin = "round"
context.lineWidth = 5

pen = False
lastPoint = (0, 0)

def onmousemove(e):
global lastPoint

if pen:
newPoint = (e.offsetX, e.offsetY)
context.beginPath()
context.moveTo(lastPoint[0], lastPoint[1])
context.lineTo(newPoint[0], newPoint[1])
context.closePath()
context.stroke()
lastPoint = newPoint

def onmousedown(e):
global pen, lastPoint
pen = True
lastPoint = (e.offsetX, e.offsetY)

def onmouseup(e):
global pen
pen = False

canvas.addEventListener('mousemove', onmousemove)
canvas.addEventListener('mousedown', onmousedown)
canvas.addEventListener('mouseup', onmouseup)

它输出成这样:

53bf1cf91e65346f95ec4a9e6b8158bc.png

想要了解 Pyodide 还可以做哪些事情,最好的方法就是去试一试!这里有一个示例笔记(https://alpha.iodide.io/notebooks/300/,50MB)介绍了它的高级功能。下文将深入探讨其工作原理。

现有技术

在 Pyodide 诞生之前,已经有许多令人印象深刻的项目将 Python 引入浏览器了。然而,包括 NumPy、Pandas、Scipy 和 Matplotlib 在内的这些项目都没有做到实现全功能主流数据科学栈的程度。

像 Transcrypt 这样的项目会将 Python 转换为 JavaScript。因为转换步骤是在 Python 中完成的,所以你需要提前做好所有转换,或者连上一台服务器来完成这项工作。这也无法满足我们的需求,也就是让用户在浏览器中编写 Python,并在没有任何外部辅助的情况下运行代码。

像 Brython 和 Skulpt 这样的项目是将标准 Python 解释器重写为 JavaScript,因此它们可以直接在浏览器中运行 Python 代码串。但由于它们是 Python 的全新实现,并且需要在 JavaScript 中引导,因此它们与用 C 编写的 Python 扩展,例如 NumPy 和 Pandas 等并不兼容,也就没有数据科学工具可用。

PyPyJs 是 Python 的实时编译工具 PyPy 的变体,其使用 emscripten 即时编译 Python 到浏览器上。和 PyPy 一样,它也有能力快速运行 Python 代码。但它也和 PyPy 一样在 C 语言扩展的性能方面存在问题。

上面这些方法都需要我们重写科学计算工具以获得足够的性能。我曾为 Matplotlib 做过很多工作,所以知道重写代码得花费多少劳力:这条路其他项目已经尝试过且举步维艰,而且它要做的工作肯定不是我们这支拼凑起来的新团队能够处理的。因此,我们需要构建一个尽可能基于 Python 的标准实现和多数数据科学家正在使用的科学栈的工具。

与 Mozilla 的几位 WebAssembly 专家讨论之后,我们意识到开发这个工具的关键在于 emscripten 和 WebAssembly:它们是用来将 C 语言编写的现有代码移植到浏览器上的技术。随后我们发现了一个使用 Python 构建的高水平 empscripten 实现,也就是 cpython-emscripten(https://github.com/dgym/cpython-emscripten),最后它成为了 Pyodide 的基础。

emscripten 和 WebAssembly

可以从很多角度来介绍 emscripten 的内容,但对我们而言最重要的是它的两项用途:

  1. 将 C/C++ 编译到 WebAssembly

  2. 作为兼容层,在浏览器中模仿原生计算环境

WebAssembly 是一种在现代 Web 浏览器中运行的新语言,是 JavaScript 的补充。它是一种类似于群集的底层语言,旨在作为 C 和 C++ 等底层语言的编译目标,提供接近原生环境的性能。值得注意的是,最流行的 Python 解释器 CPython 就是用 C 实现的,所以这里就是 emscripten 的用武之地了。

Pyodide 的工作流程如下:

  • 下载主流 Python 解释器(CPython,https://github.com/python/cpython)的源代码,以及科学计算包(NumPy 等);

  • 进行很小的调整以使其适应新环境;

  • 使用 emscripten 的编译器将它们编译为 WebAssembly。

如果你直接把这个 WebAssembly 输出加载到浏览器中,那么 Python 解释器就会和在操作系统中直接运行时有很大区别。例如,Web 浏览器没有文件系统(加载和保存文件的位置)。还好 emscripten 提供了一个用 JavaScript 编写的虚拟文件系统供 Python 解释器使用。默认情况下,这些虚拟“文件”会驻留在浏览器选项卡临时占用的内存里,页面关闭时它们就会消失。(emscripten 还为文件系统提供了一种在浏览器的本地存储空间中存储内容的方法,但 Pyodide 不用它。)

通过模拟文件系统和其它标准计算环境中的功能,emscripten 可以只用很少的调整就将现有项目迁移到 Web 浏览器中。(将来我们可能会转而使用 WASI 作为系统仿真层,但是现在 emscripten 是更成熟和完善的选择)。

总而言之,要在浏览器中加载 Pyodide,你需要下载:

用 WebAssembly 编译的 Python 解释器。

  • emscripten 提供的一些 JavaScript,用于系统仿真。

  • 一个打包的文件系统,包含 Python 解释器所需的所有文件,其中最重要的是 Python 标准库。

这些文件可能会非常大:Python 本身为 21MB,NumPy 为 7MB,依此类推。所幸这些包只需要下载一次,之后它们会存储在浏览器的缓存中。

将所有这些东西组合起来后,Python 解释器就可以访问其标准库中的文件,启动,然后开始运行用户代码了。

哪些部分正常工作,哪些不行

我们用 CPython 的单元测试作为 Pyodide 持续测试的一部分,以便了解 Python 的哪些功能正常工作,哪些不行。有些东西,比如多线程现在就不能用了,但在新出现的 WebAssembly threads 的帮助下,我们应该很快就能提供支持了。

由于浏览器的安全沙箱限制,一些功能(如底层网络套接字,https://docs.python.org/3/library/socket.html)不太可能正常工作。另外很抱歉让你失望了,想要在 Web 浏览器中运行 Python minecraft 服务器(https://github.com/Yardanico/puremine)可能还有很长的路要走。不过你仍然可以使用浏览器的 API 通过网络获取内容(后文会具体介绍)。

它有多快?

在 JavaScript 虚拟机中运行 Python 解释器会损失更多性能,但这种惩罚是很小的——在我们的基准测试中,Firefox 上比原生慢 1 到 12 倍,Chrome 上慢 1 到 16 倍。经验表明,这个程度的性能对于交互探索已经很够用了。

要注意的是,在 Python 中运行大量内部循环的代码往往比使用 NumPy 执行其内部循环的代码慢很多。以下是在 Firefox 和 Chrome 中运行各种 Pure Python 和 Numpy 基准测试(https://github.com/iodide-project/pyodide/tree/master/benchmark/benchmarks)的结果,与在相同硬件上原生运行做对比。

974d2a4652dec6b9f0008edc1a3a5f37.png

Python 和 JavaScript 的交互

如果 Pyodide 能做的就只是运行 Python 代码并写入标准输出,那么它就只能当一个很酷的玩具,但难以用于实际工作。Pyodide 真正的力量在于它能够以非常高的水平与浏览器 API 和其他 JavaScript 库交互。WebAssembly 旨在轻松地与浏览器中运行的 JavaScript 交互。由于我们已经将 Python 解释器编译为 WebAssembly,因此它也与 JavaScript 这边深度集成在了一起。

Pyodide 会隐式转换 Python 和 JavaScript 之间的许多内置数据类型。其中一些转换是明显、直截了的,但有趣的部分向来都在于那些少见的情况。

10b2e0a630e4865ba3ac727dae3ef0df.png

Python 将 dict 和 object 实例视为两种不同的类型。dict(字典)只是键的映射值。另一方面,object 通常具有对这些对象“做某事”的方法。在 JavaScript 中,这两个概念被混合成一个名为 Object 的类型。(是的,我在这里简化了很多内容。)

如果没有真正理解开发者使用 JavaScript 的 Object 的意图,就没法判断它是该转换为 Python 的 dict 还是 object。因此,我们必须使用代理,用“鸭子类型”来解决问题。

代理是另一种语言中变量的包装器。代理不是简单地在 JavaScript 中读取变量并根据 Python 的构造重写它,就像对基本类型所做的那样,而是维持原始的 JavaScript 变量并“按需”调用它上面的方法。这意味着任何 JavaScript 变量,无论它的定制程度多高,都可以从 Python 完整访问。反过来也是没问题的。

鸭子类型是一个原则,不是问变量“你是鸭子吗?”而是问它“你像鸭子一样走路吗?”和“你像鸭子一样嘎嘎叫吗?”并从中推断出它可能是一只鸭子, 或者至少像鸭子般行事。这使 Pyodide 可以延后决定如何转换 JavaScript 对象:它将对象包装在代理中,并让使用它的 Python 代码决定如何处理它。当然这招并不总能见效,因为你以为它是鸭子,实际上可能是一只兔子(https://www.illusionsindex.org/i/duck-rabbit)。因此 Pyodide 还提供了显式处理这些转换的方法:

https://github.com/iodide-project/pyodide/blob/master/docs/api_reference.md#pyodideas_nested_listobj

正是这种紧密的集成让用户可以在 Python 中处理数据,然后将其发送到 JavaScript 进行可视化。例如,在我们的 Hipster Band Finder 演示(https://alpha.iodide.io/notebooks/1623/)中,我们在 Python 的 Pandas 中加载和分析数据集,然后将其发送到 JavaScript 的 Plotly 进行可视化。

访问 Web API 和 DOM

代理也是访问 Web API 的关键环节,或者是浏览器提供的使其能够完成工作的一组功能。例如,Web API 的很大一部分位于 document 对象上。你可以这样从 Python 中获取它们:

from js import document

这会将 JavaScript 中的 document 对象作为代理导入到 Python 端。你可以从 Python 开始调用它的方法:

document.getElementById("myElement")

这些都是通过代理来查找 document 对象可以即时执行的操作。Pyodide 不需要包含浏览器所有 Web API 的完整列表。

当然,直接使用 Web API 并不会一直像大多数 Python 风格或者对用户友好的方式那样处理问题。我们希望能看到为 Web API 创建的对用户友好的 Python 包装器,就像 jQuery 之类的库使 Web API 更容易通过 JavaScript 使用一样。如果你想做这种工作,请告诉我们:

https://gitter.im/iodide-project/iodide

多维数组

数据科学有自己特定的一些重要数据类型,Pyodide 也对它们提供了专门支持。其中,多维数组是所有相同类型(通常是数字)值的集合。它们往往很大,并且由于每个元素都是相同的类型,多维数组与可以容纳任意类型元素的 Python 的 list 或 JavaScript 的 Array 相比,前者具有明显的性能优势。

在 Python 中,NumPy arrays 是多维数组的最流行实现。JavaScript 也有 TypedArrays,只包含一个数字类型,但它们是单维的,因此需要在其上构建多维索引。

由于实践中这些数组可能会变得非常大,所以我们不希望在各个语言运行时之间复制它们。这不仅需要很长时间,而且在内存中同时存在两个副本会对浏览器有限的可用内存造成负担。

还好我们无需复制即可共享此数据。多维数组通常使用少量元数据来实现,这些元数据描述了值的类型、数组的形状和内存布局。数据本身通过指向内存中另一个位置的指针从该元数据中引用。这部分内存位于一个称为“WebAssembly 堆”的特殊区域,优点在于它既能用 JavaScript 也能用 Python 访问。我们可以简单地在语言之间来回复制元数据(元数据非常小),然后用指针指向引用 WebAssembly 堆的数据。

c7f6b88916cdae6748ec7ae775f8f686.png

目前,这个想法是针对一维数组实现的,对于更高维数组而言,这是一个次优的解决方法。我们需要对 JavaScript 侧进行改进,以便用一个有用的对象来处理它。现在 JavaScript 多维数组还没有很好的选择。Apache Arrow 和 xnd 的 ndarray(https://xnd.io/)等有前景的项目正在研究这方面的问题,旨在使不同语言运行时之间的内存结构化数据的传递更加便利。我们正在研究如何利用这些项目,以进一步增强这种数据转换操作。

实时交互式可视化

如 Jupyter 所做的那样,在浏览器中而不是在远程内核中进行数据科学计算的优点之一是,交互式可视化不必通过网络通信以重新处理和显示其数据。这大大降低了延迟——也就是从用户移动鼠标到更新绘图显示到屏幕所需的响应时间。

完成这项工作需要上述所有技术部分协同工作。先来看看这个交互式示例(https://alpha.iodide.io/notebooks/1658/),它使用 matplotlib 展示了对数正态分布的原理。首先,使用 Numpy 在 Python 中生成随机数据;接下来 Matplotlib 获取该数据,并使用其内置的软件渲染器绘制它;它使用 Pyodide 对零拷贝数组共享的支持将像素发送回 JavaScript 端,最终将它们渲染到 HTML 画布中。然后浏览器将这些像素显示屏幕上。用于交互的鼠标和键盘事件由从 Web 浏览器调用的回调处理,发送回 Python。

dda0890647d0a6aa98821c8d956ed59e.png

打包

Python 科学栈不是一个整体——它实际上是一组松散的附属包,它们协同工作以打造生产环境。其中最受欢迎的是 NumPy(用于数值数组和基本计算)、Scipy(用于更复杂的通用计算,如线性代数),Matplotlib(用于可视化)和 Pandas(用于表格数据或“数据帧”)。可以在此处查看 Pyodide 为浏览器构建的完整包列表,该列表还在不断更新:

https://github.com/iodide-project/pyodide/tree/master/packages

其中一些包很容易引入 Pyodide。通常来说,任何使用纯 Python 编写而没有编译语言扩展的东西都非常简单。难度高一些的类别中,像 Matplotlib 这样的项目需要使用特殊代码在 HTML 画布中显示绘图。有些包属于极端困难的类型,其中 Scipy 就一直是一项巨大的挑战。

Roman Yurchak 致力于将 Scipy 中的大量旧 Fortran 代码编译为 WebAssembly。Kirill Smelkov 改进了 emscripten,使共享对象可以被其他共享对象复用,从而缩小了 Scipy 的体积。(这些外部贡献者的工作得到了 Nexedi,http://www.nexedi.com/ 的支持)。如果你正在努力将包移植到 Pyodide 上,请在 Github 上与我们联系,你的问题我们之前很可能也遇到过:

https://github.com/iodide-project/pyodide/

由于我们无法预测用户最终需要哪些包来完成任务,因此用户可以根据需要将它们单独下载到浏览器中。例如在导入 NumPy 时:

import numpy as np

Pyodide 会获取 NumPy 库(及其所有依赖项)并同时将它们加载到浏览器中。同样,这些文件只需要下载一次,之后会存储在浏览器的缓存中。

现在向 Pyodide 添加新包是一个半手动过程,其中需要向 Pyodide 中添加文件。长远来看,我们更倾向于采用分布式方法解决这个问题,这样任何人都可以无需处理单个项目就为生态系统贡献包。这方面最好的例子是 conda-forge。如果能将它们的工具进一步扩展,支持 WebAssembly 作为平台目标就好了,这样就省去了很多重复劳动。

此外,Pyodide 很快将支持(https://github.com/iodide-project/pyodide/pull/147)直接从 PyPI(Python 的主社区包存储库,https://pypi.org/)加载包,只要它以纯 Python 编写并以轮格式(https://pythonwheels.com/)分发。这样以来,Pyodide 现在就可以访问大约 59,000 个包。

超越 Python

Pyodide 较早期的成功已经激励了其他语言,包括 Julia、R、OCaml、Lua 等社区的开发者,设法让他们的语言运行时在浏览器中正常工作,并与 Iodide 等网络优先工具集成。我们定义了一组级别,以鼓励人们创建与 JavaScript 运行时联系更紧密的集成:

  • 第 1 级:只是字符串输出,可以用作基本控制台 REPL(read-eval-print-loop)。

  • 第 2 级:将基本数据类型(数字、字符串、数组和对象)与 JavaScript 互相转换。

  • 第 3 级:在访客语言和 JavaScript 之间共享类实例(带方法的对象)。这样就能允许 Web API 访问了。

  • 第 4 级:在访客语言和 JavaScript 之间共享数据科学相关类型(n 维数组和数据帧)。

如果你尚未尝试过 Pyodide,现在就试试吧:

https://alpha.iodide.io/notebooks/300/

原文链接

https://hacks.mozilla.org/2019/04/pyodide-bringing-the-scientific-python-stack-to-the-browser/

今日荐文

点击下方图片即可阅读

b930cc509e9b603c9a458950f7c6eb5c.png

支付宝背后的OceanBase:国产自研分布式数据库

活动推荐

张鑫旭,资深前端工程师,《CSS 世界》作者,工作 10 年一直在专业一线,没有管理任何人,但过得还不错,在圈内也是小有名气。我们来听他聊聊工作 10 年以后,他在前端专业成长路上的探索。更多关于前端圈的最新技术干货欢迎点击“

8fb380c7af7358bcbf22de702eb89ea3.png

3cadf059f532918cbaf35c58d5e55f70.gif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/552273.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华锋e路航x10升级工具_万商云集:疫情下火爆的电子合同,背后是企业数字化升级的必然...

近年来,数字经济快速发展成为中国经济发展的新动能,作为企业数字化转型中非常重要的一环,电子合同也随着产业数字化程度的加深快速渗透到各行各业,万商云集早在去年年底就已经正式拥抱电子合同,助力客户实现数字化升级…

edge播放视频HTML5黑屏,Win10 edge浏览器播放视频黑屏解决方法

Edge看不了视频怎么办呢? 出现这样的问题是由于Edge浏览器中需要点击允许才能看视频,但如果不弹出提示窗口我们就无法正常观看视频,所以当我们遇到这样的情况可以按下面方法进行操作!Edge看不了视频解决步骤:1、按下winR 组合键打开运行&…

@async 如何返回list_图解 Await 和 Async

原文链接:Await and Async Explained with Diagrams and Examples文章目录简介Promise问题:组合 PromiseAsync 函数Await错误处理讨论简介JavaScript ES7中的 async/await 使得协调异步 promise 变得更容易。如果你需要从多个数据库或 API 异步获取数据&…

求一个向量变换为另一个向量的矩阵_OpenGL里旋转等变换矩阵为什么是4x4的矩阵...

OpenGL ES 的很多教程里都会有这样一个例子来讲解纹理:将一张图片作为纹理显示在屏幕上。因为纹理坐标和实际屏幕显示的坐标不一样,把图片渲染在屏幕上后,图片是上下颠倒的。一个解决方法是对当前的顶点坐标,乘以绕 z 轴旋转180度…

白鹭时代与html5关系,白鹭时代观点:HTML5行业将进入红利收割期

2016年,H5产业风风火火,各种引人注目。最大成果无疑是游戏《传奇世界H5》月流水破了3000万,引起整个行业巨大震动,同时,也标志着H5重度游戏时代来临。国内最大的HTML5移动技术与服务供应商白鹭时代认为,201…

boot定时任务开启和关闭 spring_Spring之定时任务实践

Java下的定时任务实现有Timer,Spring,QuartZ等,这里我们介绍Spring中定时任务的应用,其通过 Scheduled 注解即可轻松实现概述Spring 的定时任务可以支持各种形式的定时调度任务。其通过加在定时方法上的 Scheduled 注解来配置任务…

计算机怎么取消用户密码,怎么取消开机密码:计算机开机进入Windows时的开机密码怎么取消?...

优质回答 回答者:168长腿欧巴在电脑中的“用户账户”界面即可设置取消开机密码,具体操作请参照以下步骤。1、右键Win10系统的开始菜单,选择弹出菜单里的“运行”选项。2、然后在出现的运行对话框里输入命令“netplwiz”,点击确定。…

echarts symbol 回调函数_【OpenLayer 实战】实现仿Echarts风格的动态迁徙图/航班图

使用的数据还是来自echarts,模拟了全国各地到湖南重点景区的客流情况。分析要实现动态迁徙图的效果,主要需解决两个问题 曲线的绘制。因为给出的数据只有起点和终点两个点位,所以想要绘制曲线可以参考turf中的bezier曲线生成API。 点迹…

校运会计算机科学系大本营,计算机系团总支学生会学期总结大会

(本网讯)时光飞逝,又一个学期即将就此画上了圆满的句号。为推动我系团总支学生会工作更长久的发展,提高学生会干部工作的热情和质量,2016年12月8日晚上19:00在第一教学楼C102课室里,校学生会全体成员齐聚一堂,参加了20…

hexo评论_【前端简历加分】hexo框架搭建个人博客站点,手把手教学

最近,粉丝们在金九银十期间也是不断的面试,有比较多的毕业生说我在这个期间出多一些面试题,上几期都是倾向于面试文章,这期出一次简历加分项操作,使用hexo框架搭建个人博客。作为应届毕业生或者1-3年工作经验的程序员拥…

电脑抓整个路由器的包_网络是电竞游戏体验的命脉 2018年年度电竞路由器功能盘点...

2018年是电竞路由器的元年,从2017年的概念产品诞生开始,电竞路由器很快就确定了品类,随着《绝地求生》、《王者荣耀》等对网络质量敏感的竞技游戏的火爆,电竞路由器迅速被竞技玩家熟知,并在2018年以野火燎原的速度发展…

dos 改某个目录下所有文件的时间_go语言入门学习笔记(2)-DOS操作及go语言变量学习...

API:application program interface:应用程序编程接口。就是我们go的各个包的各个函数。我们想要了解这些函数我们可以通过Go的中文网在线标准库文档:https://studygolang.com/pkgdocDOS介绍:Dos:Disk Operating System 磁盘操作系…

es multi match_PHP 的ES搜索操作

原文:https://blog.csdn.net/JineD/article/details/106650695首先从ES的支持的字段说起,ES文档中字段有多种类型 官方文档。这几个比较常用:text,keyword,integer,float,boolean,object,geo_point(地理坐标),geo_shape(描述地理区域),date.注…

git 怎么还原历史版本_4. Git--修改/回退等操作

》》点赞,收藏关注,理财&技术不迷路《《我们已经成功地添加并提交了一个readme.txt文件,现在,是时候继续工作了,于是,我们继续修改readme.txt文件,改成如下内容:Git is a distri…

为什么用python写爬虫_零基础,是怎么开始写Python爬虫的

刚开始接触爬虫的时候,简直惊为天人,十几行代码,就可以将无数网页的信息全部获取下来,自动选取网页元素,自动整理成结构化的文件。利用这些数据,可以做很多领域的分析、市场调研,获得很多有价值…

datatable怎么根据两列分组_谈谈怎么做服务隔离

来源于公众号孤独烟 ,作者孤独烟引言OK,如下图所示那显而易见,做服务隔离的目的就是避免服务之间相互影响。毕竟谁也不能说自己的微服务百分百可用,如果不做隔离,一旦一个服务出现了问题,整个系统的稳定性都…

position: absolute;_前端性能优化--transform与position

上个星期去yy语音面试&#xff0c;就有一个这样问题&#xff1a; transform与position:absolute 有什么区别? 我回家后查资料发现这道题目其实不简单啊&#xff0c;涉及到重排、重绘、硬件加速等网页优化的知识。首先看一个用top、left实现的动画效果<style>html,body {…

台式计算机总是重启,台式电脑经常自动重启怎么修复

当我们的电脑出现了电脑自动重启的时候&#xff0c;我们就要注意了&#xff0c;说明我们的电脑主机出现问题了&#xff0c;怎么解决呢。下面是学习啦小编为大家整理的关于台式电脑经常自动重启的相关资料&#xff0c;希望对您有所帮助!台式电脑经常自动重启的解决方法方法/步骤…

线程执行完之后会释放吗_java多线程并发:CAS+AQS+HashMap+volatile+ThreadLocal,乐分享...

CyclicBarrier、CountDownLatch、Semaphore 的用法CountDownLatch(线程计数器 )CountDownLatch 类位于 java.util.concurrent 包下&#xff0c;利用它可以实现类似计数器的功能。比如有一个任务 A&#xff0c;它要等待其他 4 个任务执行完毕之后才能执行&#xff0c;此时就可以…

计算机应用基础考查方案,《计算机应用基础》考查方案

《计算机应用基础》考查方案 《计算机应用基础》考核方案 制订人&#xff1a;刘久红老师 计算机应用基础科任教师 制订部门&#xff1a;基础课与思政课教学部 制订时间&#xff1a;2012年12月 一&#xff1a;考核依据 计算机应用基础是面向全院各专业开设的一门重要的公共基础课…