0%

最近看到一个视频:如何在六个月内掌握一门外语挺让我惊喜的,里面的内容跟以往我看到的一些教学习语言的内容有挺大不同,做个记录。

开始

两大误解

  1. Talent(需要天赋)
  2. Immersion per se(沉浸式语言环境)

特别是第二点再没看到这个视频之前我一直以为学习一门新语言最好的方式是去到说该语言的环境中,沉浸式体验才能快速学会,看过视频后最起码让我觉得这应该不是最好的方式,因为我回过头来一想,之前在重庆上学的时候因为学校就在重大旁边,所以认识了几个公派留学生,他们在中国留学2年,据我的了解,这些留学生没一人能说超过10句中文,尽管他们天天待在中文的环境。

5个原则

7个动作

背景

最近了解到公司在抓研发效能这块,所以也学习学习,了解下相关内容。

研发效能提升

msup分享:

指标定义

指标是养出来的,不是一蹴而就。

分析模型

通常单个指标是不能说明问题的,需要多个指标按照一个分析模型来。

基于场景

基于场景下的实践反向验证指标的有效性

GSM

考察尽量以团队来考核,不要以个人。
不要有奖励,否则最终肯定会变形。

https://mp.weixin.qq.com/s?__biz=MzU1MjAzNjE4NA==&mid=2247484603&idx=1&sn=cc6e8341e604bab54235f9691dc23046&chksm=fb89768cccfeff9a3d4ac30fcdda18137869e486da4dfb9e9dddf3224e5a5f21d6bf301d746b&mpshare=1&scene=1&srcid=0926DpH4CCppnllj3x6aUd34&sharer_sharetime=1664164535153&sharer_shareid=90feac59023ea9aa307820b1dbe10e7f&version=4.0.16.99169&platform=mac#rd

背景

最近刚深度参与了客户现场一个堆的OOM问题的排查,在这儿简单记录一下使用到的工具。

产品为刚发的第一版,功能还在迭代中。

这个现场,是实验局现场,产品运行了1个多月,突然有一天告诉我们程序在能用和不能用之间反复横跳。

开始

我个人先下个结论。

  1. 对于发布市场的产品版本发生OOM,肯定是由于存在某个外因进而触发了内因引起的。
  2. 对于堆的OOM,很可能不是单点问题,而是多点问题,只是在某个时刻由某个单点触发了而已。

问题:

  1. 为什么突然就OOM?而且一天内发生了多次?
  2. 为什么程序直接被系统级的干掉了,连最后的dump都来不及输出?
阅读全文 »

背景

由于最近在查一个OOM问题,所以借机读起了《深入理解Java虚拟机》第三版。简单做个记录。

垃圾收集算法

分代收集理论

大多数垃圾收集器的都应用的理论。

弱分代假说(年轻代):绝大多数朝生夕灭的对象。
强分代假说(老年代):熬过越多次垃圾收集就越难消亡。
跨代引用假说

Partial GC(部分收集):

  • Minor GC/Young GC(年轻代收集)
  • Major GC/Old GC(老年代收集)
  • Mixed GC(混合收集):JDK 11 ,只有G1有,针对年轻代和部分老年代。
    Full GC(整堆收集):整个堆和方法区
阅读全文 »

背景

现场排查OOM,对于GC的一些理解。

杂项记录

https://vladmihalcea.com/improve-statement-caching-efficiency-in-clause-parameter-padding/

http://technodibble.blogspot.com/2015/02/hibernate-in-clause-outofmemory.html

http://xmlandmore.blogspot.com/2014/10/jdk-8-is-tuning-maxnewsize-in-g1-gc.html

heap内存归还给操作系统:G1GC https://openjdk.org/jeps/346

https://www.youtube.com/watch?v=BTIcja5xcK0

https://www.youtube.com/watch?v=IB7oFVYTOJ0

https://gceasy.io/gc-recommendations/important-g1-gc-arguments.jsp
https://github.com/Snailclimb/JavaGuide/blob/83efb36fb56d197f2c4b471084b884c6a4f23e37/docs/books/java.md

https://www.douban.com/doulist/2545443/

https://www.baeldung.com/jvm-parameters
https://blog.csdn.net/myth_g/article/details/119855832
https://docs.oracle.com/en/java/javase/11/gctuning/introduction-garbage-collection-tuning.html#GUID-326EB4CF-8C8C-4267-8355-21AB04F0D304

https://programmer.ink/think/jvm-series-jvm-tuning-jps-jstat-jmap-jhat-jstack-jinfo.html

https://docs.oracle.com/javase/10/jrockit-hotspot/logging.htm#JRHMG121
https://confluence.atlassian.com/confkb/unrecognized-jvm-gc-options-when-using-java-11-1002472841.html

https://dzone.com/articles/understanding-garbage-collection-log

https://sematext.com/blog/java-garbage-collection-tuning/

https://sematext.com/blog/java-garbage-collection-tuning/

https://cloud.tencent.com/developer/article/1811734

