菜单

特性优化种之总结

2018年11月15日 - Html/Html5

XCel 项目总:Electron 与 Vue 的性能优化

2017/03/01 · 基本功技术 ·
Javascript,
算法

本文作者: 伯乐在线 –
刘健超-J.c
。未经作者许可,禁止转载!
迎加入伯乐在线 专栏撰稿人。

XCEL 是出于京东用户体验设计部凹凸实验室推出的一个 Excel
数据清洗工具,其经过可视化的措施被用户轻松地对准 Excel 数据开展筛。

XCEL 基被 Electron 和 Vue 2.x,它不仅超越平台(windows 7+、Mac 和
Linux),而且充分利用 Electron 多进程任务处理等效果,使其性出色。

落地页:https://xcel.aotu.io/ ✨✨✨
品种地址:https://github.com/o2team/xcel ✨✨✨

在性能优化品种面临,我只是一个增援参与的角色,但为恰好吃了自身由外表参看项目周转的机遇,需要优化的网就是运行了6年的尽系统,数据从不曾召开过分开,涉及全库查询等致命之优化问题。另外此次项目的老板为期望对优化办事进展指导,造成移动了好多弯路,同时鉴于直数据库技术欠缺,从表找了合作伙伴进行深刻性能优化研讨。
一言以蔽之这项目就算小,但装有了复杂项目的各国地方的内容,我呢用会见指向这个项目开展开的剖析。

种背景

用户研究之定量研究和轻量级数据处理着,均要对数据开展保洁处理,以删异常数据,保证数据结果的信度和效度。目前因调研数据和轻量级数据的多变性,对轻量级数据清洗往往采取人工清洗,缺少统一、标准的清洗流程,但对此调研以及轻量级的数额往往是要保证数据稳定性的,因此,在针对数码进行清洗时最为有格的清洗方法。

基础方向

特征一览

SQL优化

率先要开的即是找来尽款的SQL或业务模块,调查SQL的业务逻辑是不是留存不过优化的空中。

  1. 咱们先举行的凡因作业有于来之暂缓业务,查询相应的SQL,并以测试环境中模仿运行,并记录生产环境与测试环境执行响应SQL的时日
  2. 将最为有代表性的SQL(常用业务)的推行计划列有,并查阅索引的履行情况。在此次项目遭到,发现执行计划没有实行设定的目,这个关键问题也是优化的根本方向。

思路以及实现

冲用研组的急需,利用 Electron 和 Vue 的特点对该工具进行开发。

调表分区

表分区直是数据库优化的主要首选。根据业务将说明按照一定的字段或一定规则进行分区,能够大大提升数据库的特性。但要专注,分区表将影响多少的插效率,与建立目录相同,在成立表分区的进程被假如分析利弊。

艺选型

数据量的增加对性开销的熏陶

品类被在测试环境与生环境,其数据量级别不同,环境布置也差,就见面促成执行同样的SQL或作业得到相反的结果,故在性质优化的初,要起码满足数据量的一块,这样可实现有同等标准的对立统一。
在档次遭到之网,将特定表的数量调整呢同时,执行效率基本相同,这就是说明:

  1. 性能不是促成SQL执行款的瓶颈
  2. 数据量的长会招缓存的多,同时效率变换与缓存大小有关,并且与命中率有关。

实现思路

  1. 经过 js-xlsx 将 Excel 文件分析为 JSON 数据
  2. 冲筛选标准对 JSON 数据开展筛过滤
  3. 以过滤后底 JSON 数据易成 js-xlsx 指定的数据结构
  4. 采用 js-xlsx 对换后底数量生成 Excel 文件

张上得来算觉浅,绝知此事而躬行

宣读写分离

是因为系统的事务数据量过好,且因要求使满足无条件限制的查询,这样即使决然造成全表扫描。为了能查询效率,必须要落实读写分离,在事情时限制才进行读操作(对查询时限要求比较逊色),非业务时间用数据进行联合。

连带技术

设若对有起技术比较熟悉,则可略读/跳了。

有关业主

本次项目之业主,技术负责人针对技术要求颇为苛刻,当然这吗是为项目能顺利进行的必要条件,如何才会适合这样的客户,时限快速迭代,快速反馈?在项目前期,我们呢移步了过多弯路。

  1. 尽的称只能于自己成无头苍蝇
  2. 当起信任危机的时候,建立信任可能曾经是无法挽回的业务
  3. 牵连频率要把握清楚,埋头苦干也使抬头看路

