Mark

腾讯前端团队是如何做web性能监控的?

*爱你&永不变心* 提交于 2020-07-27 10:17:28
也许你有听过一个问题,你这款 web 应用性能怎么样呀?你会回答什么呢?是否会优于海量 web 应用市场呢?本文就来整理下如何进行 web 性能监控?包括我们需要监控的指标、监控的分类、performance 分析以及如何监控。 但是,如何进行 web 性能监控本身是一个很大的话题,文中只会侧重一部分进行研究,某些内容不是很全面。 前言:为什么需要监控? web 的性能一定程度上影响了用户留存率,Google DoubleClick 研究表明:如果一个移动端页面加载时长超过 3 秒,用户就会放弃而离开。BBC 发现网页加载时长每增加 1 秒,用户就会流失 10%。 我们希望通过监控来知道 web 应用性能的现状和趋势,找到 web 应用的瓶颈?某次发布后的性能情况怎么样?是否发布后对性能有影响?感知到业务出错的概率?业务的稳定性怎么样? 监控什么? 首先我们需要知道应该监控些什么呢?有哪些具体的指标? google 开发者提出了一种 RAIL 模型来衡量应用性能,即: Response 、 Animation 、 Idle 、 Load ,分别代表着 web 应用生命周期的四个不同方面。并指出最好的性能指标是:100ms 内响应用户输入;动画或者滚动需在 10ms 内产生下一帧;最大化空闲时间;页面加载时长不超过 5 秒。 我们可转化为三个方面来看:响应速度、页面稳定性

乐观锁以及乐观锁的实现

别来无恙 提交于 2020-07-27 09:41:46
乐观锁介绍: 乐观锁( Optimistic Locking ) 相对悲观锁而言,乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做。那么我们如何实现乐观锁呢,一般来说有以下2种方式: 1.使用数据版本(Version)记录机制实现,这是乐观锁最常用的一种实现方式。何谓数据版本?即为数据增加一个版本标识,一般是通过为数据库表增加一个数字类型的 “version” 字段来实现。当读取数据时,将version字段的值一同读出,数据每更新一次,对此version值加一。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的version值进行比对,如果数据库表当前版本号与第一次取出来的version值相等,则予以更新,否则认为是过期数据。用下面的一张图来说明: 如上图所示,如果更新操作顺序执行,则数据的版本(version)依次递增,不会产生冲突。但是如果发生有不同的业务操作对同一版本的数据进行修改,那么,先提交的操作(图中B)会把数据version更新为2,当A在B之后提交更新时发现数据的version已经被修改了,那么A的更新操作会失败。 2.乐观锁定的第二种实现方式和第一种差不多,同样是在需要乐观锁控制的table中增加一个字段,名称无所谓

小师妹学JVM之:JVM中的Safepoints

此生再无相见时 提交于 2020-07-27 08:49:11
简介 java程序员都听说过GC,大家也都知道GC的目的是扫描堆空间,然后将那些标记为删除的对象从堆空间释放,以提升可用的堆空间。今天我们会来探讨一下隐藏在GC背后的一个小秘密Safepoints。 GC的垃圾回收器 小师妹:F师兄,GC的垃圾回收器的种类为什么会有这么多呀?使用起来不是很麻烦。并且我听说CMS在JDK9zhong已经被废弃了。 小师妹,这么多垃圾回收器实际是在JVM的发展过程中建立起来的,在之前的文章中,我们讲到了目前的GC回收器有这样几种。 基于分代技术的回收器 Concurrent mark sweep (CMS) ,CMS是mark and swap的升级版本,它使用多个线程来对heap区域进行扫描,从而提升效率。 由于CMS的参数复杂性和性能问题,CMS已经在JDK9中被废弃了。 Serial garbage collection,使用单一的线程来进行垃圾回收操作,其好处就是不需要和其他的线程进行交互。如果你是单核的CPU,那么最好就是选择Serial garbage collection,因为你不能充分利用多核的好处。同样的它也常常用在比较小型的项目中。 Parallel garbage collection,如果你是多核处理器,那么Parallel GC可能是你的选择。 Parallel GC是JDK8中的默认GC。而在JDK9之后, G1是默认的GC

Java并发编程(五):synchronized原理详解及锁优化

