第七周作业

用户头像
田振宇
关注
发布于: 2020 年 07 月 18 日

作业一:

以下两题,至少选做一题

1、性能压测的时候,随着并发压力的增加,系统响应时间和吞吐量如何变化,为什么?

刚开始随着并发数增加,响应时间基本不变或者缓慢增加,吞吐量基本线性提升。

到一定阶段之后,并发数继续增加,响应时间逐渐变长,吞吐量提升速度减慢。

到一个临界点之后,继续增加并发数,响应时间继续变长,吞吐量开始下降



2、用你熟悉的编程语言写一个 web 性能压测工具,输入参数:URL,请求总次数,并发数。输出参数:平均响应时间,95% 响应时间。用这个测试工具以 10 并发、100 次请求压测 www.baidu.com。

import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class PerformanceSummary {
/**
* 平均响应时间
*/
private Double avgRT;
/**
* 95%响应时间
*/
private long percent95RT;
}



import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
public class PerformanceLoadTest {
public static void main(String[] args) {
PerformanceSummary performanceSummary = performanceTest("http://wwww.baidu.com", 100, 10);
System.out.println("平均响应时间:"+performanceSummary.getAvgRT() + "ms,95%响应时间:"+performanceSummary.getPercent95RT()+"ms");
}
public static PerformanceSummary performanceTest(String url, int totalNum, int concurrency) {
CountDownLatch countDownLatch = new CountDownLatch(concurrency);
AtomicInteger atomicInteger = new AtomicInteger(totalNum);
List<Long> requestList = Collections.synchronizedList(new ArrayList<>(totalNum));
for (int i = 0; i < concurrency; i++) {
new Thread(() -> {
while (true) {
if(atomicInteger.decrementAndGet() >= 0){
requestList.add(httpRequest(url));
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
break;
}
}
countDownLatch.countDown();
}).start();
}
try {
countDownLatch.await();
PerformanceSummary summary = new PerformanceSummary();
summary.setAvgRT(requestList.stream().mapToLong(Long::longValue).sum() * 1.0 / totalNum);
requestList.sort(Comparator.comparing(Long::longValue));
summary.setPercent95RT(requestList.get((int) (totalNum*0.95-1)));
return summary;
} catch (InterruptedException e) {
e.printStackTrace();
return null;
}
}
public static long httpRequest(String url) {
long t1 = System.currentTimeMillis();
String result = get(url);
long t2 = System.currentTimeMillis();
return t2 - t1;
}
private static String get(String url) {
HttpGet httpGet = new HttpGet(url);
try(CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse httpResponse = httpClient.execute(httpGet);){
HttpEntity entity = httpResponse.getEntity();
String result = EntityUtils.toString(entity);
return result;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}



输出结果:

平均响应时间:435.42ms, 95%响应时间:3103ms

作业二:

根据当周学习情况,完成一篇学习总结

性能测试指标:响应时间、并发数、吞吐量、性能技术器

性能测试方法:性能测试、负载测试、压力测试、稳定性测试



性能优化的一般方法:先根据性能测试获得性能指标,然后分析性能指标,发现性能与资源瓶颈点。再进行架构与代码分析,寻找性能与资源瓶颈点所在,进而进行架构与代码优化。最后再次进行性能测试,验证性能是否得到优化。



系统性能优化的分层思想:机房与骨干网络、服务器与硬件、操作系统、虚拟机、基础组件、软件架构、软件代码



软件架构优化:缓存、异步、集群

软件代码性能优化:

1、并发编程,多线程与锁

2、资源复用,线程池与对象池

3、异步编程,生产者与消费者

4、数据结构,数组、链表、hash表、树



进程、线程,多个线程共享进程的内存地址空间

线程栈:线程永远都是执行位于栈顶的函数

线程函数栈:存储局部变量



Java web应用多线程运行时视图:物理服务器->操作系统->JVM进程->Tomcat容器->应用程序,每个用户请求分配一个线程



线程安全:多个线程同时修改堆里的数据的时候,就会产生线程安全问题

临界区:多个线程访问共享资源的一段代码被称为临界区

锁会导致线程阻塞,阻塞导致线程既不能继续执行,也不能释放资源,高并发系统中可能导致资源耗尽,进而导致系统崩溃

避免阻塞引起崩溃的手段:限流、降级、异步IO



锁原语CAS(V,E,N),V表示要更新的变量、E表示预期值、N表示新值

系统原语,如果V值等于E值,则将V的值设为N;若V值和E值不同,什么都不做

Java通过CAS原语在对象头中修改Mark Word实现加锁

偏向锁、轻量级锁、重量锁,竞争加强,性能降低



多CPU情况下的锁:每个CPU有自己的缓存,通过缓存读取主存中的数据;通过缓存一致性协议或者总线锁机制保证一致性

总线锁:使用处理器的LOCK#信号,当一个处理器在内存总线上输出此信号的时候,其他处理器的请求将被阻塞,该处理器独占内存

缓存锁:通过锁定缓存行的方式,来保证一致性,性能较好



公平锁、非公平锁

可重入锁

独享锁、互斥锁、共享锁、读写锁

乐观锁、悲观锁

分段锁

自旋锁



用户头像

田振宇

关注

还未添加个人签名 2018.05.10 加入

还未添加个人简介

评论

发布
暂无评论
第七周作业