首页 » Latest Post

1.java性能调优面临的问题

  • 能运行大内存堆的机器越来越多。催生了大内存堆的垃圾回收器G1
  • 云计算又提升了单CPU和小内存的能力,这个时候又需要针对小内存和单CPU进行优化

2.java性能调优包含的领域

  • 调整tuning flags ----编译器和垃圾收集器等。
  • API的最佳实践

3.JVM tuning flags 调优参数

  • Boolean类型:-XX:+FlagName表示启用,-xx:-FlagName表示禁用。
  • key value类型:-XX:FlagName=Param,一般Param是任意值。
  • 使用-XX:+PrintFlagsFinal 打印当前环境下所有flag的默认值。
  • 这些基于环境自动优化的过程称为ergonomics(自动优化).自动优化的前提----JVM会把机器识别为Client类或者Server类。32位的windows不考虑CPU核数,直接判定为Client类。32位的+单核的话。也是判定为Client类,不考虑操作系统。其他都认为是Server类。

4.JVM调优的瓶颈---数据库。

  • 有时候JVM调优后负载可以上升,但是数据库是瓶颈,JVM性能好反而导致数据库性能进一步下降。这样会得出一个错误的结论:JVM性能越好,整体性能反而更糟。
  • 所以负载能力和响应时间有时候需要权衡。如CPU密集型,增加线程数,等待锁的时间增加,上下文切换增加,延时增加。

5.性能条有的常见手段。

  • 借助性能分析,来优化代码。重点关注性能分析中最耗时的操作。但是这个不意味着只看叶子方法(请把调用链路看成一棵树)
  • 使用奥卡姆剃刀原理()分析性能问题。新代码比机器配置更可能引起性能问题。机器配置比JVM或者操作系统的bug更容易引起性能问题。即----最可能的原因往往最容易解释。不要一上来就跳到不太可能的场景。
  • 为最常用的操作,编写简单的算法。

-------------------------------------性能测试的方法-----------------
1.原则1---测试真实的应用,应该在产品实际的使用环境中进行测试

  • 微基准测试microbenchmarks,微小代码单元的测试。但是要注意两个计时之间的代码是否被使用过,如下面的代码
public void doTest() {
// Main Loop
double l;
long then = System.currentTimeMillis();
11
www.it-ebooks.infofor (int i = 0; i < nLoops; i++) {
l = fibImpl1(50);
}
long now = System.currentTimeMillis();
System.out.println("Elapsed time: " + (now - then));
}
...
private double fibImpl1(int n) {
if (n < 0) throw new IllegalArgumentException("Must be > 0");
if (n == 0) return 0d;
if (n == 1) return 1d;
double d = fibImpl1(n - 2) + fibImpl(n - 1);
if (Double.isInfinite(d)) throw new ArithmeticException("Overflow");
return d;
}

由于斐波那契的结果没被使用,智能编译器会优化成如下代码

long then = System.currentTimeMillis();
long now = System.currentTimeMillis();
System.out.println("Elapsed time: " + (now - then));

那么会得到错误的结果为几毫秒。
解决办法是---把l提升为实例变量,并且标记为volatile(强制每次写以后有一次的同步刷新---实际使用了cpu栅栏)
即确保读取被测试的结果,而不是i简单的写入
+不要包括无关的操作

  • 必须输入正确的参数,提前预知参数的正确性,而不是等运行出错了才知道.这个和我们常说的快速失败很像。
public double fibImplSlow(int n) {
if (n < 0) throw new IllegalArgumentException("Must be > 0");
if (n > 1476) throw new ArithmeticException("Must be < 1476");
return verySlowImpl(n);
}

  • 热点代码比较快,就是一段代码执行的越多,他的速度就越快

2.宏基准测试MacroBenchmarks

  • 必要性,JVM共用cpu的时候,GC效率不一样

3.Mesobenchmarks 介基准测试

1.kafka处理持续流动的数据

  • 不像关系数据库和kv数据库,把数据堪称持续变化continous evolving 和不断增长 ever growing的流。
  • kafka最初使用在社交网络的实时应用和数据流中。现在是 一个流平台Stream platform,可以发布和订阅数据。

2.kafka的比较

3.和普通的消息系统比,如ActiveMQ,RabbitMQ。尽管非常相像。

  • kafka可以自由伸缩,可以作为一个公司的消息中心平台。处理整个公司所有的数据流。而其他消息系统一系列是独立的brokers
  • kafka是一个存储系统,可以按你的要求时间存储数据。即可副本保存(高可用),可持久话。
  • 一般流queue系统只会传递数据,而kafka可以用很少的代码处理派生流/数据集。(derived treams 和datasets)

4.和存储系统相比,可以看成一个实时版本的hadoop

  • kafka可以存储和定期处理大量的数据文件
  • hadoop长处是数据分析,但是kafka具有实时性,可以用于核心业务的处理

5.和ETL相比,都擅长移动数据。但是kafka只是把数据拆解出来,塞给另一个系统,实际上是一个数据平台。
6.发布订阅消息模式

  • 发布者发布消息给broker,不关心谁是reciever
  • 消费者只消费他关心类型的消息

7.kafka通用数据类型

  • kafka存储的是字节数组(Arrays of bytes),对kafka来说,这些消息对kafka来说,没有特别的格式和含义
  • kafka消息可以有一个可选的Optional key,同样是字节数组,对kafka来说,没有特别的格式和含义。key可以用来生成hash来决定分区

8.kafka批次消息

  • kafka写入消息是按批次(一组消息)写的。这些消息属于同一个topic和分区partion。这样会节约网络开销,但是批次大也会导致单个消息的传输时间变长。所以要在latency和throughput之间权衡。
  • 通常会对批次进行压缩处理,提高传输效率,同时增加了计算处理。