上述是我们在业务关系和从事时起的题目,当然问题的源也时有发生以始发我们针对品种知晓不知情。

Electron

Electron 是什么?

Electron 是一个得用 JavaScript、HTML 和 CSS
构建桌面应用程序的。这些应用程序能自包到 Mac、Windows 和 Linux
系统及运行,也克上架到 Mac 和 Windows 的 App Store。

为何它如此重大?

一般而言来说,每个操作系统的桌面应用还由个别的原生语言进行编制,这表示需要
3 单集体分别吗该采取编写相应版本。而 Electron 则允许你用 Web
语言编写一潮即可。

其由什么做?

Electron 结合了 ChromiumNode.js 和用于调用操作系统本地功能的
API(如打开文件窗口、通知、图标等)。

图片 1

付出体验如何?

因 Electron 的付出就如于出网页,而且会无缝地 使用
Node
。或者说:在构建一个 Node 应用的又,通过 HTML 和 CSS
构建界面。另外,你一味待呢一个浏览器(最新的
Chrome
)进行设计(即无论是需考虑兼容性等)。

少数只经过(重点)

Electron
有个别种进程:『主进程』和『渲染进程』。部分模块只能当双方有上运行,而略则不管界定。主进程更多地任幕后角色,而渲染进程则是应用程序的各个窗口。

流动:可经过任务管理器(PC)/活动监视器(Mac)查看过程的相干消息。

主进程

预示进程,通常是一个命名为 main.js 的文件,该公文是每个 Electron
应用的入口。它控制了采用的生命周期(从打开到关门)。它既是能够调用原生元素,也能缔造新的(多个)渲染进程。另外,Node
API 是放中的。

图片 2

渲染进程

渲染进程是使的一个浏览器窗口。与主进程不同,它能存多独(注:一个
Electron
应用只能是一个主进程)并且互相独立(它呢能是隐藏的)。主窗口一般被命名吧
index.html。它们就是像超人的 HTML 文件,但 Electron 赋予了其完整的
Node API。因此,这也是它们跟浏览器的区分。

图片 3

把她想象变为这么

Chrome(或其它浏览器)的每个标签页(tab)及其页面,就吓于 Electron
中的一个独立渲染进程。即使关闭所有标签页,Chrome 依然存在。这好于
Electron 的主进程,能打开新的窗口还是关闭是用。

流淌:在 Chrome
浏览器中,一个标签页(tab)中的页面(即除浏览器本身有,如搜索框、工具栏等)就是一个渲染进程。

图片 4

相互通讯

鉴于主进程和渲染进程各自负责不同的天职,而对于用一块好的任务,它们需相互通讯。IPC就算也是要非常,它提供了经过中的简报。但其只能以主进程与渲染进程中传递信息(即渲染进程中不能够开展直接通讯)。

图片 5

聚拢成一句话

Electron 应用即比如 Node 应用,它呢依靠一个 package.json
文件。该公文定义了谁文件作为主进程,并因而为 Electron
知道打乌启动以。然后主进程会创建渲染进程,并能使 IPC
让彼此间展开消息传递。

图片 6

至今,Electron
的基础部分介绍完。该部分是依据笔者之前翻的平等篇文章《Essential
Electron》,译文可点击
这里。


Vue 全家桶

拖欠工具使用了 Vue、Vuex、Vuex-router。在工具基本定型阶段,由 1.x 升级到了
2.x。

何以选 Vue

对于笔者来说:

Vue 1.x -> Vue 2.0 的本迁移用
vue-migration-helper
即可分析产生大部分得改变的地方。

网上一度出那么些关于 Vue 的课程,故在斯不再赘言。至此,Vue 部分介绍了。


js-xlsx

该库支持各种电子表格格式的解析及转移。它由 JavaScript 实现,适用于前者和
Node。详情>>

当前支持读入的格式来(不断更新):

支撑写有之格式来:

脚下该库提供的 sheet_to_json 方法能将读入的 Excel 数据转为 JSON
格式。而对导出操作,我们要为 js-xlsx 提供指定的 JSON 格式。

