在本文中,我们将探讨客户端JavaScript代码中常见的内存泄漏类型。 我们还将学习如何使用Chrome开发工具找到它们。
1、介绍
内存泄漏是每个开发人员都要面临的问题。 即使使用内存管理的语言,也存在内存泄漏的情况。 内存泄漏是导致迟缓,崩溃,高延迟的根本原因,甚至会导致其他应用问题。
2、什么是内存泄露
实质上,内存泄漏可以定义为应用程序不再需要的内存,因为某种原因其不会返回到操作系统或可用内存池。编程语言有不同的管理内存的方式。这些方法可以减少泄漏内存的机会。然而,某一块内存是否未被使用实际上是一个不可判定的问题。 换句话说,只有开发人员才能明确是否可以将一块内存返回到操作系统。 某些编程语言提供了帮助开发人员执行此操作的功能。
3、JavaScript的内存管理
JavaScript是垃圾回收语言之一。 垃圾回收语言通过定期检查哪些先前分配的内存是否“可达”来帮助开发人员管理内存。 换句话说,垃圾回收语言将管理内存的问题从“什么内存仍可用? 到“什么内存仍可达?”。区别是微妙的,但重要的是:虽然只有开发人员知道将来是否需要一块分配的内存,但是不可达的内存可以通过算法确定并标记为返回到操作系统。
非垃圾回收的语言通常使用其他技术来管理内存:显式管理,开发人员明确告诉编译器何时不需要一块内存; 和引用计数,其中使用计数与存储器的每个块相关联(当计数达到零时,其被返回到OS)。
4、JavaScript的内存泄露
垃圾回收语言泄漏的主要原因是不需要的引用。要理解什么不需要的引用,首先我们需要了解垃圾回收器如何确定一块内存是否“可达”。
垃圾回收语言泄漏的主要原因是不需要的引用。
Mark-and-sweep
大多数垃圾回收器使用称为标记和扫描的算法。该算法由以下步骤组成:
1、垃圾回收器构建一个“根”列表。根通常是在代码中保存引用的全局变量。在JavaScript中,“window”对象是可以充当根的全局变量的示例。窗口对象总是存在的,所以垃圾回收器可以考虑它和它的所有的孩子总是存在(即不是垃圾)。
2、所有根被检查并标记为活动(即不是垃圾)。所有孩子也被递归检查。从根可以到达的一切都不被认为是垃圾。
3、所有未标记为活动的内存块现在可以被认为是垃圾。回收器现在可以释放该内存并将其返回到操作系统。
现代垃圾回收器以不同的方式改进了该算法,但本质是相同的:可访问的内存段被标记,其余被垃圾回收。不需要的引用是开发者知道它不再需要,但由于某种原因,保存在活动根的树内部的内存段的引用。 在JavaScript的上下文中,不需要的引用是保存在代码中某处的变量,它不再被使用,并指向可以被释放的一块内存。 有些人会认为这些都是开发者的错误。所以要了解哪些是JavaScript中最常见的漏洞,我们需要知道在哪些方式引用通常被忽略。
5、四种常见的JavaScript 内存泄漏
JavaScript背后的目标之一是开发一种看起来像Java的语言,容易被初学者使用。 JavaScript允许的方式之一是处理未声明的变量:对未声明的变量的引用在全局对象内创建一个新的变量。 在浏览器的情况下,全局对象是窗口。 换一种说法:
function foo(arg) {
bar = "this is a hidden global variable";
}
事实上: function foo(arg) { window.bar = "this is an explicit global variable"; } 如果bar应该只在foo函数的范围内保存对变量的引用,并且您忘记使用var来声明它,那么会创建一个意外的全局变量。 在这个例子中,泄漏一个简单的字符串可能没什么,但有更糟糕的情况。
创建偶然的全局变量的另一种方式是通过下面这样:
function foo() {
this.variable = "potential accidental global";
}
// Foo called on its own, this points to the global object (window)
// rather than being undefined.
foo();
为了防止这些错误发生,添加'use strict'; 在您的JavaScript文件的开头。 这使得能够更严格地解析JavaScript以防止意外的全局变量。
即使我们讨论了不可预测的全局变量,但是仍有一些明确的全局变量产生的垃圾。这些是根据定义不可回收的(除非被取消或重新分配)。特别地,用于临时存储和处理大量信息的全局变量是令人关注的。 如果必须使用全局变量来存储大量数据,请确保将其置空或在完成后重新分配它。与全局变量有关的增加的内存消耗的一个常见原因是高速缓存)。缓存存储重复使用的数据。 为了有效率,高速缓存必须具有其大小的上限。 无限增长的缓存可能会导致高内存消耗,因为缓存内容无法被回收。
setInterval的使用在JavaScript中是很常见的。大多数这些库在它们自己的实例变得不可达之后,使得对回调的任何引用不可达。在setInterval的情况下,但是,像这样的代码是很常见的:
var someResource = getData();
setInterval(function() {
var node = document.getElementById('Node');
if(node) {
// Do stuff with node and someResource.
node.innerHTML = JSON.stringify(someResource));
}
}, 1000);
此示例说明了挂起计时器可能发生的情况:引用不再需要的节点或数据的计时器。 由节点表示的对象可以在将来被移除,使得区间处理器内部的整个块不需要了。 但是,处理程序(因为时间间隔仍处于活动状态)无法回收(需要停止时间间隔才能发生)。 如果无法回收间隔处理程序,则也无法回收其依赖项。 这意味着someResource,它可能存储大小的数据,也不能被回收。
对于观察者的情况,重要的是进行显式调用,以便在不再需要它们时删除它们(或者相关对象即将无法访问)。 在过去,以前特别重要,因为某些浏览器(Internet Explorer 6)不能管理循环引用(参见下面的更多信息)。 现在,一旦观察到的对象变得不可达,即使没有明确删除监听器,大多数浏览器也可以回收观察者处理程序。 然而,在对象被处理之前显式地删除这些观察者仍然是良好的做法。 例如:
var element = document.getElementById('button');
function onClick(event) {
element.innerHtml = 'text';
}
element.addEventListener('click', onClick);
// Do stuff
element.removeEventListener('click', onClick);
element.parentNode.removeChild(element);
// Now when element goes out of scope,
// both element and onClick will be collected even in old browsers that don't
// handle cycles well.
关于对象观察者和循环引用:
观察者和循环引用曾经是JavaScript开发者的祸根。 这是由于Internet Explorer的垃圾回收器中的错误(或设计决策)。旧版本的Internet Explorer无法检测DOM节点和JavaScript代码之间的循环引用。这是一个典型的观察者,通常保持对可观察者的引用(如上例所示)。换句话说,每当观察者被添加到Internet Explorer中的一个节点时,它就会导致泄漏。这是开发人员在节点或在观察者中引用之前明确删除处理程序的原因。 现在,现代浏览器(包括Internet Explorer和Microsoft Edge)使用现代垃圾回收算法,可以检测这些周期并正确处理它们。 换句话说,在使节点不可达之前,不必严格地调用removeEventListener。框架和库(jQuery)在处理节点之前删除侦听器(当为其使用特定的API时)。这是由库内部处理,并确保不产生泄漏,即使运行在有问题的浏览器,如旧的Internet Explorer。
有时,将DOM节点存储在数据结构中可能很有用。 假设要快速更新表中多行的内容。 在字典或数组中存储对每个DOM行的引用可能是有意义的。 当发生这种情况时,会保留对同一个DOM元素的两个引用:一个在DOM树中,另一个在字典中。 如果在将来的某个时候,您决定删除这些行,则需要使这两个引用不可访问。
var elements = {
button: document.getElementById('button'),
image: document.getElementById('image'),
text: document.getElementById('text')
};
function doStuff() {
image.src = 'http://some.url/image';
button.click();
console.log(text.innerHTML);
// Much more logic
}
function removeButton() {
// The button is a direct child of body.
document.body.removeChild(document.getElementById('button'));
// At this point, we still have a reference to #button in the global
// elements dictionary. In other words, the button element is still in
// memory and cannot be collected by the GC.
}
对此的另外考虑与对DOM树内的内部或叶节点的引用有关。 假设您在JavaScript代码中保留对表的特定单元格(
标记)的引用。 在将来的某个时候,您决定从DOM中删除表,但保留对该单元格的引用。 直观地,可以假设GC将回收除了该单元之外的所有东西。 在实践中,这不会发生:单元格是该表的子节点,并且子级保持对其父级的引用。 换句话说,从JavaScript代码对表单元格的引用导致整个表保留在内存中。 在保持对DOM元素的引用时仔细考虑这一点。
JavaScript开发的一个关键方面是闭包:从父作用域捕获变量的匿名函数。 Meteor开发人员发现了一个特定的情况,由于JavaScript运行时的实现细节,可能以一种微妙的方式泄漏内存:
var theThing = null;
var replaceThing = function () {
var originalThing = theThing;
var unused = function () {
if (originalThing)
console.log("hi");
};
theThing = {
longStr: new Array(1000000).join('*'),
someMethod: function () {
console.log(someMessage);
}
};
};
setInterval(replaceThing, 1000);
这个片段做了一件事:每次replaceThing被调用,theThing获取一个新的对象,其中包含一个大数组和一个新的闭包(someMethod)。同时,unused变量保持一个闭包,该闭包具有对originalThing的引用(来自之前对replaceThing的调用的Thing)。已经有点混乱了,是吗?重要的是,一旦为同一父作用域中的闭包创建了作用域,则该作用域是共享的。在这种情况下,为闭包someMethod创建的作用域由unused共享。unused的引用了originalThing。即使unused未使用,可以通过theThing使用someMethod。由于someMethod与unused共享闭包范围,即使未使用,它对originalThing的引用强制它保持活动(防止其收集)。当此代码段重复运行时,可以观察到内存使用量的稳定增加。这在GC运行时不会变小。实质上,创建一个闭包的链接列表(其根以theThing变量的形式),并且这些闭包的范围中的每一个都包含对大数组的间接引用,导致相当大的泄漏。
Meteor的博文解释了如何修复此种问题。在replaceThing的最后添加originalThing = null。
垃圾回收器的不直观行为:
虽然垃圾回收器很方便,但他们有自己的一套权衡。 这些权衡之一是非确定性。 换句话说,GC是不可预测的。 通常不可能确定何时执行回收。 这意味着在某些情况下,正在使用比程序实际需要的更多的内存。 在其他情况下,短暂停顿在特别敏感的应用中可能是明显的。 虽然非确定性意味着无法确定何时执行集合,但大多数GC实现都分享在分配期间执行集合传递的常见模式。 如果没有执行分配,则大多数GC保持静止。 考虑以下情况:
1、执行相当大的一组分配。
2、大多数这些元素(或所有这些元素)被标记为不可达(假设我们使指向我们不再需要的缓存的引用为空)。
3、不执行进一步的分配。
在这种情况下,大多数GC不会运行任何进一步的集合过程。 换句话说,即使有不可达的引用可用于回收,回收器也不会回收这些引用。 这些不是严格的泄漏,但仍然导致高于通常的内存使用。
Google在他们的JavaScript内存分析文档中提供了这种行为的一个很好的例子,next!!!。
6、Chrome内存分析工具概述
Chrome提供了一组很好的工具来分析JavaScript代码的内存使用情况。 有两个与内存相关的基本视图:时间轴视图和配置文件视图。
TimeLine对于在代码中发现异常内存模式至关重要。 如果我们正在寻找大的泄漏,周期性的跳跃,收缩后不会收缩,就像一个红旗。 在这个截图中,我们可以看到泄漏对象的稳定增长可能是什么样子。 即使在大收集结束后,使用的内存总量高于开始时。 节点计数也较高。 这些都是代码中某处泄露的DOM节点的迹象。
这是你将花费大部分时间看的视图。 Profiles允许您获取快照并比较JavaScript代码的内存使用快照。 它还允许您记录分配的时间。 在每个结果视图中,不同类型的列表都可用,但是对于我们的任务最相关的是summary(概要)列表和comparison(对照)列表。
summary(概要)列表为我们概述了分配的不同类型的对象及其聚合大小:浅大小(特定类型的所有对象的总和)和保留大小(浅大小加上由于此对象保留的其他对象的大小 )。 它还给了我们一个对象相对于它的GC根(距离)有多远的概念。
comparison(对照)给了我们相同的信息,但允许我们比较不同的快照。 这对于查找泄漏是非常有用的。
7、示例:使用Chrome查找泄漏
基本上有两种类型的泄漏:1、泄漏引起内存使用的周期性增加。2、一次发生的泄漏,并且不会进一步增加内存。
由于明显的原因,当它们是周期性的时更容易发现泄漏。这些也是最麻烦的:如果内存在时间上增加,这种类型的泄漏将最终导致浏览器变慢或停止脚本的执行。不是周期性的泄漏可以很容易地发现。这通常会被忽视。在某种程度上,发生一次的小泄漏可以被认为是优化问题。然而,周期性的泄漏是错误并且必须解决的。
对于我们的示例,我们将使用Chrome的文档中的一个示例。 完整代码粘贴如下:
var x = [];
function createSomeNodes() {
var div,
i = 100,
frag = document.createDocumentFragment();
for (;i > 0; i--) {
div = document.createElement("div");
div.appendChild(document.createTextNode(i + " - "+ new Date().toTimeString()));
frag.appendChild(div);
}
document.getElementById("nodes").appendChild(frag);
}
function grow() {
x.push(new Array(1000000).join('x'));
createSomeNodes();
setTimeout(grow,1000);
}
当调用grow时,它将开始创建div节点并将它们附加到DOM。它还将分配一个大数组,并将其附加到全局变量引用的数组。这将导致使用上述工具可以找到的内存的稳定增加。
了解内存是否周期性增加
Timeline非常有用。 在Chrome中打开示例,打开开发工具,转到Timeline,选择Memory,然后点击录制按钮。 然后转到页面并单击按钮开始泄漏内存。 一段时间后停止录制,看看结果:
此示例将继续每秒泄漏内存。停止录制后,在grow函数中设置断点,以停止脚本强制Chrome关闭页面。在这个图像有两个大的迹象,表明我们正在记录泄漏。节点(绿线)和JS堆(蓝线)的图。节点正在稳步增加,从不减少。这是一个大的警告标志。
JS堆也显示内存使用的稳定增长。这是很难看到由于垃圾回收器的影响。您可以看到初始内存增长的模式,随后是大幅下降,随后是增加,然后是尖峰,继续记忆的另一下降。 在这种情况下的关键在于事实,在每次内存使用后,堆的大小保持大于上一次下降。 换句话说,虽然垃圾收集器正在成功地收集大量的存储器,但是它还是周期性地泄漏了。
现在确定有泄漏。 让我们找到它。
1、获取两个快照 要查找泄漏,我们现在将转到Chrome的开发工具的profiles部分。要将内存使用限制在可管理的级别,请在执行此步骤之前重新加载页面。我们将使用Take Heap Snapshot函数。 重新加载页面,并在完成加载后立即获取堆快照。 我们将使用此快照作为我们的基线。之后,再次点击最左边的Profiles按钮,等待几秒钟,并采取第二个快照。捕获快照后,建议在脚本中设置断点,以防止泄漏使用更多内存。
有两种方法可以查看两个快照之间的分配。 选择summary(摘要),右侧选择 Objects allocated between Snapshot 1 and Snapshot 2,或者筛选菜单选择 Comparison。在这两种情况下,我们将看到在两个快照之间分配的对象的列表。 在这种情况下,很容易找到泄漏:他们很大。看看 (string) 的 Size Delta Constructor,8MB,58个新对象。 这看起来很可疑:新对象被分配,但是没有释放,占用了8MB。 如果我们打开 (string) Constructor的分配列表,我们将注意到在许多小的分配之间有一些大的分配。大者立即引起我们的注意。如果我们选择其中的任何一个,我们可以在下面的retainers部分得到一些有趣的东西。
我们看到我们选择的分配是数组的一部分。反过来,数组由全局窗口对象内的变量x引用。这给了我们从我们的大对象到其不可收回的根(窗口)的完整路径 我们发现我们的潜在泄漏和被引用的地方。 到现在为止还挺好。但我们的例子很容易:大分配,例如在这个例子中的分配不是常态。幸运的是,我们的例子也泄漏了DOM节点,它们更小。使用上面的快照很容易找到这些节点,但在更大的网站,会变得更麻烦。 最新版本的Chrome提供了一个最适合我们工作的附加工具:记录堆分配功能。
2、Record heap allocations查找泄漏 禁用之前设置的断点,让脚本继续运行,然后返回Chrome的开发工具的“个人档案”部分。现在点击Record Heap Allocations。当工具运行时,您会注意到在顶部的图中的蓝色尖峰。这些代表分配。每秒大的分配由我们的代码执行。让它运行几秒钟,然后停止它(不要忘记再次设置断点,以防止Chrome吃更多的内存)。
在此图像中,您可以看到此工具的杀手锏:选择一段时间线以查看在该时间段内执行的分配。我们将选择设置为尽可能接近一个大峰值。列表中只显示了三个构造函数:其中一个是与我们的大漏洞((string))相关的构造函数,下一个与DOM分配相关,最后一个是Text构造函数(叶子DOM节点的构造函数 包含文本)。
从列表中选择一个 HTMLDivElement constructor,然后选择Allocation stack。
我们现在知道分配该元素的位置(grow - > createSomeNodes)。如果我们密切注意图中的每个尖峰,我们将注意到 HTMLDivElement constructor被调用了许多次。如果我们回到我们的快照比较视图,我们将注意到这个constructor显示许多分配,但没有删除。 换句话说,它正在稳定地分配内存,而没有被GC回收。从而我们知道这些对象被分配的确切位置(createSomeNodes函数)。现在回到代码,研究它,并修复漏洞。
3、另一个有用的功能 在堆分配结果视图中,我们可以选择Allocation视图。
这个视图给了一个与它们相关的函数和内存分配的列表。我们可以立即看到grow和createSomeNodes。当选择grow时,看看相关的object constructor。 可以注意到(string),HTMLDivElement和Text泄露了。 这些工具的组合可以大大有助于发现内存泄漏。在生产站点中执行不同的分析运行(理想情况下使用非最小化或模糊代码)。看看你是否能找到比他们应该保留更多的泄漏或对象(提示:这些更难找到)。
要使用此功能,请转到Dev Tools - >设置并启用“记录堆分配堆栈跟踪”。 在拍摄之前必须这样做。
8、请深入阅读
Memory Management - Mozilla Developer Network
JScript Memory Leaks - Douglas Crockford (old, in relation to Internet Explorer 6 leaks)
JavaScript Memory Profiling - Chrome Developer Docs
Memory Diagnosis - Google Developers
An Interesting Kind of JavaScript Memory Leak - Meteor blog
Grokking V8 closures
9、总结
内存泄漏可以并且确实发生在垃圾回收语言,如JavaScript。这些可以被忽视一段时间,最终他们将肆虐你的网站。因此,内存分析工具对于查找内存泄漏至关重要。分析运行应该是开发周期的一部分,特别是对于中型或大型应用程序。开始这样做,为您的用户提供最好的体验。
参考原文:https://auth0.com/blog/four-types-of-leaks-in-your-javascript-code-and-how-to-get-rid-of-them/
你可能感兴趣的:(4种JavaScript内存泄漏浅析及如何用谷歌工具查内存泄露)
斤斤计较的婚姻到底有多难?
白心之岂必有为
很多人私聊我会问到在哪个人群当中斤斤计较的人最多?我都会回答他,一般婚姻出现问题的斤斤计较的人士会非常多,以我多年经验,在婚姻落的一塌糊涂的人当中,斤斤计较的人数占比在20~30%以上,也就是说10个婚姻出现问题的斤斤计较的人有2-3个有多不减。在婚姻出问题当中,有大量的心理不平衡的、尖酸刻薄的怨妇。在婚姻中仅斤斤计较有两种类型:第一种是物质上的,另一种是精神上的。在物质与精神上抠门已经严重的影响
QQ群采集助手,精准引流必备神器
2401_87347160
其他 经验分享
功能概述微信群查找与筛选工具是一款专为微信用户设计的辅助工具,它通过关键词搜索功能,帮助用户快速找到相关的微信群,并提供筛选是否需要验证的群组的功能。主要功能关键词搜索:用户可以输入关键词,工具将自动查找包含该关键词的微信群。筛选功能:工具提供筛选机制,用户可以选择是否只显示需要验证或不需要验证的群组。精准引流:通过上述功能,用户可以更精准地找到目标群组,进行有效的引流操作。3.设备需求该工具可以
机器学习与深度学习间关系与区别
ℒℴѵℯ心·动ꦿ໊ོ꫞
人工智能 学习 深度学习 python
一、机器学习概述定义机器学习(MachineLearning,ML)是一种通过数据驱动的方法,利用统计学和计算算法来训练模型,使计算机能够从数据中学习并自动进行预测或决策。机器学习通过分析大量数据样本,识别其中的模式和规律,从而对新的数据进行判断。其核心在于通过训练过程,让模型不断优化和提升其预测准确性。主要类型1.监督学习(SupervisedLearning)监督学习是指在训练数据集中包含输入
底层逆袭到底有多难,不甘平凡的你准备好了吗?让吴起给你说说
造命者说
底层逆袭到底有多难,不甘平凡的你准备好了吗?让吴起给你说说我叫吴起,生于公元前440年的战国初期,正是群雄并起、天下纷争不断的时候。后人说我是军事家、政治家、改革家,是兵家代表人物。评价我一生历仕鲁、魏、楚三国,通晓兵家、法家、儒家三家思想,在内政军事上都有极高的成就。周安王二十一年(公元前381年),因变法得罪守旧贵族,被人乱箭射死。我出生在卫国一个“家累万金”的富有家庭,从年轻时候起就不甘平凡
2020-01-25
晴岚85
郑海燕坚持分享590天2020.1.24在生活中只存在两个问题。一个问题是:你知道想要达成的目标是什么,但却不知道如何才能达成;另一个问题是:你不知道你的目标是什么。前一个是行动的问题,后一个是结果的问题。通过制定具体的下一步行动,可以解决不知道如何开始行动的问题。而通过去想象结果,对结果做预估,可以解决找不着目标的问题。对于所有吸引我们注意力,想要完成的任务,你可以先想象一下,预期的结果究竟是什
【iOS】MVC设计模式
Magnetic_h
ios mvc 设计模式 objective-c 学习 ui
MVC前言如何设计一个程序的结构,这是一门专门的学问,叫做"架构模式"(architecturalpattern),属于编程的方法论。MVC模式就是架构模式的一种。它是Apple官方推荐的App开发架构,也是一般开发者最先遇到、最经典的架构。MVC各层controller层Controller/ViewController/VC(控制器)负责协调Model和View,处理大部分逻辑它将数据从Mod
OC语言多界面传值五大方式
Magnetic_h
ios ui 学习 objective-c 开发语言
前言在完成暑假仿写项目时,遇到了许多需要用到多界面传值的地方,这篇博客来总结一下比较常用的五种多界面传值的方式。属性传值属性传值一般用前一个界面向后一个界面传值,简单地说就是通过访问后一个视图控制器的属性来为它赋值,通过这个属性来做到从前一个界面向后一个界面传值。首先在后一个界面中定义属性@interfaceBViewController:UIViewController@propertyNSSt
UI学习——cell的复用和自定义cell
Magnetic_h
ui 学习
目录cell的复用手动(非注册)自动(注册)自定义cellcell的复用在iOS开发中,单元格复用是一种提高表格(UITableView)和集合视图(UICollectionView)滚动性能的技术。当一个UITableViewCell或UICollectionViewCell首次需要显示时,如果没有可复用的单元格,则视图会创建一个新的单元格。一旦这个单元格滚动出屏幕,它就不会被销毁。相反,它被添
谢谢你们,爱你们!
鹿游儿
昨天家人去泡温泉,二个孩子也带着去,出发前一晚,匆匆下班,赶回家和孩子一起收拾。饭后,我拿出笔和本子(上次去澳门时做手帐的本子)写下了1\2\3\4\5\6\7\8\9,让后让小壹去思考,带什么出发去旅游呢?她在对应的数字旁边画上了,泳衣、泳圈、肖恩、内衣内裤、tapuy、拖鞋……画完后,就让她自己对着这个本子,将要带的,一一带上,没想到这次带的书还是这本《便便工厂》(晚上姑婆发照片过来,妹妹累得
理解Gunicorn:Python WSGI服务器的基石
范范0825
ipython linux 运维
理解Gunicorn:PythonWSGI服务器的基石介绍Gunicorn,全称GreenUnicorn,是一个为PythonWSGI(WebServerGatewayInterface)应用设计的高效、轻量级HTTP服务器。作为PythonWeb应用部署的常用工具,Gunicorn以其高性能和易用性著称。本文将介绍Gunicorn的基本概念、安装和配置,帮助初学者快速上手。1.什么是Gunico
学点心理知识,呵护孩子健康
静候花开_7090
昨天听了华中师范大学教育管理学系副教授张玲老师的《哪里才是学生心理健康的最后庇护所,超越教育与技术的思考》的讲座。今天又重新学习了一遍,收获匪浅。张玲博士也注意到了当今社会上的孩子由于心理问题导致的自残、自杀及伤害他人等恶性事件。她向我们普及了一个重要的命题,她说心理健康的一些基本命题,我们与我们通常的一些教育命题是不同的,她还举了几个例子,让我们明白我们原来以为的健康并非心理学上的健康。比如如果
爬山后遗症
璃绛
爬山,攀登,一步一步走向制高点,是一种挑战。成功抵达是一种无法言语的快乐,在山顶吹吹风,看看风景,这是从未有过的体验。然而,爬山一时爽,下山腿打颤,颠簸的路,一路向下走,腿部力量不够,走起来抖到不行,停不下来了!第二天必定腿疼,浑身酸痛,坐立难安!
《投行人生》读书笔记
小蘑菇的树洞
《投行人生》----作者詹姆斯-A-朗德摩根斯坦利副主席40年的职业洞见-很短小精悍的篇幅,比较适合初入职场的新人。第一部分成功的职业生涯需要规划1.情商归为适应能力分享与协作同理心适应能力,更多的是自我意识,你有能力识别自己的情并分辨这些情绪如何影响你的思想和行为。2.对于初入职场的人的建议,细节,截止日期和数据很重要截止日期,一种有效的方法是请老板为你所有的任务进行优先级排序。和老板喝咖啡的好
Long类型前后端数据不一致
igotyback
前端
响应给前端的数据浏览器控制台中response中看到的Long类型的数据是正常的到前端数据不一致前后端数据类型不匹配是一个常见问题,尤其是当后端使用Java的Long类型(64位)与前端JavaScript的Number类型(最大安全整数为2^53-1,即16位)进行数据交互时,很容易出现精度丢失的问题。这是因为JavaScript中的Number类型无法安全地表示超过16位的整数。为了解决这个问
绘本讲师训练营【24期】8/21阅读原创《独生小孩》
1784e22615e0
24016-孟娟《独生小孩》图片发自App今天我想分享一个蛮特别的绘本,讲的是一个特殊的群体,我也是属于这个群体,80后的独生小孩。这是一本中国绘本,作者郭婧,也是一个80厚。全书一百多页,均为铅笔绘制,虽然为黑白色调,但并不显得沉闷。全书没有文字,犹如“默片”,但并不影响读者对该作品的理解,反而显得神秘,梦幻,給读者留下想象的空间。作者在前蝴蝶页这样写到:“我更希望父母和孩子一起分享这本书,使他
店群合一模式下的社区团购新发展——结合链动 2+1 模式、AI 智能名片与 S2B2C 商城小程序源码
说私域
人工智能 小程序
摘要:本文探讨了店群合一的社区团购平台在当今商业环境中的重要性和优势。通过分析店群合一模式如何将互联网社群与线下终端紧密结合,阐述了链动2+1模式、AI智能名片和S2B2C商城小程序源码在这一模式中的应用价值。这些创新元素的结合为社区团购带来了新的机遇,提升了用户信任感、拓展了营销渠道,并实现了线上线下的完美融合。一、引言随着互联网技术的不断发展,社区团购作为一种新兴的商业模式,在满足消费者日常需
我校举行新老教师师徒结对仪式暨名师专业工作室工作交流活动
李蕾1229
为促进我校教师专业发展,发挥骨干教师的引领带头作用,11月6日下午,我校举行新老教师师徒结对仪式暨名师专业工作室工作交流活动。图片发自App会议由教师发展处李蕾主任主持,首先,由范校长宣读新老教师结对名单及双方承担职责。随后,两位新调入教师陈玉萍、莫正杰分别和他们的师傅鲍元美、刘召彬老师签订了师徒结对协议书。图片发自App图片发自App师徒拥抱、握手。有了师傅就有了目标有了方向,相信两位新教师在师
向内而求
陈陈_19b4
10月27日,阴。阅读书目:《次第花开》。作者:希阿荣博堪布,是当今藏传佛家宁玛派最伟大的上师法王,如意宝晋美彭措仁波切颇具影响力的弟子之一。多年以来,赴海内外各地弘扬佛法,以正式授课、现场开示、发表文章等多种方法指导佛学弟子修行佛法。代表作《寂静之道》、《生命这出戏》、《透过佛法看世界》自出版以来一直是佛教类书籍中的畅销书。图片发自App金句:1.佛陀说,一切痛苦的根源在于我们长期以来对自身及外
ArcGIS栅格计算器常见公式(赋值、0和空值的转换、补充栅格空值)
研学随笔
arcgis 经验分享
我们在使用ArcGIS时通常经常用到栅格计算器,今天主要给大家介绍我日常中经常用到的几个公式,供大家参考学习。将特定值(-9999)赋值为0,例如-9999.Con("raster"==-9999,0,"raster")2.给空值赋予特定的值(如0)Con(IsNull("raster"),0,"raster")3.将特定的栅格值(如1)赋值为空值,其他保留原值SetNull("raster"==
高级编程--XML+socket练习题
masa010
java 开发语言
1.北京华北2114.8万人上海华东2,500万人广州华南1292.68万人成都华西1417万人(1)使用dom4j将信息存入xml中(2)读取信息,并打印控制台(3)添加一个city节点与子节点(4)使用socketTCP协议编写服务端与客户端,客户端输入城市ID,服务器响应相应城市信息(5)使用socketTCP协议编写服务端与客户端,客户端要求用户输入city对象,服务端接收并使用dom4j
本周第二次约练
2cfbdfe28a51
中原焦点团队中24初26刘霞2021.12.3约练161次,分享第368天当事人虽然是带着问题来的,但是咨询过程中发现,她是经过自己不断地调整和努力才走到现在的,看到当事人的不容易,找到例外,发现资源,力量感也就随之而来。增强画面感,或者说重温,会给当事人带来更深刻的感受。
今日联对0306
诗图佳得
自对联:烟销皓月临江浒,水漫金山荡塔裙。一一肖士平2020.3.6.1、试对肖老师联:烟销皓月临江浒,夜笼寒沙梦晚舟。耀哥求正2、试对萧老师联:烟销浩月临江浒,雾散乾坤解汉城。秀霞习作请各位老师校正3、自对联:烟销皓月临江浒,水漫金山荡塔裙。一一肖士平2020.3.6.4、试对肖老师垫场联:烟销皓月临江浒,雾锁寒林缈葉丛。小智求正[抱拳]5、试对肖老师联:烟销皓月临江浒;风卷乱云入峰巅。一一五品6
2022-07-08
保利学府里李楚怡1307022
——保利碧桂园学府里——童梦奇趣【科学实验室】「7.9-7.10」✏玩出大智慧约99-144㎡二期全新升级力作
2022-04-18
Apbenz
语重心长的和我说,不要老是说不行,人至而立之年危机四伏,内在的,外在的,感觉就是心力憔悴,让人无所适从。面对职场的无情,突然好羡慕干体力劳动的外卖小哥。难道命运是想让我去送外卖了吗?干体力活才能让我活下去?fastadmin打卡成功,淘宝金币任务完成。ㅏㅓㅗㅜㅡㅣㅐㅔㅑㅕㅛㅠㅢㅒㅖY行。야자여자요리우유의사얘기예
每日一题——第八十二题
互联网打工人no1
C语言程序设计每日一练 c语言
题目:将一个控制台输入的字符串中的所有元音字母复制到另一字符串中#include#include#include#include#defineMAX_INPUT1024boolisVowel(charp);intmain(){charinput[MAX_INPUT];charoutput[MAX_INPUT];printf("请输入一串字符串:\n");fgets(input,sizeof(inp
每日一题——第八十三题
互联网打工人no1
C语言程序设计每日一练 c语言
题目:将输入的整形数字输出,输出1990,输出"1990"#include#defineMAX_INPUT1024intmain(){intarrr_num[MAX_INPUT];intnum,i=0;printf("请输入一个数字:");scanf_s("%d",&num);while(num!=0){arrr_num[i++]=num%10;num/=10;}printf("\"");for(
Python中os.environ基本介绍及使用方法
鹤冲天Pro
# Python python 服务器 开发语言
文章目录python中os.environos.environ简介os.environ进行环境变量的增删改查python中os.environ的使用详解1.简介2.key字段详解2.1常见key字段3.os.environ.get()用法4.环境变量的增删改查和判断是否存在4.1新增环境变量4.2更新环境变量4.3获取环境变量4.4删除环境变量4.5判断环境变量是否存在python中os.envi
水泥质量纠纷案代理词
徐宝峰律师
贵州领航建设有限公司诉贵州纳雍隆庆乌江水泥有限公司产品质量纠纷案代理词尊敬的审判长、审判员:贵州千里律师事务所接受被告贵州纳雍隆庆乌江水泥有限公司的委托,指派我担任其诉讼代理人,参加本案的诉讼活动。下面,我结合本案事实和相关法律规定发表如下代理意见,供合议庭评议案件时参考:原告应当举证证明其遭受的损失与被告生产的水泥质量的因果关系。首先水泥是一种粉状水硬性无机胶凝材料。加水搅拌后成浆体,能在空气中
2019-12-22-22:30
涓涓1016
今天是冬至,写下我的日更,是因为这两天的学习真的是能量的满满,让我看到了自己,未来另外一种可能性,也让我看到了这两年这几年的过程中我所接受那些痛苦的来源。一切的根源和痛苦都来自于人生,家庭,而你的原生家庭,你的爸爸和妈妈,是因为你这个灵魂在那一刻选择他们作为你的爸爸和妈妈来的,所以你得接受他,你得接纳他,他就是因为他的存在而给你的学习和成长带来这些痛苦,那其实是你必然要经历的这个过程,当你去接纳的
第四天旅游线路预览——从换乘中心到喀纳斯湖
陟彼高冈yu
基于Google earth studio 的旅游规划和预览 旅游
第四天:从贾登峪到喀纳斯风景区入口,晚上住宿贾登峪;换乘中心有4路车,喀纳斯①号车,去喀纳斯湖,路程时长约5分钟;将上面的的行程安排进行动态展示,具体步骤见”Googleearthstudio进行动态轨迹显示制作过程“、“Googleearthstudio入门教程”和“Googleearthstudio进阶教程“相关内容,得到行程如下所示:Day4-2-480p
Linux的Initrd机制
被触发
linux
Linux 的 initrd 技术是一个非常普遍使用的机制,linux2.6 内核的 initrd 的文件格式由原来的文件系统镜像文件转变成了 cpio 格式,变化不仅反映在文件格式上, linux 内核对这两种格式的 initrd 的处理有着截然的不同。本文首先介绍了什么是 initrd 技术,然后分别介绍了 Linux2.4 内核和 2.6 内核的 initrd 的处理流程。最后通过对 Lin
maven本地仓库路径修改
bitcarter
maven
默认maven本地仓库路径:C:\Users\Administrator\.m2
修改maven本地仓库路径方法:
1.打开E:\maven\apache-maven-2.2.1\conf\settings.xml
2.找到
 
XSD和XML中的命名空间
darrenzhu
xml xsd schema namespace 命名空间
http://www.360doc.com/content/12/0418/10/9437165_204585479.shtml
http://blog.csdn.net/wanghuan203/article/details/9203621
http://blog.csdn.net/wanghuan203/article/details/9204337
http://www.cn
Java 求素数运算
周凡杨
java 算法 素数
网络上对求素数之解数不胜数,我在此总结归纳一下,同时对一些编码,加以改进,效率有成倍热提高。
第一种:
原理: 6N(+-)1法 任何一个自然数,总可以表示成为如下的形式之一: 6N,6N+1,6N+2,6N+3,6N+4,6N+5 (N=0,1,2,…)
java 单例模式
g21121
java
想必单例模式大家都不会陌生,有如下两种方式来实现单例模式:
class Singleton {
private static Singleton instance=new Singleton();
private Singleton(){}
static Singleton getInstance() {
return instance;
}
Linux下Mysql源码安装
510888780
mysql
1.假设已经有mysql-5.6.23-linux-glibc2.5-x86_64.tar.gz
(1)创建mysql的安装目录及数据库存放目录
解压缩下载的源码包,目录结构,特殊指定的目录除外:
32位和64位操作系统
墙头上一根草
32位和64位操作系统
32位和64位操作系统是指:CPU一次处理数据的能力是32位还是64位。现在市场上的CPU一般都是64位的,但是这些CPU并不是真正意义上的64 位CPU,里面依然保留了大部分32位的技术,只是进行了部分64位的改进。32位和64位的区别还涉及了内存的寻址方面,32位系统的最大寻址空间是2 的32次方= 4294967296(bit)= 4(GB)左右,而64位系统的最大寻址空间的寻址空间则达到了
我的spring学习笔记10-轻量级_Spring框架
aijuans
Spring 3
一、问题提问:
→ 请简单介绍一下什么是轻量级?
轻量级(Leightweight)是相对于一些重量级的容器来说的,比如Spring的核心是一个轻量级的容器,Spring的核心包在文件容量上只有不到1M大小,使用Spring核心包所需要的资源也是很少的,您甚至可以在小型设备中使用Spring。
 
mongodb 环境搭建及简单CURD
antlove
Web Install curd NoSQL mongo
一 搭建mongodb环境
1. 在mongo官网下载mongodb
2. 在本地创建目录 "D:\Program Files\mongodb-win32-i386-2.6.4\data\db"
3. 运行mongodb服务 [mongod.exe --dbpath "D:\Program Files\mongodb-win32-i386-2.6.4\data\
数据字典和动态视图
百合不是茶
oracle 数据字典 动态视图 系统和对象权限
数据字典(data dictionary)是 Oracle 数据库的一个重要组成部分,这是一组用于记录数据库信息的只读(read-only)表。随着数据库的启动而启动,数据库关闭时数据字典也关闭 数据字典中包含
数据库中所有方案对象(schema object)的定义(包括表,视图,索引,簇,同义词,序列,过程,函数,包,触发器等等)
数据库为一
多线程编程一般规则
bijian1013
java thread 多线程 java多线程
如果两个工两个以上的线程都修改一个对象,那么把执行修改的方法定义为被同步的,如果对象更新影响到只读方法,那么只读方法也要定义成同步的。
不要滥用同步。如果在一个对象内的不同的方法访问的不是同一个数据,就不要将方法设置为synchronized的。
将文件或目录拷贝到另一个Linux系统的命令scp
bijian1013
linux unix scp
一.功能说明 scp就是security copy,用于将文件或者目录从一个Linux系统拷贝到另一个Linux系统下。scp传输数据用的是SSH协议,保证了数据传输的安全,其格式如下: scp 远程用户名@IP地址:文件的绝对路径
【持久化框架MyBatis3五】MyBatis3一对多关联查询
bit1129
Mybatis3
以教员和课程为例介绍一对多关联关系,在这里认为一个教员可以叫多门课程,而一门课程只有1个教员教,这种关系在实际中不太常见,通过教员和课程是多对多的关系。
示例数据:
地址表:
CREATE TABLE ADDRESSES
(
ADDR_ID INT(11) NOT NULL AUTO_INCREMENT,
STREET VAR
cookie状态判断引发的查找问题
bitcarter
form cgi
先说一下我们的业务背景:
1.前台将图片和文本通过form表单提交到后台,图片我们都做了base64的编码,并且前台图片进行了压缩
2.form中action是一个cgi服务
3.后台cgi服务同时供PC,H5,APP
4.后台cgi中调用公共的cookie状态判断方法(公共的,大家都用,几年了没有问题)
问题:(折腾两天。。。。)
1.PC端cgi服务正常调用,cookie判断没
通过Nginx,Tomcat访问日志(access log)记录请求耗时
ronin47
一、Nginx通过$upstream_response_time $request_time统计请求和后台服务响应时间
nginx.conf使用配置方式:
log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_r
java-67- n个骰子的点数。 把n个骰子扔在地上,所有骰子朝上一面的点数之和为S。输入n,打印出S的所有可能的值出现的概率。
bylijinnan
java
public class ProbabilityOfDice {
/**
* Q67 n个骰子的点数
* 把n个骰子扔在地上,所有骰子朝上一面的点数之和为S。输入n,打印出S的所有可能的值出现的概率。
* 在以下求解过程中,我们把骰子看作是有序的。
* 例如当n=2时,我们认为(1,2)和(2,1)是两种不同的情况
*/
private stati
看别人的博客,觉得心情很好
Cb123456
博客 心情
以为写博客,就是总结,就和日记一样吧,同时也在督促自己。今天看了好长时间博客:
职业规划:
http://www.iteye.com/blogs/subjects/zhiyeguihua
android学习:
1.http://byandby.i
[JWFD开源工作流]尝试用原生代码引擎实现循环反馈拓扑分析
comsci
工作流
我们已经不满足于仅仅跳跃一次,通过对引擎的升级,今天我测试了一下循环反馈模式,大概跑了200圈,引擎报一个溢出错误
在一个流程图的结束节点中嵌入一段方程,每次引擎运行到这个节点的时候,通过实时编译器GM模块,计算这个方程,计算结果与预设值进行比较,符合条件则跳跃到开始节点,继续新一轮拓扑分析,直到遇到
JS常用的事件及方法
cwqcwqmax9
js
事件 描述
onactivate 当对象设置为活动元素时触发。
onafterupdate 当成功更新数据源对象中的关联对象后在数据绑定对象上触发。
onbeforeactivate 对象要被设置为当前元素前立即触发。
onbeforecut 当选中区从文档中删除之前在源对象触发。
onbeforedeactivate 在 activeElement 从当前对象变为父文档其它对象之前立即
正则表达式验证日期格式
dashuaifu
正则表达式 IT其它 java其它
正则表达式验证日期格式
function isDate(d){
var v = d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i);
if(!v) {
this.focus();
return false;
}
}
<input value="2000-8-8" onblu
Yii CModel.rules() 方法 、validate预定义完整列表、以及说说验证
dcj3sjt126com
yii
public array rules () {return} array 要调用 validate() 时应用的有效性规则。 返回属性的有效性规则。声明验证规则,应重写此方法。 每个规则是数组具有以下结构:array('attribute list', 'validator name', 'on'=>'scenario name', ...validation
UITextAttributeTextColor = deprecated in iOS 7.0
dcj3sjt126com
ios
In this lesson we used the key "UITextAttributeTextColor" to change the color of the UINavigationBar appearance to white. This prompts a warning "first deprecated in iOS 7.0."
Ins
判断一个数是质数的几种方法
EmmaZhao
Math python
质数也叫素数,是只能被1和它本身整除的正整数,最小的质数是2,目前发现的最大的质数是p=2^57885161-1【注1】。
判断一个数是质数的最简单的方法如下:
def isPrime1(n):
for i in range(2, n):
if n % i == 0:
return False
return True
但是在上面的方法中有一些冗余的计算,所以
SpringSecurity工作原理小解读
坏我一锅粥
SpringSecurity
SecurityContextPersistenceFilter
ConcurrentSessionFilter
WebAsyncManagerIntegrationFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
Use
JS实现自适应宽度的Tag切换
ini
JavaScript html Web css html5
效果体验:http://hovertree.com/texiao/js/3.htm
该效果使用纯JavaScript代码,实现TAB页切换效果,TAB标签根据内容自适应宽度,点击TAB标签切换内容页。
HTML文件代码:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
Hbase Rest API : 数据查询
kane_xie
REST hbase
hbase(hadoop)是用java编写的,有些语言(例如python)能够对它提供良好的支持,但也有很多语言使用起来并不是那么方便,比如c#只能通过thrift访问。Rest就能很好的解决这个问题。Hbase的org.apache.hadoop.hbase.rest包提供了rest接口,它内嵌了jetty作为servlet容器。
启动命令:./bin/hbase rest s
JQuery实现鼠标拖动元素移动位置(源码+注释)
明子健
jquery js 源码 拖动 鼠标
欢迎讨论指正!
print.html代码:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv=Content-Type content="text/html;charset=utf-8">
<title>发票打印</title>
&l
Postgresql 连表更新字段语法 update
qifeifei
PostgreSQL
下面这段sql本来目的是想更新条件下的数据,可是这段sql却更新了整个表的数据。sql如下:
UPDATE tops_visa.visa_order
SET op_audit_abort_pass_date = now()
FROM
tops_visa.visa_order as t1
INNER JOIN tops_visa.visa_visitor as t2
ON t1.
将redis,memcache结合使用的方案?
tcrct
redis cache
公司架构上使用了阿里云的服务,由于阿里的kvstore收费相当高,打算自建,自建后就需要自己维护,所以就有了一个想法,针对kvstore(redis)及ocs(memcache)的特点,想自己开发一个cache层,将需要用到list,set,map等redis方法的继续使用redis来完成,将整条记录放在memcache下,即findbyid,save等时就memcache,其它就对应使用redi
开发中遇到的诡异的bug
wudixiaotie
bug
今天我们服务器组遇到个问题:
我们的服务是从Kafka里面取出数据,然后把offset存储到ssdb中,每个topic和partition都对应ssdb中不同的key,服务启动之后,每次kafka数据更新我们这边收到消息,然后存储之后就发现ssdb的值偶尔是-2,这就奇怪了,最开始我们是在代码中打印存储的日志,发现没什么问题,后来去查看ssdb的日志,才发现里面每次set的时候都会对同一个key