9.kafka message schemas 消息模式

  • kafka 被建议用JSON和XML,但是这两者缺乏强类型约束和健壮性,而且不同版本兼容性也不好
  • kafka开发者大多采用 Apche Avro ( 最初开发为hadoop使用的序列化框架),作为kafka消息的schemas。Avro提供一种紧凑的序列化格式,Schemas和message payloads是分开的,Schemas变化,不需要重新序列化,向前和向后兼容
  • kafka需要这种一致性数据,不能发布端的数据格式变化,引起所有消费端升级。即数据格式的接偶

10.kafka的主题topics

  • topic是消息的分类方式,好比数据库中的table,topic会被分区,类似数据库中的分表,这也是kafka可以水平扩展的原因。
  • kafka 只能保证分区内的有序性,不能保证整个topic的有序性 (time Ordering)。
  • 一个分区类似一个commit log,只能追加的方式吸入。
  • 这中无界的commit log 一般被描述为流。如果忽略分区,一个topic会被视为一个流。即代表单个数据流 从生产者移动到消费者。
  • 流处理框架,有kafka Stream,Storm,及实时real time的操作数据。与之对比的是离线offline处理框架。如hadoop

11.kafka的client----生产者和消费者

  • 一般使用key做hash,来决定消息写到哪个分区。也可以自定义分区器partioner。这样根据业务把需要顺序性的业务数据分到同一个分区。
  • 消费者使用一种元数据(每个消息生成的时候,都会分配一个offset并保存到消息中,这个类似数据库中的主键,自增的整数)----offset来标记是否已经处理过。
  • 消费者把每个分区的读取的偏移量offset,保存到zookeeper,或者kafka本身。如果消费者关闭,那么读取的状态不会丢失。
  • 多个消费者会按组划分,但是会保证一个partion只会分给组中特定某一个消费者,以保证分区的顺序性。即一个分区不会分给同一个组内的多个消费者。

12.kafka broker,单个kafka的server被成为brokder

  • brokder接收生产者发送的消息,并且分配offset给这个消息

13.kafka消息保留retention

  • 可以设置保留时间。或者topic保留的容量大小,比如某个topic设置了最大保留数据1GB,一旦超过时间或者容量,消息就会被失效,或者删除。所以任何时刻,kafka的消息总量不会超过配置的大小。
  • 可以为某个topic单独设置过期时间和容量。
  • 还可以设置为log compacted ---紧凑型日志。kafka只会保留最后的一条消息。

14.kafka 多集群

  • kafka 集群 内置了副本机制,保证同一个集群可以互为副本
  • MirrorMaker 用来同步多个集群之间。MirrorMaker的本质包含了一个Producer和Consumer,Consumer从一个集群上读取消息,然后用Producer发送到另一个集群上
  • 多集群的原因有三1.隔离数据类型2.隔离安全级别3多数据中心容灾

15.kafka的使用场景

  • 活动记录----Activity Tracking
  • Messaging----用户通知等,如邮件,格式化消息(装饰)
  • 度量指标和日志记录
  • commit log ----事务的基本使用
  • Stream processing 流处理

16.kafka 安装环境

  • JAVA8,最好安装jdk
  • zookeeper---保存Broker和Topic的metadata,另外老版本中,还保存consumer的offset指针,可以使用srvr命令验证zookeeper安装是否正确
  • zookeeper的群组叫做Ensemble,由于zookeeper使用了一致性协议,所以最好群组内的节点使用奇数个。这样才能少数服从多数。如果有3个节点,允许1个节点失败,如果有5个节点,那么允许2个节点失败

使用openssh 作为server,然后一台计算机就可以使用ssh连接这个server

1.server端

sudo pacman -S openssh

2.修改配置

sudo vim /etc/ssh/sshd_config

3.去掉注释并修改如下内容

AllowUsers user1 user2
AllowGroups group1 group2
PermitRootLogin no
Port 22 #笔者只设置了这一项

4.设置开机启动

sudo systemctl start sshd.socket
sudo systemctl enable sshd.socket

5.使用命令查看当前server的ip

ip address

6.client 端连接

ssh user@ip

archlinux 或者manjaro 这个因为源有问题,解决方案是替换可用的源

[1] 修改/etc/pacman.conf ,添加中科大的源,并且放到前面的位置

#USTC
[archlinuxcn]
     
SigLevel = Never
Server = https://mirrors.ustc.edu.cn/archlinuxcn/$arch

[2] 更新源

pacman -Syy

[3]也有可能是你的镜像源没有更新,上面两部不用做,直接运行下面一行,然后重新安装即可。

sudo pacman -Sy

查找一个字符串中最长的字符串,这个思路就是从左向右找,用i向右找,j标识开始统计的字符。max记录最大长度.如:
Input: "pwwkew"
Output: 3
Explanation: The answer is "wke", with the length of 3.
Note that the answer must be a substring, "pwke" is a subsequence and not a substring.

[1]算法如下,复杂度O(n)


import java.util.HashMap;
import java.util.Map;
class Solution {

    public int lengthOfLongestSubstring(String s) {
        int max = 0;
        Map<Character,Integer> map= new HashMap<Character,Integer>();
        for(int i =0,j=0;i < s.length();i++){
            Character cha = s.charAt(i);
            if(map.containsKey(cha)){
                j = Math.max(j,map.get(cha)+1);
            }
            map.put(cha,i);
            max = Math.max(max,i-j + 1);
        }
        return max;
    }
}