僤鯓⒐⒋嵵緔 提交于 2020-07-27 06:58:50
文章目录 1 引言 2 synchronized实现原理 2.1 监视器锁(monitor)机制 2.1.1 作用在方法上 2.1.2 作用在代码块 2.2 获取锁和释放锁的内存语义 3 synchronized的锁优化 3.1 JVM中对象的内存区域 3.2 偏向锁 3.2.1 偏向锁的获取 3.2.2 偏向锁的撤销 3.3 轻量级锁 3.3.1 加锁 3.3.2 解锁 3.4 各种锁的比较 3.5 小结 点点关注,不会迷路 1 引言 线程运行时拥有自己 私有的栈空间 ,会在自己的栈空间运行,如果多线程间没有共享的数据也就是说多线程间并没有协作完成一件事情,那么,多线程就不能发挥优势,不能带来巨大的价值。那么共享数据的线程安全问题怎样处理?很自然而然的想法就是每一个线程依次去读写这个共享变量,这样就不会有任何数据安全的问题,因为每个线程所操作的都是当前最新的版本数据。那么,在 Java关键字synchronized就具有使每个线程依次排队操作共享变量的功能 。很显然,这种同步机制效率很低,但synchronized是其他并发容器实现的基础,对它的理解大有裨益。 2 synchronized实现原理 在Java代码中,synchronized可使用在代码块和方法中,synchronized的使用场景如下: 如图,synchronized可以用在 方法 上也可以使用在 代码块 中

networkx+python构建图结构数据并可视化

荒凉一梦 提交于 2020-07-27 05:52:39
目前处理非欧数据最常见的方法还是构建 图 ,而networkx一个专门的构建图数据的工具。方便又好用。 先给链接: https://networkx.github.io/ 官方文档 : https://networkx.github.io/documentation/latest/ networkx的安装方法上面的官方文档已经很详细记录,阿盏就不赘述了。 官方文档里给了几个demo,虽然便利,但泛化性不强。我这边给一个泛化性强一些的demo: import networkx as nx import matplotlib.pyplot as plt g = nx.Graph() g.add_edge('1', '2') g.add_edge('2', '3') g.add_edge('1', '4') g.add_edge('2', '4') fig, ax = plt.subplots() nx.draw(g, ax=ax) plt.show() 咱们构建的图数据就是g,看得出来一共有['1', '2', '3', 4'']四个节点。可视化结果为: 就一张光秃秃的点棍图,可以把节点label加上,只需设置with_labels=True: import networkx as nx import matplotlib.pyplot as plt g = nx.Graph() g

MATLAB程序:用FCM分割脑图像

99封情书 提交于 2020-07-27 04:56:58
MATLAB程序:用FCM分割脑图像 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 脑图像基础知识请看: 脑图像 ;FCM算法介绍请看: 聚类——FCM ;数据来源: BrainWeb: Simulated Brain Database ,只选取脑图像中的0、1、2、3类,其余类别设为0。本文用到的数据: Simulated Brain Database 1. MATLAB程序 FCM_image_main.m function [accuracy,iter_FCM,run_time]=FCM_image_main(filename, num, K) %num:第几层,K:聚类数 %[accuracy,iter_FCM,run_time]=FCM_image_main('t1_icbm_normal_1mm_pn0_rf0.rawb', 100, 4) [data_load, label_load]=main(filename, num); %原图像 [m,n]=size(data_load); X=reshape(data_load,m*n,1); %(m*n)*1 real_label=reshape(label_load,m*n,1)+ones(m*n,1); Ground_truth(num, K); %标准分割结果

你不知道的java对象序列化的秘密