再也多关于 Excel 在 JavaScript
中拍卖的知而查看凹凸实验室的《Node读写Excel文件探究实践》。但该文章是个别处问题(均以
js-xlsx 实战的导出表格部分):

  1. 扭转头部时,Excel 的排列信息简单地经过 String.fromCharCode(65+j)
    生成。当排大于 26 时会起问题。这个题材会见在后章节中于来解决方案;
  2. 改换成为 worksheet
    需要的组织处,出现逻辑性错误,并且会导致严重的特性问题。逻辑问题在这不讲述,我们省性能问题:
    随着 ECMAScript 的不断更新,JavaScript
    变得愈加强有力和易用。尽管如此,我们或如完成『物尽所用』,而非苟『大材小用』,否则可能会见博得“反效果”。这里导致性问题的亏
    Object.assign()
    方法,该法可以将自由多只来自对象的可是枚举属性拷贝至目标靶,并返回目标靶。由于该办法本身的实现机制,会于此案例中起大量底冗余操作。在本案例中,单元格信息是绝无仅有的,所以直接通过
    forEach 为一个缺损对象赋值即可。提升 N
    倍性能的又,也管逻辑性错误解决了。

原来的:

JavaScript

var result = 某数组.reduce((prev, next) => Object.assign({}, prev,
{[next.position]: {v: next.v}}), {});

1
2
var result = 某数组.reduce((prev, next) => Object.assign({}, prev, {[next.position]: {v: next.v}}), {});
 

改为:

JavaScript

var result = 某数组.forEach((v, i) => data[v.position]= {v: v.v})

1
2
var result = 某数组.forEach((v, i) => data[v.position]= {v: v.v})
 

执行是查真理的唯一标准

在理解上述知识后,下面就是讨论在拖欠型实施备受总下的艺、难点和关键

CSS、JavaScript 和 Electron 相关的知识及技巧

高亮 table 的列

Excel 单元格采用 table 标签显示。在 Excel
中,被入选的单元格会高亮相应的『行』和『列』,以提醒用户。在该行使中呢发出召开相应的拍卖,横向高亮用
tr:hover 实现,而纵向呢?这里所使用的一个技能是:

要是 HTML 结构如下:

JavaScript

div.container table tr td

1
2
3
4
5
div.container
  table
    tr
      td
 

CSS 代码如下:

JavaScript

.container { overflow:hidden; } td { position: relative; }
td:hover::after { position: absolute; left: 0; right: 0; top: -1个亿px;
// 小目标及,不过是据的😭 bottom: -1独亿px; z-index: -1; //
避免遮住我及同列 td 的内容、border 等 }

1
2
3
4
5
6
7
8
9
10
11
.container { overflow:hidden; }
td { position: relative; }
td:hover::after {
  position: absolute;
  left: 0;
  right: 0;
  top: -1个亿px; // 小目标达成,不过是负的😭
  bottom: -1个亿px;
  z-index: -1; // 避免遮住自身和同列 td 的内容、border 等
}
 

斜分割线

如图:图片 7

分割线可以透过 ::after/::before 伪类元素实现均等久直线,然后通过
transform:rotate();
旋转特定角度实现。但这种实现的一个题材是:由于宽度是休自然的,因此需要经
JavaScript 运算才会赢得确切之对角分割线。

