测试飞腾ARM处理器FT2500的性能表现
ARM
ARM公司最早是由赫尔曼·豪泽(Hermann Hauser)和工程师Chris Curry在1978年创立(早期全称是 Acorn RISC Machine),后来改名为现在的ARM公司(Advanced RISC Machine)
ARM 芯片厂家
查看厂家
#cat /proc/cpuinfo |grep implementer
CPU implementer : 0x70
#cat /sys/devices/system/cpu/cpu0/regs/identification/midr_el1
0x00000000701f6633 // 70 表示厂家
vendor id对应厂家
Vendor Name | Vendor ID |
---|---|
ARM | 0x41 |
Broadcom | 0x42 |
Cavium | 0x43 |
DigitalEquipment | 0x44 |
HiSilicon | 0x48 |
Infineon | 0x49 |
Freescale | 0x4D |
NVIDIA | 0x4E |
APM | 0x50 |
Qualcomm | 0x51 |
Marvell | 0x56 |
Intel | 0x69 |
飞腾 | 0x70 |
飞腾ARM芯片介绍
飞腾处理器,又称银河飞腾处理器,是由中国人民解放军国防科学技术大学研制的一系列嵌入式数字信号处理器(DSP)和*处理器(CPU)芯片。[1]这个处理器系列的研发,是由国防科技大的邢座程教授[2]带领的团队负责研发。[3]其商业化推广则是由中国电子信息产业集团有限公司旗下的天津飞腾信息技术有限公司负责。
飞腾公司在早期,考察了SPARC、MIPS、ALPHA架构,这三种指令集架构都可以以极其低廉的价格(据说SPARC的授权价只有99美元,ALPHA不要钱)获得授权,飞腾选择了SPARC架构进行了CPU的研发。
2012年ARM正式推出了自己的第一个64位指令集处理器架构ARMv8,进入服务器等新的领域。此后飞腾放弃了SPARC,拿了ARMv8指令集架构的授权,全面转向了ARM阵营,芯片roadmap如下:
测试芯片详细信息
2020 年 7 月 23 日,飞腾发布新一代高可扩展多路服务器芯片腾云 S2500,采用 16nm 工艺, 主频 2.0~2.2Ghz,拥有 64 个 FTC663 内核,片内集成 64MB 三级 Cache,支持 8 个 DDR4-3200 存 储通道,功耗 150W。
基于 ARM 架构,兼具高可拓展性和低功耗,扩展支持 2 路到 8 路直连。与主流架构 X86 相比, ARM 架构具备低功耗、低发热和低成本的优势,ARM 单核的面积仅为 X86 核的 1/7,同样芯片尺寸下可以继承更多核心数,可以通过增加核心数提高性能,在性能快速提升下,也能保持较低的功耗,符合云计算场景下并行计算上高并发和高效率的要求,也能有效控制服务器的能耗和成本支出。腾云 S2500 增加了 4 个直连接口,总带宽 800Gbps,支持 2 路、4 路和 8 路直连,具备高可 拓展性,可以形成 128 核到 512 核的计算机系统,带动算力提升。
飞腾(FT2500), ARMv8架构,主频2.1G,服务器两路,每路64个物理core,没有超线程,总共16个numa,每个numa 8个core
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
#dmidecode -t processor
# dmidecode 3.0
Getting SMBIOS data from sysfs.
SMBIOS 3.2.0 present.
# SMBIOS implementations newer than version 3.0 are not
# fully supported by this version of dmidecode.
Handle 0x0004, DMI type 4, 48 bytes
Processor Information
Socket Designation: BGA3576
Type: Central Processor
Family: <OUT OF SPEC>
Manufacturer: PHYTIUM
ID: 00 00 00 00 70 1F 66 22
Version: FT2500
Voltage: 0.8 V
External Clock: 50 MHz
Max Speed: 2100 MHz
Current Speed: 2100 MHz
Status: Populated, Enabled
Upgrade: Other
L1 Cache Handle: 0x0005
L2 Cache Handle: 0x0007
L3 Cache Handle: 0x0008
Serial Number: 1234567
Asset Tag: No Asset Tag
Part Number: NULL
Core Count: 64
Core Enabled: 64
Thread Count: 64
Characteristics:
64-bit capable
Multi-Core
Hardware Thread
Execute Protection
Enhanced Virtualization
Power/Performance Control
#lscpu
Architecture: aarch64
Byte Order: Little Endian
CPU(s): 128
On-line CPU(s) list: 0-127
Thread(s) per core: 1
Core(s) per socket: 64
Socket(s): 2
NUMA node(s): 16
Model: 3
BogoMIPS: 100.00
L1d cache: 32K
L1i cache: 32K
L2 cache: 2048K
L3 cache: 65536K
NUMA node0 CPU(s): 0-7
NUMA node1 CPU(s): 8-15
NUMA node2 CPU(s): 16-23
NUMA node3 CPU(s): 24-31
NUMA node4 CPU(s): 32-39
NUMA node5 CPU(s): 40-47
NUMA node6 CPU(s): 48-55
NUMA node7 CPU(s): 56-63
NUMA node8 CPU(s): 64-71
NUMA node9 CPU(s): 72-79
NUMA node10 CPU(s): 80-87
NUMA node11 CPU(s): 88-95
NUMA node12 CPU(s): 96-103
NUMA node13 CPU(s): 104-111
NUMA node14 CPU(s): 112-119
NUMA node15 CPU(s): 120-127
Flags: fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
node distances:
node 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0: 10 20 40 30 20 30 50 40 100 100 100 100 100 100 100 100
1: 20 10 30 40 50 20 40 50 100 100 100 100 100 100 100 100
2: 40 30 10 20 40 50 20 30 100 100 100 100 100 100 100 100
3: 30 40 20 10 30 20 40 50 100 100 100 100 100 100 100 100
4: 20 50 40 30 10 50 30 20 100 100 100 100 100 100 100 100
5: 30 20 50 20 50 10 50 40 100 100 100 100 100 100 100 100
6: 50 40 20 40 30 50 10 30 100 100 100 100 100 100 100 100
7: 40 50 30 50 20 40 30 10 100 100 100 100 100 100 100 100
8: 100 100 100 100 100 100 100 100 10 20 40 30 20 30 50 40
9: 100 100 100 100 100 100 100 100 20 10 30 40 50 20 40 50
10: 100 100 100 100 100 100 100 100 40 30 10 20 40 50 20 30
11: 100 100 100 100 100 100 100 100 30 40 20 10 30 20 40 50
12: 100 100 100 100 100 100 100 100 20 50 40 30 10 50 30 20
13: 100 100 100 100 100 100 100 100 30 20 50 20 50 10 50 40
14: 100 100 100 100 100 100 100 100 50 40 20 40 30 50 10 30
15: 100 100 100 100 100 100 100 100 40 50 30 50 20 40 30 10
|
cpu详细信息:
飞腾芯片,按如下distance绑核基本没区别!展示出来的distance是假的一样
FT2500芯片集成的 64 个处理器核心,划分为 8 个 Panel,每个 Panel 中有两个 Cluster (每个 Cluster 包含 4 个处理器核心及共享的 2M 二级 cache)、两个本地目录控 制部件(DCU)、一个片上网络路由器节点(Cell)和一个紧密耦合的访存控制 器(MCU)。Panel 之间通过片上网络接口连接,一致性维护报文、数据报文、 调测试报文、中断报文等统一从同一套网络接口进行路由和通信
一个Panel的实现是FTC663版本,采用四发射乱序超标量流水线结构,兼容 ARMv8 指令集,支持 EL0~EL3 多个特权级。流水线分为取指、译码、分派、执 行和写回五个阶段,采用顺序取指、乱序执行、顺序提交的多发射执行机制,取 值宽度、译码宽度、分派宽度均是 4 条指令,共有 9 个执行部件(或者称为 9 条功能流水线),分别是 4 个整数部件、2 个浮点部件、1 个 load 部件、1 个 load/store 部件和 1 个系统管理指令执行部件。浮点流水线能够合并执行双路浮点 SIMD 指 令,实现每拍可以执行 4 条双精度浮点操作的峰值性能。
猜测FT2500 64core用的是一个Die, 但是core之间的连接是Ring Bus,而Ring Bus下core太多后延迟会快速增加,所以一个Die 内部做了8个小的Ring Bus,每个Ring Bus下8个core。
飞腾官方提供的测试结果
飞腾2500 和 鲲鹏9200 参数对比
FT2000与FT2500差异
下表是FT2000和FT2500产品规格对比表,和芯片的单核内部结构变化较少,多了L3,主频提高了,其他基本没有变化。
特征 | FT-2000+/64 | FT-2500 |
---|---|---|
指令 | 兼容 ARM V8 指令集 FTC662 内核 | 兼容 ARM V8 指令集FTC663 内核 |
Core数 | 64个 | 64个 |
频率 | 2.2GHZ/2.0GHZ/1.8GHZ | 2.0~2.3GHz |
体系架构 | NUMA | NUMA |
RAS | 无 | 支持 |
加解密 | 无 | ASE128、SHA1、SHA2-256、PMULL |
L1 Cache | 每个核独占32KB指令Cache与32KB数据Cache | 每个核独占32K指令Cache与32K数据Cache |
L2 Cache | 共32MB,每4个核共享2MB | 共32MB,每4个核共享2MB |
L3 Cache | 无 | 64MB |
LMU数量 | 8个 | 8个 |
支持最大容量 | 1TB | 1TB*socket数量 |
支持最大频率 | 3200MHZ | 支持3200MHZ |
外接设备 | 支持带 ECC 的 DDR4 DIMM,支持 RDIMM、UDIMM、SODIMM、 LR-DIMM,电压 1.2V | 支持带 ECC 的 DDR4 DIMM,支持 RDIMM、UDIMM、SODIMM、LR-DIMM,电压 1.2V |
镜像存储 | 无 | 每两个MCU互为备份 |
PCIe | PCIE3.02 个 x16 和 1 个 x1每个 x16 可拆分成 2 个 x8,支持翻转 | PCIE3.01 个 x16 和 1 个 x1x16 可拆分成 2 个 x8,支持翻转 |
SPI | 支持 4 个片选,单片最大支持容量为 512MB,电压 1.8V | 支持 4 个片选,单片最大支持容量为 512MB,电压 1.8V |
UART | 4个 UART,其中 1 个为 9 线全功能串口,3 个为 3 线调试串口 | 4个 UART,其中 1 个为 9 线全功能串口,3 个为 3 线调试串口 |
GPIO | 4 个 8 位 GPIO 接口,GPIOA[0:7],GPIOB[0:7],GPIOC[0:7], GPIOD[0:7] | 4 个 8 位 GPIO 接口,GPIOA[0:7],GPIOB[0:7],GPIOC[0:7], GPIOD[0:7] |
LPC | 1 个 LPC 接口,兼容 Intel Low Pin Count 协议, 电压 1.8V | 1 个 LPC 接口,兼容 Intel Low Pin Count 协议, 电压 1.8V |
I2C | 2 个 I2C master 控制器 | 2 个 I2C master /Slave控制器,2个slave控制器 |
直连 | 无 | 四个直连通路,每路X4个lane,每条lane速率为25Gbps,支持2路、4路、8路 |
飞腾ARM芯片性能测试数据
以下测试场景基本都是运行CPU和网络瓶颈的业务逻辑,绑核前IPC只有0.08
绑核后对性能提升非常明显:
点查场景:
如上是绑48-63号核
绑不同的核性能差异比较大,比如同样绑第一个socket最后16core和绑第二个socket最后16core,第二个socket的最后16core性能要好25-30%—这是因为网卡软中断,如果将软中断绑定到0-4号cpu后差异基本消失,因为网卡队列设置的是60,基本跑在前60core上,也就是第一个socket上。
点查场景绑核和不绑核性能能差1倍, 将table分表后,物理rt稳定了(截图中物理rt下降是因为压力小了–待证)
点查场景压测16个core的节点
一个节点16core,16个core绑定到14、15号NUMA上,然后压测
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
#perl numa-maps-summary.pl </proc/79694/numa_maps //16core
N0 : 1103 ( 0.00 GB)
N1 : 107368 ( 0.41 GB)
N10 : 144736 ( 0.55 GB)
N11 : 16919 ( 0.06 GB)
N12 : 551987 ( 2.11 GB)
N13 : 59499 ( 0.23 GB)
N14 : 5621573 ( 21.44 GB) //内存就近分配
N15 : 6200398 ( 23.65 GB)
N2 : 700 ( 0.00 GB)
N3 : 89 ( 0.00 GB)
N4 : 5784 ( 0.02 GB)
N5 : 77 ( 0.00 GB)
N6 : 426 ( 0.00 GB)
N7 : 472 ( 0.00 GB)
N8 : 107 ( 0.00 GB)
N9 : 6137 ( 0.02 GB)
active : 85 ( 0.00 GB)
anon : 12712675 ( 48.50 GB)
dirty : 12712679 ( 48.50 GB)
kernelpagesize_kB: 17444 ( 0.07 GB)
mapmax : 1598 ( 0.01 GB)
mapped : 4742 ( 0.02 GB)
#perf stat -e branch-misses,bus-cycles,cache-misses,cache-references,cpu-cycles,instructions,L1-dcache-load-misses,L1-dcache-loads,L1-dcache-store-misses,L1-dcache-stores,L1-icache-load-misses,L1-icache-loads,branch-load-misses,branch-loads,dTLB-load-misses,iTLB-load-misses -a -p 79694
^C
Performance counter stats for process id '79694':
1719788217 branch-misses (39.70%)
311069393237 bus-cycles (38.07%)
2021349865 cache-misses # 6.669 % of all cache refs (38.32%)
30308501243 cache-references (39.67%)
310980728138 cpu-cycles (46.46%)
67298903097 instructions # 0.22 insns per cycle (47.63%)
1983728595 L1-dcache-load-misses # 6.62% of all L1-dcache hits (48.76%)
29943167305 L1-dcache-loads (47.89%)
1957152091 L1-dcache-store-misses (46.14%)
29572767575 L1-dcache-stores (44.91%)
4223808613 L1-icache-load-misses (43.08%)
49122358099 L1-icache-loads (38.15%)
1724605628 branch-load-misses (37.63%)
15225535577 branch-loads (36.61%)
997458038 dTLB-load-misses (35.81%)
542426693 iTLB-load-misses (34.98%)
10.489297296 seconds time elapsed
[ 29s] threads: 160, tps: 0.00, reads/s: 15292.01, writes/s: 0.00, response time: 25.82ms (95%)
[ 30s] threads: 160, tps: 0.00, reads/s: 16399.99, writes/s: 0.00, response time: 23.58ms (95%)
[ 31s] threads: 160, tps: 0.00, reads/s: 17025.00, writes/s: 0.00, response time: 20.73ms (95%)
[ 32s] threads: 160, tps: 0.00, reads/s: 16991.01, writes/s: 0.00, response time: 22.83ms (95%)
[ 33s] threads: 160, tps: 0.00, reads/s: 18400.94, writes/s: 0.00, response time: 21.29ms (95%)
[ 34s] threads: 160, tps: 0.00, reads/s: 17760.05, writes/s: 0.00, response time: 20.69ms (95%)
[ 35s] threads: 160, tps: 0.00, reads/s: 17935.00, writes/s: 0.00, response time: 20.23ms (95%)
[ 36s] threads: 160, tps: 0.00, reads/s: 18296.98, writes/s: 0.00, response time: 20.10ms (95%)
[ 37s] threads: 160, tps: 0.00, reads/s: 18111.02, writes/s: 0.00, response time: 20.56ms (95%)
[ 38s] threads: 160, tps: 0.00, reads/s: 17782.99, writes/s: 0.00, response time: 20.54ms (95%)
[ 38s] threads: 160, tps: 0.00, reads/s: 21412.13, writes/s: 0.00, response time: 11.96ms (95%)
[ 40s] threads: 160, tps: 0.00, reads/s: 18027.85, writes/s: 0.00, response time: 20.18ms (95%)
[ 41s] threads: 160, tps: 0.00, reads/s: 17907.04, writes/s: 0.00, response time: 20.02ms (95%)
[ 42s] threads: 160, tps: 0.00, reads/s: 13860.96, writes/s: 0.00, response time: 23.58ms (95%)
[ 43s] threads: 160, tps: 0.00, reads/s: 18491.02, writes/s: 0.00, response time: 20.18ms (95%)
[ 44s] threads: 160, tps: 0.00, reads/s: 17673.02, writes/s: 0.00, response time: 20.85ms (95%)
[ 45s] threads: 160, tps: 0.00, reads/s: 18048.96, writes/s: 0.00, response time: 21.47ms (95%)
[ 46s] threads: 160, tps: 0.00, reads/s: 18130.03, writes/s: 0.00, response time: 22.13ms (95%)
|
点查场景压测8个core的节点
因为每个NUMA才8个core,所以测试一下8core的节点绑核前后性能对比。实际结果看起来和16core节点绑核性能提升差不多。
绑核前后对比:绑核后QPS翻倍,绑核后的服务rt从7.5降低到了2.2,rt下降非常明显,可以看出主要是绑核前跨numa访问慢。实际这个测试是先跑的不绑核,内存分布在所有NUMA上,没有重启再绑核就直接测试了,所以性能提升不明显,因为内存已经跨NUMA分配完毕了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
perl numa-maps-summary.pl </proc/33727/numa_maps //绑定8core后,在如下内存分配下QPS能到11000,但是抖动略大,应该是一个numa内存不够了
N0 : 551 ( 0.00 GB)
N1 : 1023418 ( 3.90 GB)
N10 : 52065 ( 0.20 GB)
N11 : 190737 ( 0.73 GB)
N12 : 516115 ( 1.97 GB)
N13 : 186556 ( 0.71 GB)
N14 : 1677489 ( 6.40 GB)
N15 : 324531 ( 1.24 GB)
N2 : 397 ( 0.00 GB)
N3 : 8 ( 0.00 GB)
N4 : 398 ( 0.00 GB)
N6 : 349 ( 0.00 GB)
N7 : 437 ( 0.00 GB)
N8 : 108508 ( 0.41 GB)
N9 : 69162 ( 0.26 GB)
active : 2296 ( 0.01 GB)
anon : 4144997 ( 15.81 GB)
dirty : 4145002 ( 15.81 GB)
kernelpagesize_kB: 7508 ( 0.03 GB)
mapmax : 1548 ( 0.01 GB)
mapped : 5724 ( 0.02 GB)
[ 349s] threads: 100, tps: 0.00, reads/s: 11088.99, writes/s: 0.00, response time: 20.18ms (95%)
[ 350s] threads: 100, tps: 0.00, reads/s: 8778.98, writes/s: 0.00, response time: 26.20ms (95%)
[ 351s] threads: 100, tps: 0.00, reads/s: 7995.01, writes/s: 0.00, response time: 31.79ms (95%)
[ 352s] threads: 100, tps: 0.00, reads/s: 9549.01, writes/s: 0.00, response time: 23.90ms (95%)
[ 353s] threads: 100, tps: 0.00, reads/s: 8757.99, writes/s: 0.00, response time: 24.60ms (95%)
[ 354s] threads: 100, tps: 0.00, reads/s: 10288.02, writes/s: 0.00, response time: 21.85ms (95%)
[ 355s] threads: 100, tps: 0.00, reads/s: 11003.97, writes/s: 0.00, response time: 18.90ms (95%)
[ 356s] threads: 100, tps: 0.00, reads/s: 11111.01, writes/s: 0.00, response time: 20.51ms (95%)
[ 357s] threads: 100, tps: 0.00, reads/s: 11426.00, writes/s: 0.00, response time: 17.98ms (95%)
[ 358s] threads: 100, tps: 0.00, reads/s: 11007.01, writes/s: 0.00, response time: 19.35ms (95%)
[ 359s] threads: 100, tps: 0.00, reads/s: 10425.00, writes/s: 0.00, response time: 20.92ms (95%)
[ 360s] threads: 100, tps: 0.00, reads/s: 10024.00, writes/s: 0.00, response time: 23.17ms (95%)
[ 361s] threads: 100, tps: 0.00, reads/s: 10100.98, writes/s: 0.00, response time: 22.94ms (95%)
[ 362s] threads: 100, tps: 0.00, reads/s: 8164.01, writes/s: 0.00, response time: 27.48ms (95%)
[ 363s] threads: 100, tps: 0.00, reads/s: 6593.00, writes/s: 0.00, response time: 37.10ms (95%)
[ 364s] threads: 100, tps: 0.00, reads/s: 7008.00, writes/s: 0.00, response time: 32.32ms (95%)
#调整这个实例到内存充足的NUMA7上 QPS峰值能到14000,稳定在11000-13000之间,RT明显更稳定了
perl numa-maps-summary.pl </proc/78245/numa_maps
N0 : 551 ( 0.00 GB)
N1 : 115 ( 0.00 GB)
N11 : 695 ( 0.00 GB)
N12 : 878 ( 0.00 GB)
N13 : 2019 ( 0.01 GB)
N14 : 25 ( 0.00 GB)
N15 : 60 ( 0.00 GB)
N2 : 394 ( 0.00 GB)
N3 : 8 ( 0.00 GB)
N4 : 197713 ( 0.75 GB)
N6 : 349 ( 0.00 GB)
N7 : 3957844 ( 15.10 GB)
N8 : 1 ( 0.00 GB)
active : 10 ( 0.00 GB)
anon : 4154693 ( 15.85 GB)
dirty : 4154698 ( 15.85 GB)
kernelpagesize_kB: 7452 ( 0.03 GB)
mapmax : 1567 ( 0.01 GB)
mapped : 5959 ( 0.02 GB)
[ 278s] threads: 100, tps: 0.00, reads/s: 13410.99, writes/s: 0.00, response time: 15.36ms (95%)
[ 279s] threads: 100, tps: 0.00, reads/s: 14049.99, writes/s: 0.00, response time: 15.54ms (95%)
[ 280s] threads: 100, tps: 0.00, reads/s: 13107.02, writes/s: 0.00, response time: 16.72ms (95%)
[ 281s] threads: 100, tps: 0.00, reads/s: 12431.99, writes/s: 0.00, response time: 17.79ms (95%)
[ 282s] threads: 100, tps: 0.00, reads/s: 13164.01, writes/s: 0.00, response time: 16.33ms (95%)
[ 283s] threads: 100, tps: 0.00, reads/s: 13455.01, writes/s: 0.00, response time: 16.19ms (95%)
[ 284s] threads: 100, tps: 0.00, reads/s: 12932.01, writes/s: 0.00, response time: 16.22ms (95%)
[ 285s] threads: 100, tps: 0.00, reads/s: 12790.99, writes/s: 0.00, response time: 17.00ms (95%)
[ 286s] threads: 100, tps: 0.00, reads/s: 12706.00, writes/s: 0.00, response time: 17.88ms (95%)
[ 287s] threads: 100, tps: 0.00, reads/s: 11886.00, writes/s: 0.00, response time: 19.43ms (95%)
[ 288s] threads: 100, tps: 0.00, reads/s: 12700.00, writes/s: 0.00, response time: 16.97ms (95%)
#perl numa-maps-summary.pl </proc/54723/numa_maps //54723绑定在NUMA6上
N0 : 551 ( 0.00 GB)
N1 : 115 ( 0.00 GB)
N11 : 682 ( 0.00 GB)
N12 : 856 ( 0.00 GB)
N13 : 2018 ( 0.01 GB)
N14 : 25 ( 0.00 GB)
N15 : 60 ( 0.00 GB)
N2 : 1270166 ( 4.85 GB) //不应该分配这里的内存,实际是因为N6内存被PageCache使用掉了
N3 : 8 ( 0.00 GB)
N4 : 398 ( 0.00 GB)
N6 : 3662400 ( 13.97 GB)
N7 : 460 ( 0.00 GB)
N8 : 1 ( 0.00 GB)
active : 9 ( 0.00 GB)
anon : 4931796 ( 18.81 GB)
dirty : 4931801 ( 18.81 GB)
kernelpagesize_kB: 7920 ( 0.03 GB)
mapmax : 1580 ( 0.01 GB)
mapped : 5944 ( 0.02 GB)
#cat /proc/meminfo | grep -i active
Active: 22352360 kB
Inactive: 275173756 kB
Active(anon): 16984 kB
Inactive(anon): 240344208 kB
Active(file): 22335376 kB
Inactive(file): 34829548 kB
#echo 3 > /proc/sys/vm/drop_caches
#cat /proc/meminfo | grep -i active
Active: 1865724 kB
Inactive: 242335632 kB
Active(anon): 7108 kB
Inactive(anon): 240199020 kB
Active(file): 1858616 kB //回收了大量PageCache内存
Inactive(file): 2136612 kB
perl numa-maps-summary.pl </proc/54723/numa_maps
N0 : 552 ( 0.00 GB)
N1 : 115 ( 0.00 GB)
N11 : 682 ( 0.00 GB)
N12 : 856 ( 0.00 GB)
N13 : 2018 ( 0.01 GB)
N14 : 25 ( 0.00 GB)
N15 : 60 ( 0.00 GB)
N2 : 1740 ( 0.01 GB)
N3 : 8 ( 0.00 GB)
N4 : 398 ( 0.00 GB)
N6 : 4972492 ( 18.97 GB)
N7 : 459 ( 0.00 GB)
N8 : 1 ( 0.00 GB)
active : 16 ( 0.00 GB)
anon : 4973486 ( 18.97 GB)
dirty : 4973491 ( 18.97 GB)
kernelpagesize_kB: 8456 ( 0.03 GB)
mapmax : 1564 ( 0.01 GB)
mapped : 5920 ( 0.02 GB)
|
绑核前的IPC:
绑核后的IPC:
如果是两个8core对一个16core在都最优绑核场景下从上面的数据来看能有40-50%的性能提升,并且RT抖动更小,这两个8core绑定在同一个Socket下,验证是否争抢,同时可以看到绑核后性能可以随着加节点线性增加
结论:不绑核一个FT2500的core点查只有500 QPS,绑核后能到1500QPS, 在Intel 8263下一个core能到6000以上(开日志、没开协程)
MySQL 数据库场景绑核
通过同一台物理上6个Tomcat节点,总共96个core,压6台MySQL,MySQL基本快打挂了。sysbench 点查,32个分表,增加Tomcat节点进来物理rt就增加,从最初的的1.2ms加到6个Tomcat节点后变成8ms。
MySQL没绑好核,BIOS默认关闭了NUMA,外加12个MySQL分布在物理机上不均匀,3个节点3个MySQL,剩下的物理机上只有一个MySQL实例。
MySQL每个实例32core,管控默认已经做了绑核,但是如果两个MySQL绑在了一个socket上竞争会很激烈,ipc比单独的降一半。
比如这三个MySQL,qps基本均匀,上面两个cpu高,但是没效率,每个MySQL绑了32core,上面两个绑在一个socket上,下面的MySQL绑在另一个socket上,第一个socket还有网络软中断在争抢cpu,飞腾环境下性能真要冲高还有很大空间。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
第二个MySQL IPC只有第三个的30%多点,这就是为什么CPU高这么多,但是QPS差不多
perf stat -e branch-misses,bus-cycles,cache-misses,cache-references,cpu-cycles,instructions,L1-dcache-load-misses,L1-dcache-loads,L1-dcache-store-misses,L1-dcache-stores,L1-icache-load-misses,L1-icache-loads,branch-load-misses,branch-loads,dTLB-load-misses,iTLB-load-misses -a -p 61238
^C
Performance counter stats for process id '61238':
86,491,052 branch-misses (58.55%)
98,481,418,793 bus-cycles (55.64%)
113,095,618 cache-misses # 6.169 % of all cache refs (53.20%)
1,833,344,484 cache-references (52.00%)
101,516,165,898 cpu-cycles (57.09%)
4,229,190,014 instructions # 0.04 insns per cycle (55.91%)
111,780,025 L1-dcache-load-misses # 6.34% of all L1-dcache hits (55.40%)
1,764,421,570 L1-dcache-loads (52.62%)
112,261,128 L1-dcache-store-misses (49.34%)
1,814,998,338 L1-dcache-stores (48.51%)
219,372,119 L1-icache-load-misses (49.56%)
2,816,279,627 L1-icache-loads (49.15%)
85,321,093 branch-load-misses (50.38%)
1,038,572,653 branch-loads (50.65%)
45,166,831 dTLB-load-misses (51.98%)
29,892,473 iTLB-load-misses (52.56%)
1.163750756 seconds time elapsed
#第三个MySQL
perf stat -e branch-misses,bus-cycles,cache-misses,cache-references,cpu-cycles,instructions,L1-dcache-load-misses,L1-dcache-loads,L1-dcache-store-misses,L1-dcache-stores,L1-icache-load-misses,L1-icache-loads,branch-load-misses,branch-loads,dTLB-load-misses,iTLB-load-misses -a -p 53400
^C
Performance counter stats for process id '53400':
295,575,513 branch-misses (40.51%)
110,934,600,206 bus-cycles (39.30%)
537,938,496 cache-misses # 8.310 % of all cache refs (38.99%)
6,473,688,885 cache-references (39.80%)
110,540,950,757 cpu-cycles (46.10%)
14,766,013,708 instructions # 0.14 insns per cycle (46.85%)
538,521,226 L1-dcache-load-misses # 8.36% of all L1-dcache hits (48.00%)
6,440,728,959 L1-dcache-loads (46.69%)
533,693,357 L1-dcache-store-misses (45.91%)
6,413,111,024 L1-dcache-stores (44.92%)
673,725,952 L1-icache-load-misses (42.76%)
9,216,663,639 L1-icache-loads (38.27%)
299,202,001 branch-load-misses (37.62%)
3,285,957,082 branch-loads (36.10%)
149,348,740 dTLB-load-misses (35.20%)
102,444,469 iTLB-load-misses (34.78%)
8.080841166 seconds time elapsed
|
12个MySQL流量基本均匀:
numa太多,每个numa下core比较少
导致跨numa高概率发生,如下是在正常部署下的测试perf 数据,可以看到IPC极低,才0.08,同样的场景在其他家芯片都能打到0.6
执行绑核,将一个进程限制在2个numa内,因为进程需要16core,理论上用8core的进程性能会更好
可以看到IPC从0.08提升到了0.22,实际能到0.27,对应的业务测试QPS也是原来的4倍。
用numactl 在启动的时候绑定cpu在 node0、1上,优先使用node0、1的内存,不够再用其它node的内存
1
|
numactl --cpunodebind 0,1 --preferred 0,1 /u01/xcluster80/bin/mysqld_safe --defaults-file=/polarx/xcluster3308/my.cnf --basedir=/u01/xcluster80_current --datadir=/polarx/xcluster3308/data --plugin-dir=/u01/xcluster80/lib/plugin --user=mysql --log-error=/polarx/xcluster3308/log/alert.log --open-files-limit=615350 --pid-file=/polarx/xcluster3308/run/mysql.pid --socket=/polarx/xcluster3308/run/mysql.sock --cluster-info=11.158.239.200:11308@1 --mysqlx-port=13308 --port=3308
|
网卡队列调整
这批机器默认都是双网卡做bond,但是两块网卡是HA,默认网卡队列是60,基本都跑在前面60个core上
将MySQL网卡队列从60个改成6个后MySQL性能提升大概10%
默认第一个MySQL都绑在0-31号核上,其实改少队列加大了0-5号core的压力,但是实际数据表现要好。
比较其它
绑核的时候还要考虑磁盘、网卡在哪个socket上,相对来说node和磁盘、网卡在同一个socket下性能要好一些。
左边的mysqld绑定在socket1的64core上,磁盘、网卡都在socket1上;右边的mysqld绑定在0-31core上,网卡在socket0上,但是磁盘在socket1上
右边这个刚好是跨socket访问磁盘,不知道是不是巧合log_flush排位比较高
此时对应的IPC:
如果上面两个进程在没有刷日志的场景下时候对应的IPC两者基本一样:
结论
FT2500比同主频Intel x86芯片差了快一个数量级的性能,在对FT2500上的业务按node绑核后性能提升了几倍,但是离Intel x86还有很大的距离
用循环跑多个nop指令在飞腾2500下IPC只能跑到1,据说这是因为nop指令被扔掉了,所以一直在跑跳转循环判断;
对寄存器变量进行++运算,IPC是0.5;
用如下代码能将IPC跑到2.49,也是我能跑出来的最高IPC了,去掉nop那行,IPC是1.99
1
2
3
4
|
register unsigned i=0;
for (i=0;i<(1u<<31);i++) {
__asm__ ("nop");
}
|
系列文章
CPU的制造和概念
CPU 性能和Cache Line
Perf IPC以及CPU性能
Intel、海光、鲲鹏920、飞腾2500 CPU性能对比
飞腾ARM芯片(FT2500)的性能测试的性能测试/)
十年后数据库还是不敢拥抱NUMA?
一次海光物理机资源竞争压测的记录
Intel PAUSE指令变化是如何影响自旋锁以及MySQL的性能的
参考资料
CPU Utilization is Wrong
作者|plantegg
推荐阅读
-
对比分析ARM Cortex-A系列处理器的性能表现
-
SSM三大框架基础面试题-一、Spring篇 什么是Spring框架? Spring是一种轻量级框架,提高开发人员的开发效率以及系统的可维护性。 我们一般说的Spring框架就是Spring Framework,它是很多模块的集合,使用这些模块可以很方便地协助我们进行开发。这些模块是核心容器、数据访问/集成、Web、AOP(面向切面编程)、工具、消息和测试模块。比如Core Container中的Core组件是Spring所有组件的核心,Beans组件和Context组件是实现IOC和DI的基础,AOP组件用来实现面向切面编程。 Spring的6个特征: 核心技术:依赖注入(DI),AOP,事件(Events),资源,i18n,验证,数据绑定,类型转换,SpEL。 测试:模拟对象,TestContext框架,Spring MVC测试,WebTestClient。 数据访问:事务,DAO支持,JDBC,ORM,编组XML。 Web支持:Spring MVC和Spring WebFlux Web框架。 集成:远程处理,JMS,JCA,JMX,电子邮件,任务,调度,缓存。 语言:Kotlin,Groovy,动态语言。 列举一些重要的Spring模块? Spring Core:核心,可以说Spring其他所有的功能都依赖于该类库。主要提供IOC和DI功能。 Spring Aspects:该模块为与AspectJ的集成提供支持。 Spring AOP:提供面向切面的编程实现。 Spring JDBC:Java数据库连接。 Spring JMS:Java消息服务。 Spring ORM:用于支持Hibernate等ORM工具。 Spring Web:为创建Web应用程序提供支持。 Spring Test:提供了对JUnit和TestNG测试的支持。 谈谈自己对于Spring IOC和AOP的理解 IOC(Inversion Of Controll,控制反转)是一种设计思想: 在程序中手动创建对象的控制权,交由给Spring框架来管理。IOC在其他语言中也有应用,并非Spring特有。IOC容器实际上就是一个Map(key, value),Map中存放的是各种对象。 将对象之间的相互依赖关系交给IOC容器来管理,并由IOC容器完成对象的注入。这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。IOC容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。在实际项目中一个Service类可能由几百甚至上千个类作为它的底层,假如我们需要实例化这个Service,可能要每次都搞清楚这个Service所有底层类的构造函数,这可能会把人逼疯。如果利用IOC的话,你只需要配置好,然后在需要的地方引用就行了,大大增加了项目的可维护性且降低了开发难度。 Spring中的bean的作用域有哪些? 1.singleton:该bean实例为单例 2.prototype:每次请求都会创建一个新的bean实例(多例)。 3.request:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。 4.session:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP session内有效。 5.global-session:全局session作用域,仅仅在基于Portlet的Web应用中才有意义,Spring5中已经没有了。Portlet是能够生成语义代码(例如HTML)片段的小型Java Web插件。它们基于Portlet容器,可以像Servlet一样处理HTTP请求。但是与Servlet不同,每个Portlet都有不同的会话。 Spring中的单例bean的线程安全问题了解吗? 概念用于理解:大部分时候我们并没有在系统中使用多线程,所以很少有人会关注这个问题。单例bean存在线程问题,主要是因为当多个线程操作同一个对象的时候,对这个对象的非静态成员变量的写操作会存在线程安全问题。 有两种常见的解决方案(用于回答的点): 1.在bean对象中尽量避免定义可变的成员变量(不太现实)。 2.在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在ThreadLocal(线程本地化对象)中(推荐的一种方式)。 ThreadLocal解决多线程变量共享问题(参考博客):https://segmentfault.com/a/1190000009236777 Spring中Bean的生命周期: 1.Bean容器找到配置文件中Spring Bean的定义。 2.Bean容器利用Java Reflection API创建一个Bean的实例。 3.如果涉及到一些属性值,利用set方法设置一些属性值。 4.如果Bean实现了BeanNameAware接口,调用setBeanName方法,传入Bean的名字。 5.如果Bean实现了BeanClassLoaderAware接口,调用setBeanClassLoader方法,传入ClassLoader对象的实例。 6.如果Bean实现了BeanFactoryAware接口,调用setBeanClassFacotory方法,传入ClassLoader对象的实例。 7.与上面的类似,如果实现了其他*Aware接口,就调用相应的方法。 8.如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执postProcessBeforeInitialization方法。 9.如果Bean实现了InitializingBean接口,执行afeterPropertiesSet方法。 10.如果Bean在配置文件中的定义包含init-method属性,执行指定的方法。 11.如果有和加载这个Bean的Spring容器相关的BeanPostProcess对象,执行postProcessAfterInitialization方法。 12.当要销毁Bean的时候,如果Bean实现了DisposableBean接口,执行destroy方法。 13.当要销毁Bean的时候,如果Bean在配置文件中的定义包含destroy-method属性,执行指定的方法。 Spring框架中用到了哪些设计模式? 1.工厂设计模式:Spring使用工厂模式通过BeanFactory和ApplicationContext创建bean对象。 2.代理设计模式:Spring AOP功能的实现。 3.单例设计模式:Spring中的bean默认都是单例的。 4.模板方法模式:Spring中的jdbcTemplate、hibernateTemplate等以Template结尾的对数据库操作的类,它们就使用到了模板模式。 5.包装器设计模式:我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。 6.观察者模式:Spring事件驱动模型就是观察者模式很经典的一个应用。 7.适配器模式:Spring AOP的增强或通知(Advice)使用到了适配器模式、Spring MVC中也是用到了适配器模式适配Controller。 还有很多。。。。。。。 @Component和@Bean的区别是什么 1.作用对象不同。@Component注解作用于类,而@Bean注解作用于方法。 2.@Component注解通常是通过类路径扫描来自动侦测以及自动装配到Spring容器中(我们可以使用@ComponentScan注解定义要扫描的路径)。@Bean注解通常是在标有该注解的方法中定义产生这个bean,告诉Spring这是某个类的实例,当我需要用它的时候还给我。 3.@Bean注解比@Component注解的自定义性更强,而且很多地方只能通过@Bean注解来注册bean。比如当引用第三方库的类需要装配到Spring容器的时候,就只能通过@Bean注解来实现。 @Configuration public class AppConfig { @Bean public TransferService transferService { return new TransferServiceImpl; } } <beans> <bean id="transferService" class="com.kk.TransferServiceImpl"/> </beans> @Bean public OneService getService(status) { case (status) { when 1: return new serviceImpl1; when 2: return new serviceImpl2; when 3: return new serviceImpl3; } } 将一个类声明为Spring的bean的注解有哪些? 声明bean的注解: @Component 组件,没有明确的角色 @Service 在业务逻辑层使用(service层) @Repository 在数据访问层使用(dao层) @Controller 在展现层使用,控制器的声明 注入bean的注解: @Autowired:由Spring提供 @Inject:由JSR-330提供 @Resource:由JSR-250提供 *扩:JSR 是 java 规范标准 Spring事务管理的方式有几种? 1.编程式事务:在代码中硬编码(不推荐使用)。 2.声明式事务:在配置文件中配置(推荐使用),分为基于XML的声明式事务和基于注解的声明式事务。 Spring事务中的隔离级别有哪几种? 在TransactionDefinition接口中定义了五个表示隔离级别的常量:ISOLATION_DEFAULT:使用后端数据库默认的隔离级别,Mysql默认采用的REPEATABLE_READ隔离级别;Oracle默认采用的READ_COMMITTED隔离级别。ISOLATION_READ_UNCOMMITTED:最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。ISOLATION_READ_COMMITTED:允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生ISOLATION_REPEATABLE_READ:对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。ISOLATION_SERIALIZABLE:最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。 Spring事务中有哪几种事务传播行为? 在TransactionDefinition接口中定义了八个表示事务传播行为的常量。 支持当前事务的情况:PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。PROPAGATION_SUPPORTS: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。PROPAGATION_MANDATORY: 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)。 不支持当前事务的情况:PROPAGATION_REQUIRES_NEW: 创建一个新的事务,如果当前存在事务,则把当前事务挂起。PROPAGATION_NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。PROPAGATION_NEVER: 以非事务方式运行,如果当前存在事务,则抛出异常。 其他情况:PROPAGATION_NESTED: 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于PROPAGATION_REQUIRED。 二、SpringMVC篇 什么是Spring MVC ?简单介绍下你对springMVC的理解? Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把Model,View,Controller分离,将web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。 Spring MVC的工作原理了解嘛? image.png Springmvc的优点: (1)可以支持各种视图技术,而不仅仅局限于JSP; (2)与Spring框架集成(如IoC容器、AOP等); (3)清晰的角色分配:前端控制器(dispatcherServlet) , 请求到处理器映射(handlerMapping), 处理器适配器(HandlerAdapter), 视图解析器(ViewResolver)。 (4) 支持各种请求资源的映射策略。 Spring MVC的主要组件? (1)前端控制器 DispatcherServlet(不需要程序员开发) 作用:接收请求、响应结果,相当于转发器,有了DispatcherServlet 就减少了其它组件之间的耦合度。 (2)处理器映射器HandlerMapping(不需要程序员开发) 作用:根据请求的URL来查找Handler (3)处理器适配器HandlerAdapter 注意:在编写Handler的时候要按照HandlerAdapter要求的规则去编写,这样适配器HandlerAdapter才可以正确的去执行Handler。 (4)处理器Handler(需要程序员开发) (5)视图解析器 ViewResolver(不需要程序员开发) 作用:进行视图的解析,根据视图逻辑名解析成真正的视图(view) (6)视图View(需要程序员开发jsp) View是一个接口, 它的实现类支持不同的视图类型(jsp,freemarker,pdf等等) springMVC和struts2的区别有哪些? (1)springmvc的入口是一个servlet即前端控制器(DispatchServlet),而struts2入口是一个filter过虑器(StrutsPrepareAndExecuteFilter)。 (2)springmvc是基于方法开发(一个url对应一个方法),请求参数传递到方法的形参,可以设计为单例或多例(建议单例),struts2是基于类开发,传递参数是通过类的属性,只能设计为多例。 (3)Struts采用值栈存储请求和响应的数据,通过OGNL存取数据,springmvc通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过reques域传输到页面。Jsp视图解析器默认使用jstl。 SpringMVC怎么样设定重定向和转发的? (1)转发:在返回值前面加"forward:",譬如"forward:user.do?name=method4" (2)重定向:在返回值前面加"redirect:",譬如"redirect:http://www.baidu.com" SpringMvc怎么和AJAX相互调用的? 通过Jackson框架就可以把Java里面的对象直接转化成Js可以识别的Json对象。具体步骤如下 : (1)加入Jackson.jar (2)在配置文件中配置json的映射 (3)在接受Ajax方法里面可以直接返回Object,List等,但方法前面要加上@ResponseBody注解。 如何解决POST请求中文乱码问题,GET的又如何处理呢? (1)解决post请求乱码问题: 在web.xml中配置一个CharacterEncodingFilter过滤器,设置成utf-8; <filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> (2)get请求中文参数出现乱码解决方法有两个: ①修改tomcat配置文件添加编码与工程编码一致,如下: <ConnectorURIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/> ②另外一种方法对参数进行重新编码: String userName = new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8") ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码。 Spring MVC的异常处理 ? 统一异常处理: Spring MVC处理异常有3种方式: (1)使用Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver; (2)实现Spring的异常处理接口HandlerExceptionResolver 自定义自己的异常处理器; (3)使用@ExceptionHandler注解实现异常处理; 统一异常处理的博客:https://blog.csdn.net/ctwy291314/article/details/81983103 SpringMVC的控制器是不是单例模式,如果是,有什么问题,怎么解决? 是单例模式,所以在多线程访问的时候有线程安全问题,不要用同步,会影响性能的,解决方案是在控制器里面不能写成员变量。(此题目类似于上面Spring 中 第5题 有两种解决方案) SpringMVC常用的注解有哪些? @RequestMapping:用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径。 @RequestBody:注解实现接收http请求的json数据,将json转换为java对象。 @ResponseBody:注解实现将conreoller方法返回对象转化为json对象响应给客户。 SpingMvc中的控制器的注解一般用那个,有没有别的注解可以替代? 一般用@Controller注解,也可以使用@RestController,@RestController注解相当于@ResponseBody + @Controller,表示是表现层,除此之外,一般不用别的注解代替。 如果在拦截请求中,我想拦截get方式提交的方法,怎么配置? 可以在@RequestMapping注解里面加上method=RequestMethod.GET。 怎样在方法里面得到Request,或者Session? 直接在方法的形参中声明request,SpringMVC就自动把request对象传入。 如果想在拦截的方法里面得到从前台传入的参数,怎么得到? 直接在形参里面声明这个参数就可以,但必须名字和传过来的参数一样。 如果前台有很多个参数传入,并且这些参数都是一个对象的,那么怎么样快速得到这个对象? 直接在方法中声明这个对象,SpringMVC就自动会把属性赋值到这个对象里面。 SpringMVC中函数的返回值是什么? 返回值可以有很多类型,有String, ModelAndView。ModelAndView类把视图和数据都合并的一起的。 SpringMVC用什么对象从后台向前台传递数据的? 通过ModelMap对象,可以在这个对象里面调用put方法,把对象加到里面,前台就可以拿到数据。 怎么样把ModelMap里面的数据放入Session里面? 可以在类上面加上@SessionAttributes注解,里面包含的字符串就是要放入session里面的key。 SpringMvc里面拦截器是怎么写的: 有两种写法,一种是实现HandlerInterceptor接口,另外一种是继承适配器类,接着在接口方法当中,实现处理逻辑;然后在SpringMvc的配置文件中配置拦截器即可: <!-- 配置SpringMvc的拦截器 --> <mvc:interceptors> <!-- 配置一个拦截器的Bean就可以了 默认是对所有请求都拦截 --> <bean id="myInterceptor" class="com.zwp.action.MyHandlerInterceptor"></bean> <!-- 只针对部分请求拦截 --> <mvc:interceptor> <mvc:mapping path="/modelMap.do" /> <bean class="com.zwp.action.MyHandlerInterceptorAdapter" /> </mvc:interceptor> </mvc:interceptors> 注解原理: 注解本质是一个继承了Annotation的特殊接口,其具体实现类是Java运行时生成的动态代理类。我们通过反射获取注解时,返回的是Java运行时生成的动态代理对象。通过代理对象调用自定义注解的方法,会最终调用AnnotationInvocationHandler的invoke方法。该方法会从memberValues这个Map中索引出对应的值。而memberValues的来源是Java常量池 三、Mybatis篇 什么是MyBatis? MyBatis是一个可以自定义SQL、存储过程和高级映射的持久层框架。 讲下MyBatis的缓存 MyBatis的缓存分为一级缓存和二级缓存,一级缓存放在session里面,默认就有, 二级缓存放在它的命名空间里,默认是不打开的,使用二级缓存属性类需要实现Serializable序列化接口, 可在它的映射文件中配置<cache/> Mybatis是如何进行分页的?分页插件的原理是什么? 1)Mybatis使用RowBounds对象进行分页,也可以直接编写sql实现分页,也可以使用Mybatis的分页插件。 2)分页插件的原理:实现Mybatis提供的接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql。 举例:select * from student,拦截sql后重写为:select t.* from (select * from student)t limit 0,10 简述Mybatis的插件运行原理,以及如何编写一个插件? 1)Mybatis仅可以编写针对ParameterHandler、ResultSetHandler、StatementHandler、 Executor这4种接口的插件,Mybatis通过动态代理, 为需要拦截的接口生成代理对象以实现接口方法拦截功能, 每当执行这4种接口对象的方法时,就会进入拦截方法, 具体就是InvocationHandler的invoke方法,当然, 只会拦截那些你指定需要拦截的方法。 2)实现Mybatis的Interceptor接口并复写intercept方法, 然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可, 记住,别忘了在配置文件中配置你编写的插件。 Mybatis动态sql是做什么的?都有哪些动态sql?能简述一下动态sql的执行原理不? 1)Mybatis动态sql可以让我们在Xml映射文件内, 以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能。 2)Mybatis提供了9种动态sql标签:trim|where|set|foreach|if|choose|when|otherwise|bind。 3)其执行原理为,使用OGNL从sql参数对象中计算表达式的值, 根据表达式的值动态拼接sql,以此来完成动态sql的功能。 #{}和${}的区别是什么? 1)#{}是预编译处理,${}是字符串替换。 2)Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值(有效的防止SQL注入); 3)Mybatis在处理${}时,就是把${}替换成变量的值。 为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里? Hibernate属于全自动ORM映射工具, 使用Hibernate查询关联对象或者关联集合对象时, 可以根据对象关系模型直接获取,所以它是全自动的。 而Mybatis在查询关联对象或关联集合对象时, 需要手动编写sql来完成,所以,称之为半自动ORM映射工具。 Mybatis是否支持延迟加载?如果支持,它的实现原理是什么? 1)Mybatis仅支持association关联对象和collection关联集合对象的延迟加载, association指的就是一对一,collection指的就是一对多查询。 在Mybatis配置文件中, 可以配置是否启用延迟加载lazyLoadingEnabled=true|false。 2)它的原理是,使用CGLIB创建目标对象的代理对象, 当调用目标方法时,进入拦截器方法, 比如调用a.getB.getName, 拦截器invoke方法发现a.getB是null值, 那么就会单独发送事先保存好的查询关联B对象的sql, 把B查询上来,然后调用a.setB(b), 于是a的对象b属性就有值了, 接着完成a.getB.getName方法的调用。 这就是延迟加载的基本原理。 MyBatis与Hibernate有哪些不同? 1)Mybatis和hibernate不同,它不完全是一个ORM框架, 因为MyBatis需要程序员自己编写Sql语句, 不过mybatis可以通过XML或注解方式灵活配置要运行的sql语句, 并将java对象和sql语句映射生成最终执行的sql, 最后将sql执行的结果再映射生成java对象。 2)Mybatis学习门槛低,简单易学,程序员直接编写原生态sql, 可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发, 例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁, 一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性, 如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。 3)Hibernate对象/关系映射能力强,数据库无关性好, 对于关系模型要求高的软件(例如需求固定的定制化软件) 如果用hibernate开发可以节省很多代码,提高效率。 但是Hibernate的缺点是学习门槛高,要精通门槛更高, 而且怎么设计O/R映射,在性能和对象模型之间如何权衡, 以及怎样用好Hibernate需要具有很强的经验和能力才行。 总之,按照用户的需求在有限的资源环境下只要能做出维护性、 扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。 MyBatis的好处是什么? 1)MyBatis把sql语句从Java源程序中独立出来,放在单独的XML文件中编写, 给程序的维护带来了很大便利。 2)MyBatis封装了底层JDBC API的调用细节,并能自动将结果集转换成Java Bean对象, 大大简化了Java数据库编程的重复工作。 3)因为MyBatis需要程序员自己去编写sql语句, 程序员可以结合数据库自身的特点灵活控制sql语句, 因此能够实现比Hibernate等全自动orm框架更高的查询效率,能够完成复杂查询。 简述Mybatis的Xml映射文件和Mybatis内部数据结构之间的映射关系? Mybatis将所有Xml配置信息都封装到All-In-One重量级对象Configuration内部。 在Xml映射文件中,<parameterMap>标签会被解析为ParameterMap对象, 其每个子元素会被解析为ParameterMapping对象。 <resultMap>标签会被解析为ResultMap对象, 其每个子元素会被解析为ResultMapping对象。 每一个<select>、<insert>、<update>、<delete> 标签均会被解析为MappedStatement对象, 标签内的sql会被解析为BoundSql对象。 什么是MyBatis的接口绑定,有什么好处? 接口映射就是在MyBatis中任意定义接口,然后把接口里面的方法和SQL语句绑定, 我们直接调用接口方法就可以,这样比起原来了SqlSession提供的方法我们可以有更加灵活的选择和设置. 接口绑定有几种实现方式,分别是怎么实现的? 接口绑定有两种实现方式,一种是通过注解绑定,就是在接口的方法上面加 上@Select@Update等注解里面包含Sql语句来绑定, 另外一种就是通过xml里面写SQL来绑定,在这种情况下, 要指定xml映射文件里面的namespace必须为接口的全路径名. 什么情况下用注解绑定,什么情况下用xml绑定? 当Sql语句比较简单时候,用注解绑定;当SQL语句比较复杂时候,用xml绑定,一般用xml绑定的比较多 MyBatis实现一对一有几种方式?具体怎么操作的? 有联合查询和嵌套查询,联合查询是几个表联合查询,只查询一次, 通过在resultMap里面配置association节点配置一对一的类就可以完成; 嵌套查询是先查一个表,根据这个表里面的结果的外键id, 去再另外一个表里面查询数据,也是通过association配置, 但另外一个表的查询通过select属性配置。 Mybatis能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别? 能,Mybatis不仅可以执行一对一、一对多的关联查询, 还可以执行多对一,多对多的关联查询,多对一查询, 其实就是一对一查询,只需要把selectOne修改为selectList即可; 多对多查询,其实就是一对多查询,只需要把selectOne修改为selectList即可。 关联对象查询,有两种实现方式,一种是单独发送一个sql去查询关联对象, 赋给主对象,然后返回主对象。另一种是使用嵌套查询,嵌套查询的含义为使用join查询, 一部分列是A对象的属性值,另外一部分列是关联对象B的属性值, 好处是只发一个sql查询,就可以把主对象和其关联对象查出来。 MyBatis里面的动态Sql是怎么设定的?用什么语法? MyBatis里面的动态Sql一般是通过if节点来实现,通过OGNL语法来实现, 但是如果要写的完整,必须配合where,trim节点,where节点是判断包含节点有 内容就插入where,否则不插入,trim节点是用来判断如果动态语句是以and 或or 开始,那么会自动把这个and或者or取掉。 Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式? 第一种是使用<resultMap>标签,逐一定义列名和对象属性名之间的映射关系。 第二种是使用sql列的别名功能,将列别名书写为对象属性名, 比如T_NAME AS NAME,对象属性名一般是name,小写, 但是列名不区分大小写,Mybatis会忽略列名大小写,
-
测试飞腾ARM处理器FT2500的性能表现