Nodejs通过Thrift操作hbase卡住原因分析及与javascript的垃圾回收机制的关系
在最近使用Nodejs通过Thrift操作hbase的时候写了个脚本,不断发送http请求,从而取得hbase下所需的数据,但是在run的过程中for循环并没有执行完全,在执行一部分后会卡住,就再也进不到hbase下取数据,出现socket hang up的错误,查了很多资料也没解决。当时认为是hbase的并发数问题,其并发数的限制导致了资源负载的极限,后来不断测试找到原因所在,其实与hbase处理并发的能力无关,真正的原因是jsvascript的垃圾回收机制使得资源使用达到瓶颈,下面是代码处理前与处理后的对比:
var thrift = require('thrift'),
HBase = require('./gen-nodejs/Hbase.js'),
HBaseTypes = require('./gen-nodejs/Hbase_types.js'),
connection = thrift.createConnection('localhost', 9090, {
transport: thrift.TFramedTransport,
protocol: thrift.TBinaryProtocol
}); var client = thrift.createClient(HBase,connection); /*router.get('/', function(req, res)
{ res.render('index', { title: 'Welcome' }); });*/ router.get('/search', function(req, res)
{ var dateTimeArray = {};
var valueArray = {};
var searchPlateBegin = null;
var searchPlateEnd = null;
var searchDetailsBegin = null;
var searchDetailsEnd = null;
var convertReverseArray = new Array();
}
/*router.get('/', function(req, res)
{ res.render('index', { title: 'Welcome' }); });*/ router.get('/search', function(req, res)
{ var dateTimeArray = {};
var valueArray = {};
var searchPlateBegin = null;
var searchPlateEnd = null;
var searchDetailsBegin = null;
var searchDetailsEnd = null;
var convertReverseArray = new Array(); var thrift = require('thrift'),
HBase = require('./gen-nodejs/Hbase.js'),
HBaseTypes = require('./gen-nodejs/Hbase_types.js'),
connection = thrift.createConnection('localhost', 9090, {
transport: thrift.TFramedTransport,
protocol: thrift.TBinaryProtocol
}); var client = thrift.createClient(HBase,connection);
}
两段代码的唯一区别就是thrift连接hbase的几行代码是否放在了路由search下,在运行的脚本之中不断地请求该路由这就是原因所在,由于不断请求,每请求一次都会进行一次thrift连接hbase,那段代码看似很简单,其实背后的运行很复杂,包括hbase中库的添加,结构组织,内存的分配等等,这样循环下去就创建了非常多的thrift对象,由于JavaScript垃圾回收机制的延时性不可能都进行回收,这样方法对象的不断增多就会造成thrift从hbase中请求数据的阻塞,就像我们看到的那样,卡在了那里。
下面来说一下javascript的回收机制:
现在各大浏览器通常用采用的垃圾回收有两种方法:标记清除、引用计数。
1.标记清除:
这是JavaScript最常见的垃圾回收方式,当变量进入执行环境的时候,比如函数中声明一个变量,垃圾回收器将其标记为“进入环境”,当变量离开环境的时候(函数执行结束)将其标记为“离开环境”。至于怎么标记有很多种方式,比如特殊位的反转、维护一个列表等,这些并不重要,重要的是使用什么策略,原则上讲不能够释放进入环境的变量所占的内存,它们随时可能会被调用的到。
垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量以及被环境中变量所引用的变量(闭包),在这些完成之后仍存在标记的就是要删除的变量了,因为环境中的变量已经无法访问到这些变量了,然后垃圾回收器相会这些带有标记的变量机器所占空间。
2.引用计数:
另一种不太常见的垃圾回收策略是引用计数。引用计数的含义是跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型赋值给该变量时,则这个值的引用次数就是1。相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数就减1。当这个引用次数变成0时,则说明没有办法再访问这个值了,因而就可以将其所占的内存空间给收回来。这样,垃圾收集器下次再运行时,它就会释放那些引用次数为0的值所占的内存。
比如对象A有一个属性指向对象B,而对象B也有有一个属性指向对象A,这样相互引用
function test(){
var a={};
var b={};
a.prop=b;
b.prop=a;
}
这样a和b的引用次数都是2,即使在test()执行完成后,两个对象都已经离开环境,在标记清除的策略下是没有问题的,离开环境的就被清除,但是在引用计数策略下不行,因为这两个对象的引用次数仍然是2,不会变成0,所以其占用空间不会被清理,如果这个函数被多次调用,这样就会不断地有空间不会被回收,造成内存泄露。
减少JavaScript中的垃圾回收:
1.数组Array优化:
将[]赋值给一个数组对象,是清空数组的捷径(例如: arr = [];),但是需要注意的是,这种方式又创建了一个新的空对象,并且将原来的数组对象变成了一小片内存垃圾!实际上,将数组长度赋值为0(arr.length = 0)也能达到清空数组的目的,并且同时能实现数组重用,减少内存垃圾的产生。
2.函数function优化:
方法一般都是在初始化的时候创建,并且此后很少在运行时进行动态内存分配,这就使得导致内存垃圾产生的方法,找起来就不是那么容易了。但是从另一角度来说,这更便于我们寻找了,因为只要是动态创建方法的地方,就有可能产生内存垃圾。
setTimeout(
(function(self) {
return function () {
self.tick();
};
})(this), 16)
每过16毫秒调用一次this.tick(),嗯,乍一看似乎没什么问题,但是仔细一琢磨,每一次调用都返回了一个新的方法对象,这就导致了大量的方法对象垃圾!
可以将作为返回值的方法保存起来,例如:
this.tickFunc = (
function(self) {
return function() {
self.tick();
};
}
)(this); // in the tick() function
setTimeout(this.tickFunc, 16);
相比于每次都新建一个方法对象,这种方式在每一帧当中重用了相同的方法对象。这种方式的优势是显而易见的,而这种思想也可以应用在任何以方法为返回值或者在运行时创建方法的情况当中。
Nodejs通过Thrift操作hbase卡住原因分析及与javascript的垃圾回收机制的关系的更多相关文章
- python全栈开发,Day44(IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)
昨日内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yield,greenlet 遇到IO gevent: 检测到IO,能够使用greenlet实现自动切换,规避了IO阻 ...
- java中存在垃圾回收机制,但是还会有内存泄漏的问题,原因是
答案是肯定的,但不能拿这一句回答面试官的问题.分析:JAVA是支持垃圾回收机制的,在这样的一个背景下,内存泄露又被称为“无意识的对象保持”.如果一个对象引用被无意识地保留下来,那么垃圾回收器不仅不会处 ...
- PHP通过Thrift操作Hbase
PHP通过Thrift操作Hbase HBase是一个开源的NoSQL产品,它是实现了Google BigTable论文的一个开源产品,和Hadoop和HDFS一起,可用来存储和处理海量col ...
- python 全栈开发,Day44(IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)
昨日内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yield,greenlet 遇到IO gevent: 检测到IO,能够使用greenlet实现自动切换,规避了IO阻 ...
- (IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)
参考博客: https://www.cnblogs.com/xiao987334176/p/9056511.html 内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yi ...
- java面试官最爱问的垃圾回收机制,这位阿里P7大佬分析的属实到位
前言 JVM 内存模型一共包括三个部分: 堆 ( Java代码可及的 Java堆 和 JVM自身使用的方法区). 栈 ( 服务Java方法的虚拟机栈 和 服务Native方法的本地方法栈 ) 保证程序 ...
- js 垃圾回收机制和引起内存泄漏的操作
垃圾回收机制 JS中最常见的垃圾回收方式是标记清除. 工作原理:是当变量进入环境时,将这个变量标记为“进入环境”.当变量离开环境时,则将其标记为“离开环境”.标记“离开环境”的就回收内存. 工作流程: ...
- Chrome 浏览器垃圾回收机制与内存泄漏分析
Chorme 浏览器中的垃圾回收和内存泄漏 垃圾回收 通常情况下,垃圾数据回收分为手动回收和自动回收两种策略. 手动回收策略,何时分配内存.何时销毁内存都是由代码控制的. 自动回收策略,产生的垃圾数据 ...
- JVM中垃圾回收机制如何判断是否死亡?详解引用计数法和可达性分析 !
因为热爱,所以坚持. 文章下方有本文参考电子书和视频的下载地址哦~ 这节我们主要讲垃圾收集的一些基本概念,先了解垃圾收集是什么.然后触发条件是什么.最后虚拟机如何判断对象是否死亡. 一.前言 我们 ...
随机推荐
- LeetCode OJ——Unique Binary Search Trees
class Solution { public: int numTrees(int n) { ); vector<int> numVector; numVector.assign(n+,) ...
- Group by 两表联查取另一表与之关联数据的总数
使用group by 需要查询的字段 必须要放在group by 后面 SELECT U.UserLotterySn,count(W.Userlotterysn) as WinCount,U.Acti ...
- 使用KNN对iris数据集进行分类——python
filename='g:\data\iris.csv' lines=fr.readlines()Mat=zeros((len(lines),4))irisLabels=[]index=0for lin ...
- BZOJ 1044 木棍分割(二分答案 + DP优化)
题目链接 木棍分割 1044: [HAOI2008]木棍分割 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3830 Solved: 1453[S ...
- 洛谷——P2149 [SDOI2009]Elaxia的路线
P2149 [SDOI2009]Elaxia的路线 题目描述 最近,Elaxia和w的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间.Elaxia和w每 ...
- 洛谷——P1220 关路灯
P1220 关路灯 题目描述 某一村庄在一条路线上安装了n盏路灯,每盏灯的功率有大有小(即同一段时间内消耗的电量有多有少).老张就住在这条路中间某一路灯旁,他有一项工作就是每天早上天亮时一盏一盏地关掉 ...
- codeforces A. In Search of an Easy Problem
A. In Search of an Easy Problem time limit per test 1 second memory limit per test 256 megabytes inp ...
- CEF General Usage(CEF3预览)
CEF General Usage(CEF3预览) 介绍 CEF全称Chromium Embedded Framework,是一个基于Google Chromium 的开源项目.Google Chro ...
- 将压缩包文件(rar/zip)伪装成图片(jpg/gif/png/ico)
1.在Windows上使用copy命令,缺点是只能是jpg文件,gif不支持,命令如下: copy in1.jpg+in2.rar out.jpg 2.网上说使用UEdit方式可以制作gif,但是测试 ...
- Android自定义控件之基本原理(一)
前言: 在日常的Android开发中会经常和控件打交道,有时Android提供的控件未必能满足业务的需求,这个时候就需要我们实现自定义一些控件,今天先大致了解一下自定义控件的要求和实现的基本原理. 自 ...