https://docs.oracle.com/en/java/javase/11/tools/jstat.html#GUID-5F72A7F9-5D5A-4486-8201-E1D1BA8ACCB5

https://www.javatang.com/archives/2017/10/19/51301886.html

https://morioh.com/p/935f204ccc1a

https://dzone.com/articles/jvm-tuning-using-jcmd

https://sematext.com/blog/java-garbage-collection-logs/

MAT

dump文件分析用的MAT。

https://zhanglvmeng.gitbooks.io/mat-usage/content/kai-shi-shi-yong/yan-shen-yue-du/shi-yong-mat-de-10-ge-jian-yi.html

线程分析

https://geekflare.com/generate-analyze-thread-dumps/

https://blog.fastthread.io/2016/02/22/thread-dump-analysis-pattern-repetitive-strain-injury-rsi/

当应用程序出现性能瓶颈时,大部分线程将开始在有问题的瓶颈区域累积。这些线程将具有相同的堆栈跟踪。因此,每当大量线程表现出相同/重复的堆栈跟踪时,就应该调查这些堆栈跟踪。这可能表示性能问题。

以下是一些这样的场景:

  • 假设您的 SOR 或外部服务正在变慢,那么大量线程将开始等待其响应。在这种情况下,这些线程将显示相同的堆栈跟踪。
  • 假设一个线程获得了一个锁并且它从未释放,那么在同一执行路径中的其他几个线程将进入阻塞状态,显示相同的堆栈跟踪。
  • 如果循环(for 循环、while 循环、do..while 循环)条件未终止,则执行该循环的多个线程将显示相同的堆栈跟踪。
    当出现上述任何一种情况时,应用程序的性能和可用性都会受到质疑。

重点关注:Troubleshooting Tools、Monitoring Tools
https://docs.oracle.com/en/java/javase/11/tools/tools-and-command-reference.html

https://programmer.ink/think/jvm-series-jvm-tuning-jps-jstat-jmap-jhat-jstack-jinfo.html

https://www.hollischuang.com/archives/110

线程状态产生的原因

  • runnable:状态一般为RUNNABLE。

  • in Object.wait():等待区等待,状态为WAITING或TIMED_WAITING。

  • waiting for monitor entry:进入区等待,状态为BLOCKED。

  • waiting on condition:等待区等待、被park。

  • sleeping:休眠的线程,调用了Thread.sleep()。

https://jakubstransky.com/2017/12/19/hotspot-jvm-internal-threads/

Tomcat线程模型

NIO: synchronous and non blocking. It can support large concurrency better than traditional bio. This mode is adopted by default after Tomcat 8.0.

NiO

https://developpaper.com/nio-optimization-principle-and-tomcat-thread-model/

Tomcat’s NiO model has more poller rolesAcceptor、PollerandHandler worker thread pool。 Are these three roles very familiar? If poller is replaced by reactor, is it the reactor model. Yes, Tomcat’s NiO model is based onMaster slave reactor modelIt’s just a change of name.

AcceptorThe: accepter thread is specifically responsible for establishing network connections(accept)。 After the new connection is created, instead of directly using the worker thread to process the request, the request is first sent to the poller buffer queue.
Poller: in poller, a selector object is maintained. After poller takes the connection from the buffer queue, it registers in the selector and blocks to wait for read and write ready(Read wait ready, send wait ready)。
Handlers: traverse the selector to find out the ready IO operations in the selector and hand them over to the worker thread for processing(Read memory read, decode, process, encode, send memory write)。

https://www.cnblogs.com/grey-wolf/p/13740845.html

调优
https://tomcat.apache.org/tomcat-9.0-doc/config/http.html
https://www.datadoghq.com/blog/tomcat-architecture-and-performance/

断断续续的在看一本书《代码整洁之道》

记录一下我认为实用的点。

有意义的命名

  • 有意义的名称。
  • 好搜索的名称,比如常量的命名。
  • 可读出来的名称。

可能会说这玩意还用说吗?这是基础的基础,一般情况下的命名我自认为做的挺好,但是看书之后我才发现我一个小毛病,就是习惯于把较长的命名给死命缩短(通常就是改变单词的缩写),感觉不缩短就难受。这样下来就有个问题。下一次再看代码的时候有时候会卡壳,忘了这个缩写是表示啥意思了。我这就是犯了上面的第三点“名称不可读”。

所以命名的前提是首先要能让人看懂,别整虚头巴脑的,一定要描述完整,当然有时候你发现你的命名需要装下好几个单词,得反过来再看看,是不是代码结构存在问题。

函数

一个函数只做一件事,每个函数一个抽象层级(向下规则)。
函数要么做什么事,要么回答什么事,二则不可兼得。

异常

  • 抽离try/catch代码块
  • 使用异常替代错误码

参数

  • 参数能少则少,至多三个,实在超出了三个用对象。
  • 尽量不使用标识参数。比如Boolean isXXX。加了标识参数通常就代表函数最少也做了两件事,是方法变得复杂了起来。
  • 应避免使用输出参数,通常情况下直接修改对象就行,不用再返回。