故事扮演 提交于 2020-07-27 03:48:18
简介 你知道序列化可以使用代理吗?你知道序列化的安全性吗?每个java程序员都听说过序列化,要存储对象需要序列化,要在网络上传输对象要序列化,看起来很简单的序列化其实里面还隐藏着很多小秘密,今天本文将会为大家一一揭秘。 更多精彩内容且看: 区块链从入门到放弃系列教程-涵盖密码学,超级账本,以太坊,Libra,比特币等持续更新 Spring Boot 2.X系列教程:七天从无到有掌握Spring Boot-持续更新 Spring 5.X系列教程:满足你对Spring5的一切想象-持续更新 java程序员从小工到专家成神之路(2020版)-持续更新中,附详细文章教程 更多内容请访问 www.flydean.com 什么是序列化 序列化就是将java对象按照一定的顺序组织起来,用于在网络上传输或者写入存储中。而反序列化就是从网络中或者存储中读取存储的对象,将其转换成为真正的java对象。 所以序列化的目的就是为了传输对象,对于一些复杂的对象,我们可以使用第三方的优秀框架,比如Thrift,Protocol Buffer等,使用起来非常的方便。 JDK本身也提供了序列化的功能。要让一个对象可序列化,则可以实现java.io.Serializable接口。 java.io.Serializable是从JDK1.1开始就有的接口,它实际上是一个marker interface,因为java

jvm入门及理解(六)——垃圾回收与算法

别说谁变了你拦得住时间么 提交于 2020-07-27 03:21:38
一、jvm垃圾回收要做的事情 哪些内存需要回收 什么时候回收 怎么回收 二、如何判断对象已经死亡,或者说确定为垃圾 引用计数法: 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器的值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。这也就是需要回收的对象,简单地说,即一个对象如果没有任何与之关联的引用,即他们的引用计数都为 0,则说明对象不太可能再被用到,那么这个对象就是可回收的对象。 引用计数法是对象记录自己被多少 程序 引用,引用计数为零的对象将被清除。 计数器表示的是有多少程序引用了这个对象(被引用数)。计数器是无符号的整数。 根搜索算法:     通过一系列成为GC roots的点作为起点,向下搜索,当一个对象到任何GC Roots时没有引用链相连,则说明对象已经死亡。     如果在GC roots和一个对象之间没有可达路径(引用链),则称该对象是不可达的。要注意的是,不可达对象不等价于可回收对象,不可达对象变为可回收对象至少要经过两次标记 过程。两次标记后仍然是可回收对象,则将面临回收。     jvm会将以下的对象定义为GC Roots: Java虚拟机栈中引用的对象:比如方法里面定义这种局部变量 User user= new User(); 方法区中的静态属性引用的对象:比如 private static User

99 道 Java 多线程面试题,看完我跪了!

醉酒当歌 提交于 2020-07-27 01:24:00
今天给大家更新的是一篇关于多线程面试的文章,是根据时下热门的面试内容给大家进行总结的,如有雷同,请多见谅。 本篇文章属于干货内容!请各位读者朋友一定要坚持读到最后,完整阅读本文后相信你对多线程会有不一样感悟,下次面试和面试官也能杠一杠相关内容了。 1.什么是进程? 进程是系统中正在运行的一个程序,程序一旦运行就是进程。 进程可以看成程序执行的一个实例。进程是系统资源分配的独立实体,每个进程都拥有独立的地址空间。一个进程无法访问另一个进程的变量和数据结构,如果想让一个进程访问另一个进程的资源,需要使用进程间通信,比如管道,文件,套接字等。 2.什么是线程? 是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。 3.线程的实现方式? 1.继承Thread类 2.实现Runnable接口 3.使用Callable和Future 4.Thread 类中的start() 和 run() 方法有什么区别? 1.start()方法来启动线程,真正实现了多线程运行。这时无需等待run方法体代码执行完毕,可以直接继续执行下面的代码;通过调用Thread类的start()方法来启动一个线程, 这时此线程是处于就绪状态, 并没有运行。然后通过此Thread类调用方法run(

Python数据结构与算法——排序算法

五迷三道 提交于 2020-07-25 11:08:44
冒泡排序 冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。 算法描述 比较相邻的元素。如果第一个比第二个大,就交换它们两个; 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数; 针对所有的元素重复以上的步骤,除了最后一个; 重复步骤1~3,直到排序完成。 动图演示 解法1: def bubble_sort(alist): for pass_num in range(len(alist)-1, 0, -1): for i in range(pass_num): if alist[i] > alist[i+1]: alist[i], alist[i+1] = alist[i+1], alist[i] return alist 解法2: def bubble_sort_recusion(alist): pass_num = len(alist) - 1 exchange = True while pass_num > 0 and exchange: exchange = False for i in range(pass_num): if