故而,这里可以透过 CSS 线性渐变
linear-gradient(to top right, transparent, transparent calc(50% - .5px), #d3d6db calc(50% - .5px), #d3d6db calc(50% + .5px), transparent calc(50% + .5px))
实现。无论宽高如何转移,依然妥妥地自适应。

Excel 的列转换

JavaScript

// 将盛传的当数易为26进制表示。映射关系:[0-25] -> [A-Z]。
function getCharCol(n) { let temCol = ”, s = ”, m = 0 while (n >=
0) { m = n % 26 + 1 s = String.fromCharCode(m + 64) + s n = (n – m) / 26
} return s }

1
2
3
4
5
6
7
8
9
10
11
12
13
// 将传入的自然数转换为26进制表示。映射关系:[0-25] -> [A-Z]。
function getCharCol(n) {
  let temCol = ”,
    s = ”,
    m = 0
  while (n >= 0) {
    m = n % 26 + 1
    s = String.fromCharCode(m + 64) + s
    n = (n – m) / 26
  }
  return s
}
 

JavaScript

// 将盛传的26进制转换为自然数。映射关系:[A-Z] ->[0-25]。
function getNumCol(s) { if (!s) return 0 let n = 0 for (let i = s.length

1
2
3
4
5
6
7
8
9
10
11
12
// 将传入的26进制转换为自然数。映射关系:[A-Z] ->[0-25]。
function getNumCol(s) {
  if (!s) return 0
  let n = 0
  for (let i = s.length – 1, j = 1; i >= 0; i–, j *= 26) {
    let c = s[i].toUpperCase()
    if (c < ‘A’ || c > ‘Z’) return 0
    n += (c.charCodeAt() – 64) * j
  }
  return n – 1
}
 

否 DOM 的 File 对象多了 path 属性

Electron 也 File 对象额外增了 path
属性,该属性可得到文件在文件系统上之实事求是路径。因此,你可以使用 Node
为所欲为。应用场景有:拖拽文件后,通过 Node 提供的 File API
读取文件等。

支撑周边的编辑功能,如粘贴和复制

Electron 应用在 MacOS
中默认不支持『复制』『粘贴』等广编辑功能,因此用为 MacOS
显式地安装复制粘贴等编制功能的菜单栏,并也夫设置相应的快捷键。

JavaScript

// darwin 就是 MacOS if (process.platform === ‘darwin’) { var template =
[{ label: ‘FromScratch’, submenu: [{ label: ‘Quit’, accelerator:
‘CmdOrCtrl+Q’, click: function() { app.quit(); } }] }, { label: ‘Edit’,
submenu: [{ label: ‘Undo’, accelerator: ‘CmdOrCtrl+Z’, selector:
‘undo:’ }, { label: ‘Redo’, accelerator: ‘Shift+CmdOrCtrl+Z’, selector:
‘redo:’ }, { type: ‘separator’ }, { label: ‘Cut’, accelerator:
‘CmdOrCtrl+X’, selector: ‘cut:’ }, { label: ‘Copy’, accelerator:
‘CmdOrCtrl+C’, selector: ‘copy:’ }, { label: ‘Paste’, accelerator:
‘CmdOrCtrl+V’, selector: ‘paste:’ }, { label: ‘Select All’, accelerator:
‘CmdOrCtrl+A’, selector: ‘selectAll:’ }] }]; var osxMenu =
menu.buildFromTemplate(template); menu.setApplicationMenu(osxMenu); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// darwin 就是 MacOS
if (process.platform === ‘darwin’) {
    var template = [{
      label: ‘FromScratch’,
      submenu: [{
        label: ‘Quit’,
        accelerator: ‘CmdOrCtrl+Q’,
        click: function() { app.quit(); }
      }]
    }, {
      label: ‘Edit’,
      submenu: [{
        label: ‘Undo’,
        accelerator: ‘CmdOrCtrl+Z’,
        selector: ‘undo:’
      }, {
        label: ‘Redo’,
        accelerator: ‘Shift+CmdOrCtrl+Z’,
        selector: ‘redo:’
      }, {
        type: ‘separator’
      }, {
        label: ‘Cut’,
        accelerator: ‘CmdOrCtrl+X’,
        selector: ‘cut:’
      }, {
        label: ‘Copy’,
        accelerator: ‘CmdOrCtrl+C’,
        selector: ‘copy:’
      }, {
        label: ‘Paste’,
        accelerator: ‘CmdOrCtrl+V’,
        selector: ‘paste:’
      }, {
        label: ‘Select All’,
        accelerator: ‘CmdOrCtrl+A’,
        selector: ‘selectAll:’
      }]
    }];
    var osxMenu = menu.buildFromTemplate(template);
    menu.setApplicationMenu(osxMenu);
}
 

又接近原生应用

Electron
的一个缺陷是:即使你的以是一个概括的钟,但它们吧只能包含圆的底子设备(如
Chromium、Node
等)。因此,一般情况下,打包后底次序至少会达到几十兆(根据网项目进行转移)。当你的利用更加复杂,就愈加可以忽略文件体积问题。

明明,页面的渲染难免会促成『白屏』,而且这里运用了 Vue
这看似框架,情况就算更是糟糕了。另外,Electron
应用也避免不了『先开辟浏览器,再渲染页面』的手续。下面提供几乎种植方法来减轻这种情形,以让程序还靠近原生应用。

  1. 点名 BrowserWindow 的背景颜色;
  2. 先行躲窗口,直到页面加载后再行显;
  3. 保存窗口的尺寸及职务,以给程序下次让辟时,依然保存的平等大小与产出于同的职务上。

对此第一碰,若采用的背景不是纯白(#fff)的,那么可指定窗口的背景颜色及那个平,以避免渲染后的突变。

JavaScript

mainWindow = new BrowserWindow({ title: ‘XCel’, backgroundColor:
‘#f5f5f5’, };

1
2
3
4
5
mainWindow = new BrowserWindow({
    title: ‘XCel’,
    backgroundColor: ‘#f5f5f5’,
};
 

于第二点,由于 Electron
本质是一个浏览器,需要加载非网页部分的资源。因此,我们可以预先躲窗口。

JavaScript

var mainWindow = new BrowserWindow({ title: ‘ElectronApp’, show: false,
};

1
2
3
4
5
var mainWindow = new BrowserWindow({
    title: ‘ElectronApp’,
    show: false,
};
 

齐及渲染进程始起渲染页面的那么一刻,在 ready-to-show
的回调函数中形窗口。

JavaScript

mainWindow.on(‘ready-to-show’, function() { mainWindow.show();
mainWindow.focus(); });

1
2
3
4
5
mainWindow.on(‘ready-to-show’, function() {
    mainWindow.show();
    mainWindow.focus();
});
 

于第三碰,笔者并没有实现,原因如下:

  1. 用户一般是因当下的图景对程序的尺寸及职务展开调整,即视情况如果得。
  2. 以上是自己个人臆测,主要是自家懒。

其二促成方式,可参考《4 must-know tips for building cross platform
Electron
apps》。

怎样在渲染进程调用原生弹框?

当渲染进程面临调用原本专属于主进程遭到之 API (如弹框)的主意来星星点点种:

  1. IPC 通讯模块:先在主进程通过 ipcMain 进行监听,然后于渲染进程经过
    ipcRenderer 进行接触;
  2. remote 模块:该模块为渲染进程与主进程之间提供了飞跃的报导方式。

对于第二种办法,在渲染进程面临,运行以下代码即可:

JavaScript

const remote = require(‘electron’).remote remote.dialog.showMessageBox({
type: ‘question’, buttons: [‘不报告你’, ‘没有梦想’], defaultId: 0,
title: ‘XCel’, message: ‘你的梦想是什么?’ }

1
2
3
4
5
6
7
8
9
10
const remote = require(‘electron’).remote
 
remote.dialog.showMessageBox({
  type: ‘question’,
  buttons: [‘不告诉你’, ‘没有梦想’],
  defaultId: 0,
  title: ‘XCel’,
  message: ‘你的梦想是什么?’
}
 

自动更新

而 Electron
应用尚未供自动更新功能,那么尽管代表用户想体验新出之成效要因故上修复
Bug
后的新本子,只能依靠用户自己主动地去官网下载,这如实是糟糕之体会。Electron
提供的 autoUpdater
模片可实现自动更新功能,该模块提供了第三正在框架
Squirrel 的接口,但 Electron 目前光放了
Squirrel.Mac,且它与
Squirrel.Windows(需要额外引入)的处理方式也未相同(在客户端和服务器端两上面)。因此要对该模块不熟识,处理起来会相对比麻烦。具体可以参照笔者的其它一样篇译文《Electron
自动更新的完整教程(Windows 和
OSX)》。

即 Electron 的 autoUpdater 模块不支持 Linux 系统。

另外,XCel 目前连没有动用 autoUpdater 模块实现自动更新功能,而是以
Electron 的
DownloadItem
模块实现,而服务器端则采取了 Nuts。

呢 Electron 应用生成 Windows 安装包

通过 electron-builder 可径直扭转常见的
MacOS 安装包,但她生成的 Windows 的装包可多少发简洁(默认选项项时)。

图片 8
Mac 常见的设置模式,将“左侧的使图标”拖拽到“右侧的 Applications”即可

透过 electron-builder 生成的 Windows 安装包与我们在 Windows
上常见的软件设置界面不绝雷同,它从未安装向导和点击“下一样步”的按钮,只出一个安时的
gif 动画(默认的 gif 动画如下图,当然你为堪指定特定的 gif
动画),因此也尽管倒闭了用户挑选安装路径等权利。

图片 9
Windows 安装时 默认显示的 gif
动画

一旦您想啊包装后底 Electron 应用(即透过
electron-packager/electron-builder
生成的,可径直运行的顺序目录)生成有点击“下一致步”按钮和而于用户指定安装路径的周边安装包,可以尝尝
NSIS 程序,具体但圈就首教程 《[教學]单设10分鐘學會使用 NSIS
包裝您的桌面軟體–安裝程式打包。完全免費。》。

流动:electron-builder
也提供了转安装包之安排起,实际查看>>。

NSIS(Nullsoft Scriptable Install System)是一个开源之 Windows
系统下安装程序制作程序。它提供了设置、卸载、系统装置、文件解压缩等作用。正而该名所描述的那么,NSIS
是通过它的脚本语言来描述安装程序的行以及逻辑的。NSIS
的脚本语言和科普的编程语言来类似的结构和语法,但她是吗安装程序这类似应用所计划的。

时至今日,CSS、JavaScript 和 Electron 相关的文化与技能有阐述了。


性能优化

下谈谈『性能优化』,这片提到到运作效率内存占用量
横流:以下内容均冲 Excel 样例文件(数据量为:1913 行 x 180
列)得出的结论。

尽效率及渲染之优化

Vue 性能真的吓?

Vue 一直表现着温馨性优异,但当数据量上升至自然量级时(如 1913 x 180 ≈
34 万只数据单元),会冒出严重的习性问题(未开相应优化的前提下)。

一经直接通过列表渲染 v-for 渲染数据常常,会招致程序卡死。
报:通过翻有关材料可得, v-for
在首位渲染时,需要针对每个子项进行初始化(如数据绑定等操作,以便拥有更快的创新快),这对数据量较生时,无疑会导致深重的属性问题。

旋即,我想开了少于栽缓解思路:

  1. Vue 是数量让视图的,对数据分段 push,即以一个巨大的职责分割为 N
    份。
  2. 温馨并接 HTML 字符串,再经 innerHTML 一次性插入。

末,我选择了次漫长,理由是:

  1. 特性最佳,因为老是执行多少过滤时,Vue 都设开展 diff,性能不美。
  2. 再也切合当下以的需要:纯展示且无需动画过渡等。
  3. 落实重新简短

用本来繁重的 DOM 操作(Vue)转换为 JavaScript
的拼接字符串后,性能得到了那个充分提升(不见面导致程序卡死而渲染不闹视图)。这种优化措施难道不就是
Vue、React
等框架解决之题材有吧?只不过框架考虑的观更普遍,有些地方用我们温馨根据实际状况进行优化而已。

在浏览器中,JavaScript 的运算在现世底发动机中充分快,但 DOM
本身是雅慢的物。当您调用原生 DOM API 的时段,浏览器需要在
JavaScript 引擎的语境下接触原生的 DOM
的兑现,这个进程发生相当的特性损耗。所以,本质之勘察是,要拿吃时间的操作尽量在纯粹的计着失做,保证最后计算出来的需要实际点实际
DOM 的操作是不过少之。 —— 《Vue
2.0——渐进式前端解决方案》

本来,由于 JavaScript
天生单线程,即使实施数速度又抢,也在所难免会造成页面有短暂之时间不容用户之输入。此时可是经过
Web Worker 或其它措施化解,这也用是咱们累讲到的题材。

也闹网友供了优化大量列表的法门:https://clusterize.js.org/。但于该案例中笔者并无行使这方式。

强大的 GPU 加速

以拼接的字符串插入 DOM
后,出现了另外一个问题:滚动会很卡。猜想这是渲染问题,毕竟 34
万单单元格同时设有于界面中。

添加 transform: translate3d(0, 0, 0) / translateZ(0) 属性启动 GPU
渲染,即可缓解这渲染性能问题。再次感叹该属性的有力。

后来,考虑到用户并不需要查看所有数量,只需要出示部分数据让用户展开参考即可。我们对是才渲染前
30/50 行数据。这样即可提升用户体验,也克更优化性能。

记关闭 Vuex 的严厉模式

此外,由于投机学艺不强和疏忽,忘记在生养环境关闭 Vuex
的『严格模式』。

Vuex 的从严模式使于产环境面临关闭,否则会针对 state 树进行一个深观察
(deep
watch),产生不必要的特性损耗。也许在数据量少时,不会见小心到之题目。

回复当时之观:导入 Excel 数据后,再进行相互(涉及 Vuex
的读写操作),需要等几秒才会应,而一直通过纯 DOM
监听的轩然大波则凭此题材。由此,判断发生是 Vuex 问题。

JavaScript

const store = new Vuex.Store({ // … strict: process.env.NODE_ENV !==
‘production’ })

1
2
3
4
5
const store = new Vuex.Store({
  // …
  strict: process.env.NODE_ENV !== ‘production’
})
 

多进程!!!

前方说道,JavaScript
天生单线程,即使再快,对于数据量较充分时,也会见现出拒绝响应的问题。因此用
Web Worker 或近似的方案去化解。

当此地自己无选择 Web worker 的原故来如下几触及:

  1. 产生任何更好之代方案:一个主进程能创建多单渲染进程,通过 IPC
    即可进展多少交互;
  2. Electron 不支持 Web
    Worker!(当然,可能会见在新本子支持,最新信息请关注官方)

Electron 作者在 2014.11.7 在《state of web worker support?》 issue
中恢复了以下就等同段:

Node integration doesn’t work in web workers, and there is no plan to
do. Workers in Chromium are implemented by starting a new thread, and
Node is not thread safe. Back in past we had tried to add node
integration to web workers in Atom, but it crashed too easily so we
gave up on it.

所以,我们最后采取了创一个初的渲染进程 background process
进行拍卖数据。由 Electron 章节可知,每个 Electron
渲染进程是独的,因此它不会见相互影响。但随即吗带动了一个题材:它们不克相互通讯?

错!下面有 3 种植办法进行报道:

  1. Storage
    API:对某标签页的
    localStorage/sessionStorage 对象开展增删改时,其他标签页能通过
    window.storage 事件监听到。
  2. IndexedDB:IndexedDB
    是一个为了能在客户端存储可观数额的结构化数据,并且以这些数据及行使索引进行高性能检索的
    API。
  3. 透过主进程作为中转站:设主界面的渲染进程是 A,background process
    是 B,那么 A 先将 Excel 数据传递至主进程,然后主进程又转发到 B。B
    处理了晚重新原路返回,具体要下图。当然,也可用数据存储在主进程中,然后于差不多个渲染进程遭到动用
    remote 模块来拜会它。

该工具采用了第三种方式的第一栽情景:
图片 10

1、主页面渲染进程 A 的代码如下:

JavaScript

//① ipcRenderer.send(‘filter-start’, { filterTagList:
this.filterTagList, filterWay: this.filterWay, curActiveSheetName:
this.activeSheet.name }) // ⑥ 在某处接收 filter-response 事件
ipcRenderer.on(“filter-response”, (arg) => { // 得到处理数据 })

1
2
3
4
5
6
7
8
9
10
11
12
//①
ipcRenderer.send(‘filter-start’, {
    filterTagList: this.filterTagList,
    filterWay: this.filterWay,
    curActiveSheetName: this.activeSheet.name
})
 
// ⑥ 在某处接收 filter-response 事件
ipcRenderer.on("filter-response", (arg) => {
    // 得到处理数据
})
 

2、作为中转站的主进程的代码如下:

JavaScript

//② ipcMain.on(“filter-start”, (event, arg) => { // webContents
用于渲染和操纵 web page
backgroundWindow.webContents.send(“filter-start”, arg) }) // ⑤
用于吸纳返回事件 ipcMain.on(“filter-response”, (event, arg) => {
mainWindow.webContents.send(“filter-response”, arg) })

1
2
3
4
5
6
7
8
9
10
11
//②
ipcMain.on("filter-start", (event, arg) => {
    // webContents 用于渲染和控制 web page
    backgroundWindow.webContents.send("filter-start", arg)
})
 
// ⑤ 用于接收返回事件
ipcMain.on("filter-response", (event, arg) => {
    mainWindow.webContents.send("filter-response", arg)
})
 

3、处理繁重数据的 background process 渲染进程 B 的代码如下:

JavaScript

// ③ ipcRenderer.on(‘filter-start’, (event, arg) => { // 进行演算 …
// ④ 运算完毕后,再经过 IPC 原行程返回。主进程和渲染进程 A
也要建立相应的监听事件 ipcRenderer.send(‘filter-response’, { filRow:
tempFilRow }) })

1
2
3
4
5
6
7
8
9
10
11
// ③
ipcRenderer.on(‘filter-start’, (event, arg) => {
    // 进行运算
    …
 
    // ④ 运算完毕后,再通过 IPC 原路返回。主进程和渲染进程 A 也要建立相应的监听事件
    ipcRenderer.send(‘filter-response’, {
        filRow: tempFilRow
    })
})
 

至此,我们将『读取文件』、『过滤数据』和『导出文件』三百般耗时的数操作均易到了
background process 中处理。

此,我们惟有创造了一个
background process,如果想要召开得重不过,我们好新建『CPU 线程数- 1 』
个的 background process
同时针对数码进行拍卖,然后于主进程对处理后数开展拼接,最后更将拼接后底多少返回到主页面的渲染进程。这样便足以尽管榨干
CPU 了。当然,在此笔者非见面进行这个优化。

不用为优化而优化,否则得不偿失。 —— 某网友

内存占有量过十分

釜底抽薪了实施效率及渲染问题后,发现也在内存占用量过好的问题。当时猜测是以下几只原因:

  1. 老三分外耗时操作都放置于 background process
    处理。在通讯传递数据的经过遭到,由于无是共享内存(因为 IPC 是因
    Socket
    的),导致出现多份数据副本(在描绘这篇文章时才发生了马上相对方便的答案)。
  2. Vuex
    是盖一个大局单例的模式开展管制,但其会是匪是指向数据做了少数封装,而致使性的淘呢?
  3. 是因为 JavaScript
    目前无享有积极回收资源的力量,所以只能积极对闲置对象设置也
    null,然后等待 GC 回收。

由 Chromium 采用多进程架构,因此会涉嫌到过程之中通信问题。Browser
进程在开行 Render 进程的过程中会建立一个为 UNIX Socket 为根基的 IPC
通道。有矣 IPC 通道后,接下去 Browser 进程和 Render
进程就盖信之款型展开通信。我们拿这种消息称 IPC
消息,以界别为线程消息循环中之消息。
——《Chromium的IPC消息发送、接收及散发机制分析》

概念:为了容易理解,以下『Excel 数据』均指 Excel 的整套有效单元格转为
JSON 格式后的数目。

尽轻处理的确凿是第三碰,手动将不再用之变量及时安装也
null,但作用并无明朗。

新生,通过操作系统的『活动监视器』(Windows
上是天职管理器)对拖欠工具的各级路(打开时、导入文本时、筛选时以及导出时)进行简短的内存分析,得到以下报告:

—————- S:报告分割线 —————-
经观察,主要耗内存的凡页面渲染进程。下面通过截图证明:
PID 15243 是主进程
PID 15246 是页面渲染进程
PID 15248 是 background 渲染进程

a、首不善开行程序时(第 4 行是主进程;第 1 行是页面渲染进程;第 3 行是
background 渲染进程 )

图片 11

b、导入文本(第 5 行是主进程;第 2 行是页面渲染进程;第 4 行是
background 渲染进程 )
图片 12

c、筛选数据(第 4 行是主进程;第 1 行是页面渲染进程;第 3 行是
background 渲染进程 )
图片 13

出于 JavaScript 目前不备积极回收资源的力量,所以只好积极以对象设置为
null,然后等待 GC 回收。

因而,经过一段时间等待后,内存占用如下:
d、一段时间后(第 4 行是主进程;第 1 行是页面渲染进程;第 3 行是
background 渲染进程 )
图片 14

是因为上述可得,页面渲染进程由于页面元素和 Vue 等 UI
相关资源是稳的,占用内存较生且未可知回收。主进程占用资源为不能够得充分好放,暂时无知情原委,而
background 渲染进程则较好地放走资源。

—————- E:报告分割线 —————-

据悉报告,初步得出的结论是 Vue 和报道时占用资源比较生。

冲拖欠工具的莫过于应用场景:Excel
数据仅在『导入』和『过滤后』两只号需要展示,而且显示的是由此
JavaScript 拼接的 HTML 字符串所结合的 DOM 而已。因此将表格数据放置于
Vuex 中,有硌滥用资源的疑心。

另外,在 background process 中为有怀来平等客 Excel
数据副本。因此,索性单当 background process 存储一卖 Excel
数据,然后在数据变化时,通过 IPC 让 background process 返回拼接好之
HTML
字符串即可。这样一来,内存占有量立刻跌落多。另外,这吗是一个一举多得之优化:

  1. 字符串拼接操作为易到了
    background process,页面渲染进程进一步削减耗时底操作;
  2. 内存占有量大大削弱多少,响应速度也得到了提升。

骨子里,这吗生接触像 Vuex 的『全局单例模式管理』,一卖数据就好。

本,对于 Excel 的中坚信息,如行列数、SheetName、标题组等清一色仍保留于
Vuex。

优化后底内存占有量如下图。与上述报告的老三张图相比(同一等级),内存占有量下降了
44.419%: 图片 15
另外,对于不需要应的多少,可经 Object.freeze()
冻结起来。这为是一样栽优化手段。但拖欠工具目前并没有行使至。

从那之后,优化部分也阐述了了!


该工具目前凡开源的,欢迎大家用还是引进给用研组等有需要的人数。

你们的反馈(可领交 issues /
pull
request)能叫这家伙在采用和效能及不断完善。

最后,感谢 LV
在成品规划、界面设计和优化及之强力支撑。全文完!

打赏支持我形容有又多好文章,谢谢!

打赏作者

打赏支持自己写有重新多好文章,谢谢!

任选一栽出办法

图片 16
图片 17

1 赞 2 收藏
评论

关于作者:刘健超-J.c

图片 18

前端,在路上…http://jchehe.github.io
个人主页 ·
我之稿子 ·
19 ·
    

图片 19

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图