Check heaps что за процесс
Надежный системный администратор для малого бизнеса
ежедневно, с 9:30 до 20:00 8 (499) 653-83-80
Ветрикс Надежный системный администратор для малого бизнеса
Интенсивное использование CPU в коммутаторе Catalyst 6500/6000 — Часть 5
Проверка загрузки ЦП
При высокой загрузке ЦП выполните сначала команду show processes cpu. Выходные данные показывают загрузку ЦП коммутатора, а также потребление ресурсов ЦП каждым процессом.
Router#show processes cpu CPU utilization for five seconds: 57%/48%; one minute: 56%; five minutes: 48% PID Runtime(ms) Invoked uSecs 5Sec 1Min 5Min TTY Process 1 0 5 0 0.00% 0.00% 0.00% 0 Chunk Manager 2 12 18062 0 0.00% 0.00% 0.00% 0 Load Meter 4 164532 13717 11994 0.00% 0.21% 0.17% 0 Check heaps 5 0 1 0 0.00% 0.00% 0.00% 0 Pool Manager !--- Output is suppressed. 172 0 9 0 0.00% 0.00% 0.00% 0 RPC aapi_rp 173 243912 2171455 112 9.25% 8.11% 7.39% 0 SNMP ENGINE 174 68 463 146 0.00% 0.00% 0.00% 0 RPC pm-mp !--- Output is suppressed.
В этих выходных данных общая загрузка ЦП составляет 57 процентов, а загрузка ЦП прерываниями — 48 процентов. Эти показатели отображаются полужирным шрифтом. Коммутация трафика прерываний процессором приводит к загрузке ЦП прерываниями. В выходных данных команды перечисляются процессы, которые приводят к разнице между этими двумя загрузками. В данном случае причиной является процесс SNMP.
Чтобы не вникать в механизмы, наймите специалистов по обслуживанию сетей. В механизме управления, который работает под управлением CatOS, выходные данные выглядят так:
Switch> (enable) show processes cpu CPU utilization for five seconds: 99.72% one minute: 100.00% five minutes: 100.00% PID Runtime(ms) Invoked uSecs 5Sec 1Min 5Min TTY Process --- ----------- ---------- -------- ------- ------- ------- --- --------------- 1 0 0 0 0.28% 0.00% 0.00% -2 Kernel and Idle 2 2 261 1000 0.00% 0.00% 0.00% -2 Flash MIB Updat 3 0 1 0 0.00% 0.00% 0.00% -2 L2L3IntHdlr 4 0 1 0 0.00% 0.00% 0.00% -2 L2L3PatchRev !--- Output is suppressed. 61 727295 172025 18000 0.82% 0.00% 0.00% -2 SptTimer 62 18185410 3712736 106000 22.22% 21.84% 21.96% -2 SptBpduRx 63 845683 91691 105000 0.92% 0.00% 0.00% -2 SptBpduTx
В этих выходных данных первый процесс — Kernel and Idle — показывает простой в использовании ЦП. Этот процесс обычно наверху, если какие-либо другие процессы не потребляют циклы ЦП. В этом примере процесс SptBpduRx приводит к повышению загрузки ЦП.
Если причиной высокой загрузки ЦП является один из этих процессов, можно провести диагностику и определить, почему этот процесс приводит к высокой загрузке. Но если ЦП загружен из-за трафика, поступающего на него, необходимо определить, почему приходит этот трафик. При этом можно определить происхождение трафика.
Служебные программы и средства для определения трафика, поступающего на ЦП
В этом разделе определяются некоторые служебные программы и средства, которые могут помочь изучить этот трафик.
Системное программное обеспечение Cisco IOS
В ПО Cisco IOS процессор коммутатора в механизме управления называется SP, а MSFC называется RP.
Команда show interface дает основную информацию о состоянии интерфейса и скорости трафика на интерфейсе. В этой команде также предусмотрены счетчики ошибок.
Router#show interface gigabitethernet 4/1 GigabitEthernet4/1 is up, line protocol is up (connected) Hardware is C6k 1000Mb 802.3, address is 000a.42d1.7580 (bia 000a.42d1.7580) Internet address is 100.100.100.2/24 MTU 1500 bytes, BW 1000000 Kbit, DLY 10 usec, reliability 255/255, txload 1/255, rxload 1/255 Encapsulation ARPA, loopback not set Keepalive set (10 sec) Half-duplex, 100Mb/s input flow-control is off, output flow-control is off Clock mode is auto ARP type: ARPA, ARP Timeout 04:00:00 Last input 00:00:00, output 00:00:00, output hang never Last clearing of "show interface" counters never Input queue: 5/75/1/24075 (size/max/drops/flushes); Total output drops: 2 Queueing strategy: fifo Output queue: 0/40 (size/max) 30 second input rate 7609000 bits/sec, 14859 packets/sec 30 second output rate 0 bits/sec, 0 packets/sec L2 Switched: ucast: 0 pkt, 184954624 bytes - mcast: 1 pkt, 500 bytes L3 in Switched: ucast: 2889916 pkt, 0 bytes - mcast: 0 pkt, 0 bytes mcast L3 out Switched: ucast: 0 pkt, 0 bytes mcast: 0 pkt, 0 bytes 2982871 packets input, 190904816 bytes, 0 no buffer Received 9 broadcasts, 0 runts, 0 giants, 0 throttles 1 input errors, 1 CRC, 0 frame, 28 overrun, 0 ignored 0 input packets with dribble condition detected 1256 packets output, 124317 bytes, 0 underruns 2 output errors, 1 collisions, 2 interface resets 0 babbles, 0 late collision, 0 deferred 0 lost carrier, 0 no carrier 0 output buffer failures, 0 output buffers swapped out
В этих выходных данных можно увидеть, что входящий трафик коммутируется на 3 уровне вместо коммутации 2 уровня. Это показывает, что трафик поступает на ЦП.
Команда show processes cpu показывает, являются ли эти пакеты пакетами обычного трафика или пакетами управления.
Router#show processes cpu | exclude 0.00 CPU utilization for five seconds: 91%/50%; one minute: 89%; five minutes: 47% PID Runtime(ms) Invoked uSecs 5Sec 1Min 5Min TTY Process 5 881160 79142 11133 0.49% 0.19% 0.16% 0 Check heaps 98 121064 3020704 40 40.53% 38.67% 20.59% 0 IP Input 245 209336 894828 233 0.08% 0.05% 0.02% 0 IFCOM Msg Hdlr
Если пакеты коммутируются процессом, то будет видно, что процесс IP Input повышается. Чтобы увидеть эти пакеты, выполните такую команду:
show buffers input-interface
Router#show buffers input-interface gigabitethernet 4/1 packet Buffer information for Small buffer at 0x437874D4 data_area 0x8060F04, refcount 1, next 0x5006D400, flags 0x280 linktype 7 (IP), enctype 1 (ARPA), encsize 14, rxtype 1 if_input 0x505BC20C (GigabitEthernet4/1), if_output 0x0 (None) inputtime 00:00:00.000 (elapsed never) outputtime 00:00:00.000 (elapsed never), oqnumber 65535 datagramstart 0x8060F7A, datagramsize 60, maximum size 308 mac_start 0x8060F7A, addr_start 0x8060F7A, info_start 0x0 network_start 0x8060F88, transport_start 0x8060F9C, caller_pc 0x403519B4 source: 100.100.100.1, destination: 100.100.100.2, id: 0x0000, ttl: 63, TOS: 0 prot: 17, source port 63, destination port 63 08060F70: 000A 42D17580 ..BQu. 08060F80: 00000000 11110800 4500002E 00000000 . E. 08060F90: 3F11EAF3 64646401 64646402 003F003F ?.jsddd.ddd. 08060FA0: 001A261F 00010203 04050607 08090A0B ..&. 08060FB0: 0C0D0E0F 101164 . d
Если трафик коммутируется прерываниями, то эти пакеты нельзя увидеть с помощью команды show buffers input-interface. ИТ аутсорсинг это возможность не вникать в скучную информацию. Чтобы увидеть пакеты, поступающие на ЦП для коммутации на уровне прерываний, можно выполнить захват SPAN порта RP.
Заказать звонок
Пожалуйста, оставьте свои контакты
Check heaps что за процесс
Маршрутизаторы Cisco 871w и Cisco 1801w значительно более производительны, чем маршрутизатор Cisco SB101, и, как показали опыты, копирование по NetBios не было так эффективно, как использование программы ttcp. Cisco 871w with using of CBAC:
c:\ttcp>PCATTCP.exe -t -f m -n 122070 192.168.1.1 PCAUSA Test TCP Utility V2.01.01.08 TCP Transmit Test Transmit : TCP -> 192.168.1.1:5001 Buffer Size : 8192; Alignment: 16384/0 TCP_NODELAY : DISABLED (0) Connect : Connected to 192.168.1.1:5001 Send Mode : Send Pattern; Number of Buffers: 122070 Statistics : TCP -> 192.168.1.1:5001 999997440 bytes in 186.02 real seconds = 41.01 Mbit/sec +++ numCalls: 122070; msec/call: 1.56; calls/sec: 656.23
c871w#sh proc cpu s CPU utilization for five seconds: 99%/97%; one minute: 91%; five minutes: 33% Cisco 871w w/o of CBAC:
c:\ttcp>PCATTCP.exe -t -f m -n 122070 192.168.1.1 PCAUSA Test TCP Utility V2.01.01.08 TCP Transmit Test Transmit : TCP -> 192.168.1.1:5001 Buffer Size : 8192; Alignment: 16384/0 TCP_NODELAY : DISABLED (0) Connect : Connected to 192.168.1.1:5001 Send Mode : Send Pattern; Number of Buffers: 122070 Statistics : TCP -> 192.168.1.1:5001 999997440 bytes in 118.14 real seconds = 64.58 Mbit/sec +++ numCalls: 122070; msec/call: 0.99; calls/sec: 1033.26
c871w#sh proc cpu s CPU utilization for five seconds: 97%/96%; one minute: 94%; five minutes: 72% То есть, в случае с Cisco 871w, всё упирается в производительность процессора. Cisco 1801w witch using of CBAC:
c:\ttcp>PCATTCP.exe -t -f m -n 122070 192.168.1.1 PCAUSA Test TCP Utility V2.01.01.08 TCP Transmit Test Transmit : TCP -> 192.168.1.1:5001 Buffer Size : 8192; Alignment: 16384/0 TCP_NODELAY : DISABLED (0) Connect : Connected to 192.168.1.1:5001 Send Mode : Send Pattern; Number of Buffers: 122070 Statistics : TCP -> 192.168.1.1:5001 999997440 bytes in 90.28 real seconds = 84.51 Mbit/sec +++ numCalls: 122070; msec/call: 0.76; calls/sec: 1352.11
c1801w#sh proc cpu s CPU utilization for five seconds: 54%/54%; one minute: 26%; five minutes: 8% Cisco 1801w w/o CBAC:
c:\ttcp>PCATTCP.exe -t -f m -n 122070 192.168.1.1 PCAUSA Test TCP Utility V2.01.01.08 TCP Transmit Test Transmit : TCP -> 192.168.1.1:5001 Buffer Size : 8192; Alignment: 16384/0 TCP_NODELAY : DISABLED (0) Connect : Connected to 192.168.1.1:5001 Send Mode : Send Pattern; Number of Buffers: 122070 Statistics : TCP -> 192.168.1.1:5001 999997440 bytes in 89.41 real seconds = 85.33 Mbit/sec +++ numCalls: 122070; msec/call: 0.75; calls/sec: 1365.34
yourname#sh proc cpu s CPU utilization for five seconds: 39%/39%; one minute: 34%; five minutes: 19% А вот производительности Cisco 1801w более, чем достаточно для обеспечения ~100 Mbit/sec производительности, даже при использования CBAC+NAT, есть свободные процессорные ресурсы для использования других сервисов, например IPSec или IPS. (2) Флуд воспроизводился на внешний интерфейс.
netwox— набор сетевых инструментов для аудита сети.
Команда «netwox 74 -i «, посылает множество ip-пакетов со случайным src ip-адресом.
Команда «netwox 75 -d «, посылает множество ethernet фреймов, со случайным dst-mac адресом, заполняя cam таблицу.
Cisco SB 101 Флуд на WAN портe1, защищённый CBAC’ом. netwox 74 -i 10.20.20.1:
#sh int e1 staz Ethernet1 Switching path Pkts In Chars In Pkts Out Chars Out Processor 738 63468 12 1344 Route cache 164220 14122920 0 0 Total 164958 14186388 12 1344
#sh proc cpu s CPU utilization for five seconds: 99%/99%; one minute: 26%; five minutes: 9% PID Runtime(ms) Invoked uSecs 5Sec 1Min 5Min TTY Process 34 237424 12095 19629 0.63% 0.15% 0.04% 0 IP Input 21 6060 37174 163 0.07% 0.00% 0.00% 0 LED Timers 1 0 9 0 0.00% 0.00% 0.00% 0 Chunk Manager 2 2900 2657 1091 0.00% 0.00% 0.00% 0 Load Meter 3 1112 234 4752 0.00% 0.17% 0.14% 0 Exec
netwox 75 -d Eth0:
#sh int e1 st Ethernet1 Switching path Pkts In Chars In Pkts Out Chars Out Processor 203186 13614022 8 792 Route cache 0 0 0 0 Total 203186 13614022 8 792
sb101#sh proc cpu s CPU utilization for five seconds: 99%/99%; one minute: 31%; five minutes: 15% PID Runtime(ms) Invoked uSecs 5Sec 1Min 5Min TTY Process 48 6884 465 14804 0.14% 0.01% 0.00% 0 IP Background 4 308756 14370 21486 0.14% 1.32% 1.80% 0 Check heaps 20 5592 13558 412 0.07% 0.00% 0.00% 0 Per-Second Jobs 84 1652 699 2363 0.07% 0.00% 0.00% 0 IPSEC key engine 5 1228 20 61400 0.00% 0.00% 0.00% 0 Pool Manager 2 3720 2738 1358 0.00% 0.00% 0.00% 0 Load Meter 3 4456 443 10058 0.00% 0.12% 0.18% 0 Exec
При флуде случайными IP-пакетами – маршрутизатор не отвечает на icmp запросы, работа невозможна, при флуде же случайными eth фреймами – наблюдается следующая картина:
Ping statistics for 10.10.10.1: Packets: Sent = 48, Received = 15, Lost = 33 (68% loss), Approximate round trip times in milli-seconds: Minimum = 1ms, Maximum = 3211ms, Average = 519ms
Хочется отметить, что при флуде фреймами со случайными srs mac-адресами работа практически невозможна через консоль на маршрутизаторе (отклик на введённые команды 20-60 сек), при флуде пакетами со случайными srs ip-адресами работа на маршрутизаторе возможна, но если сделать запрещающий access-list для этого src-адреса, то наблюдается такая же ситуация, как и в первом случае. На маршрутизаторах Cisco 871w и Cisco 1801w работа не нарушилась: Cisco 871W netwox 74 -i 10.10.10.1:
с871#show proc cpu sorted CPU utilization for five seconds: 40%/38%; one minute: 26%; five minutes: 13% PID Runtime(ms) Invoked uSecs 5Sec 1Min 5Min TTY Process 37 144272 405578 355 1.19% 0.86% 0.39% 0 COLLECT STAT COU 56 1428 746 1914 0.31% 0.05% 0.01% 0 Exec 8 14744 64054 230 0.07% 0.05% 0.06% 0 ARP Input 69 15948 53114 300 0.07% 0.04% 0.00% 0 IP Input 1 8 7 1142 0.00% 0.00% 0.00% 0 Chunk Manager
netwox 75 -d Eth0:
с871##sh proc cpu s CPU utilization for five seconds: 77%/75%; one minute: 37%; five minutes: 19% PID Runtime(ms) Invoked uSecs 5Sec 1Min 5Min TTY Process 37 146416 406010 360 1.67% 1.11% 0.60% 0 COLLECT STAT COU 84 940 89322 10 0.07% 0.00% 0.00% 0 CEF process 133 140 38081 3 0.07% 0.00% 0.00% 0 PM Callback 3 708 81357 8 0.00% 0.00% 0.00% 0 Spanning Tree 4 23928 8283 2888 0.00% 0.05% 0.00% 0 Check heaps 5 0 78 0 0.00% 0.00% 0.00% 0 Pool Manager
Cisco 1801W netwox 74 -i 10.40.40.1:
с1801#sh proc cpu s CPU utilization for five seconds: 84%/39%; one minute: 44%; five minutes: 14% PID Runtime(ms) Invoked uSecs 5Sec 1Min 5Min TTY Process 79 64784 1039583 62 44.23% 22.50% 6.61% 0 IP Input 5 752 127 5921 0.47% 0.08% 0.06% 0 Check heaps 48 532 8309 64 0.23% 0.16% 0.04% 0 COLLECT STAT COU 1 0 2 0 0.00% 0.00% 0.00% 0 Chunk Manager 2 0 216 0 0.00% 0.00% 0.00% 0 Load Meter 3 6244 700 8920 0.00% 0.02% 0.18% 0 Exec
netwox 75 -d Eth0:
с1801#sh proc cpu s *Jul 14 14:40:11.231: %CLEAR-5-COUNTERS: Clear counter on all interfaces by cisc sh proc cpu s CPU utilization for five seconds: 21%/20%; one minute: 6%; five minutes: 8% PID Runtime(ms) Invoked uSecs 5Sec 1Min 5Min TTY Process 5 976 164 5951 0.23% 0.07% 0.05% 0 Check heaps 48 684 10828 63 0.23% 0.08% 0.03% 0 COLLECT STAT COU 1 0 2 0 0.00% 0.00% 0.00% 0 Chunk Manager 2 0 281 0 0.00% 0.00% 0.00% 0 Load Meter 3 6320 851 7426 0.00% 0.03% 0.06% 0 Exec
(3) IPSec тоннель между Cisco 871w и Cisco 2801, а также между Cisco 1801w и Cisco 2801.
Тестирование проводилось в трёх режимах: 1) Hardware — Hardware a) Cisco 2801 hardware IPSec + Cisco 871w hardware IPSec:
c2801#sh proc cpu h 7776777777777777775 8 3100001111101110116147 100 90 * 80 * 70 *#* ************** * 60 ##******###*#*#**** * 50 ###****########*##* * 40 ##################* * 30 ################### * 20 ################### * 10 ################### # 0. 5. 1. 1. 2. 2. 3. 3. 4. 4. 5. 5. 0 5 0 5 0 5 0 5 0 5 CPU% per minute (last 60 minutes) * = maximum CPU% # = average CPU%
c871w#sh proc cpu h 11 11 11111 111 90050050000090007 5 90000040000090006222 100 *** ** ********* 90 #** ** ********* 80 ##* ** ****#***** 70 ##* ** #####***** 60 ##* ** #####***** 50 ###****#######*#* * 40 ###*#**#########* * 30 ######*########## * 20 ################# * 10 ################# * 0. 5. 1. 1. 2. 2. 3. 3. 4. 4. 5. 5. 0 5 0 5 0 5 0 5 0 5 CPU% per minute (last 60 minutes) * = maximum CPU% # = average CPU%
Данные с компьютера, вывод программы ttcp: Поток recieve
c:\ttcp>PCATTCP.exe -r -f m PCAUSA Test TCP Utility V2.01.01.08 TCP Receive Test Local Host : host-1 Listening. On port 5001 Accept : TCP Поток transmitc:\ttcp>PCATTCP.exe -t -f m -n 122070 10.0.2.2 PCAUSA Test TCP Utility V2.01.01.08 TCP Transmit Test Transmit : TCP -> 10.0.2.2:5001 Buffer Size : 8192; Alignment: 16384/0 TCP_NODELAY : DISABLED (0) Connect : Connected to 10.0.2.2:5001 Send Mode : Send Pattern; Number of Buffers: 122070 Statistics : TCP -> 10.0.2.2:5001 999997440 bytes in 1006.26 real seconds = 7.58 Mbit/sec +++ numCalls: 122070; msec/call: 8.44; calls/sec: 121.31b) Cisco 2801 hardware IPSec + Cisco 1801w hardware IPSec:
c1801w#sh proc cpu h 4444444449 3344443540 100 90 * 80 * 70 * 60 * 50 * * 40 *#######** 30 *########* 20 #########* 10 ########## 0. 5. 1. 1. 2. 2. 3. 3. 4. 4. 5. 5. 0 5 0 5 0 5 0 5 0 5 CPU% per minute (last 60 minutes) * = maximum CPU% # = average CPU%c2801#sh proc cpu h 1222234444444444444444444444 8 8996323665666666467676666672 7 100 90 * 80 * 70 * 60 * 50 ********* ******#*** * 40 *####################* * 30 *** **####################* * 20 *##########################* * 10 ###########################* # 0. 5. 1. 1. 2. 2. 3. 3. 4. 4. 5. 5. 0 5 0 5 0 5 0 5 0 5 CPU% per minute (last 60 minutes) * = maximum CPU% # = average CPU%Поток revieve
c:\ttcp>PCATTCP.exe -r -f m PCAUSA Test TCP Utility V2.01.01.08 TCP Receive Test Local Host : host-1 Listening. On port 5001 Accept : TCP Поток transmitc:\ttcp>PCATTCP.exe -t -f m -n 122070 10.0.10.2 PCAUSA Test TCP Utility V2.01.01.08 TCP Transmit Test Transmit : TCP -> 10.0.10.2:5001 Buffer Size : 8192; Alignment: 16384/0 TCP_NODELAY : DISABLED (0) Connect : Connected to 10.0.10.2:5001 Send Mode : Send Pattern; Number of Buffers: 122070 Statistics : TCP -> 10.0.10.2:5001 999997440 bytes in 482.11 real seconds = 15.82 Mbit/sec +++ numCalls: 122070; msec/call: 4.04; calls/sec: 253.202) Software - Software a) Cisco 2801 software IPSec + Cisco 871w software IPSec:
с871w#sh proc cpu h 7777777777777777777777777777777777777777777777777777777777 7888888878877556665555556566676666655556555665665555655655 100 90 80 *############*************#########********##*************** 70 *########################################################### 60 *########################################################### 50 *########################################################### 40 *########################################################### 30 *########################################################### 20 *########################################################### 10 ############################################################ 0. 5. 1. 1. 2. 2. 3. 3. 4. 4. 5. 5. 0 5 0 5 0 5 0 5 0 5 CPU% per minute (last 60 minutes) * = maximum CPU% # = average CPU%c2801#sh proc cpu h CPU% per second (last 60 seconds) 11111111 111111111111111111111111111111111111111111111111 0000000099000000000000000000000000000000000000000000000000 0000000099000000000000000000000000000000000000000000000000 100 *#########################################################* 90 *#########################################################* 80 ##########################################################* 70 ########################################################### 60 ########################################################### 50 ########################################################### 40 ########################################################### 30 ########################################################### 20 ########################################################### 10 ########################################################### 0. 5. 1. 1. 2. 2. 3. 3. 4. 4. 5. 5. 0 5 0 5 0 5 0 5 0 5 CPU% per minute (last 60 minutes) * = maximum CPU% # = average CPU%Поток transmit
c:\ttcp>PCATTCP.exe -t -f m -n 122070 10.0.2.2 PCAUSA Test TCP Utility V2.01.01.08 TCP Transmit Test Transmit : TCP -> 10.0.2.2:5001 Buffer Size : 8192; Alignment: 16384/0 TCP_NODELAY : DISABLED (0) Connect : Connected to 10.0.2.2:5001 Send Mode : Send Pattern; Number of Buffers: 122070 Statistics : TCP -> 10.0.2.2:5001 999997440 bytes in 3158.92 real seconds = 2.42 Mbit/sec +++ numCalls: 122070; msec/call: 26.50; calls/sec: 38.64Поток receive
c:\ttcp>PCATTCP.exe -r -f m PCAUSA Test TCP Utility V2.01.01.08 TCP Receive Test Local Host : host-1 Listening. On port 5001 Accept : TCP b) Cisco 2801 software IPSec + Cisco 1801w software IPSec:с1801w#sh proc cpu h 4444464444444444444444444444444444444444444444444444444444 2222203222221122121111222222222221122222221112111211121222 100 90 80 70 60 * 50 * 40 *########################################################### 30 ############################################################ 20 ############################################################ 10 ############################################################ 0. 5. 1. 1. 2. 2. 3. 3. 4. 4. 5. 5. 0 5 0 5 0 5 0 5 0 5 CPU% per minute (last 60 minutes) * = maximum CPU% # = average CPU%c2801#sh proc cpu h 111111111111111111111111111111111111111111111111111111111 000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000 100 *#########################################################* 90 *#########################################################* 80 *#########################################################* 70 ##########################################################* 60 ##########################################################* 50 ##########################################################* 40 ##########################################################* 30 ########################################################### 20 ########################################################### 10 ########################################################### 0. 5. 1. 1. 2. 2. 3. 3. 4. 4. 5. 5. 0 5 0 5 0 5 0 5 0 5 CPU% per minute (last 60 minutes) * = maximum CPU% # = average CPU%Поток recieve
c:\ttcp>PCATTCP.exe -r -f m PCAUSA Test TCP Utility V2.01.01.08 TCP Receive Test Local Host : host-1 ************** Listening. On port 5001 Accept : TCP Поток transmitc:\ttcp>PCATTCP.exe -t -f m -n 122070 10.0.1.2 PCAUSA Test TCP Utility V2.01.01.08 TCP Transmit Test Transmit : TCP -> 10.0.1.2:5001 Buffer Size : 8192; Alignment: 16384/0 TCP_NODELAY : DISABLED (0) Connect : Connected to 10.0.1.2:5001 Send Mode : Send Pattern; Number of Buffers: 122070 Statistics : TCP -> 10.0.1.2:5001 999997440 bytes in 3818.20 real seconds = 2.00 Mbit/sec +++ numCalls: 122070; msec/call: 32.03; calls/sec: 31.97Из этого пункта видно, что при отсутствии аппаратного шифрования узким местом является Cisco 2801. 3) Hardware - Software a) Cisco 2801 hardware IPSec + Cisco 871w software IPSec:
c871w#sh proc cpu h CPU% per second (last 60 seconds) 11111111111111111111111111111111111 999999900000000000000000000000000000000000 5 66667660000000000000000000000000000000000012 100 *#**##*##################################* 90 *########################################* 80 #########################################* 70 #########################################* 60 #########################################* 50 #########################################* * 40 #########################################* * 30 #########################################* * 20 ########################################## * 10 ########################################## * 0. 5. 1. 1. 2. 2. 3. 3. 4. 4. 5. 5. 0 5 0 5 0 5 0 5 0 5 CPU% per minute (last 60 minutes) * = maximum CPU% # = average CPU%C1801w#sh proc cpu h 122222222222222222222222222222222222222222222222 8 90000003667676668765765775577777686555555655555557 100 90 * 80 * 70 * 60 * 50 * 40 * 30 **************************************** * 20 *##############################################* * 10 ################################################*# 0. 5. 1. 1. 2. 2. 3. 3. 4. 4. 5. 5. 0 5 0 5 0 5 0 5 0 5 CPU% per minute (last 60 minutes) * = maximum CPU% # = average CPU%Поток recieve
c:\ttcp>PCATTCP.exe -r -f m PCAUSA Test TCP Utility V2.01.01.08 TCP Receive Test Local Host : host-1 ************** Listening. On port 5001 Accept : TCP Поток transmitc:\ttcp>PCATTCP.exe -t -f m -n 122070 10.0.2.2 PCAUSA Test TCP Utility V2.01.01.08 TCP Transmit Test Transmit : TCP -> 10.0.2.2:5001 Buffer Size : 8192; Alignment: 16384/0 TCP_NODELAY : DISABLED (0) Connect : Connected to 10.0.2.2:5001 Send Mode : Send Pattern; Number of Buffers: 122070 Statistics : TCP -> 10.0.2.2:5001 999997440 bytes in 2370.86 real seconds = 3.22 Mbit/sec +++ numCalls: 122070; msec/call: 19.89; calls/sec: 51.49b) Cisco 2801 hardware IPSec + Cisco 1801w software IPSec:
c1801w#sh proc cpu h CPU% per second (last 60 seconds) 1111111111111111111 78878980000000000000000000 9 269501000000000000000000002 0 100 *#################* 90 ** * ################### * 80 ##**#*################### * 70 *######################### * 60 *######################### * 50 *######################### * 40 *######################### * 30 *######################### * 20 *######################### * 10 ########################### # 0. 5. 1. 1. 2. 2. 3. 3. 4. 4. 5. 5. 0 5 0 5 0 5 0 5 0 5 CPU% per minute (last 60 minutes) * = maximum CPU% # = average CPU%c2801#sh proc cpu h 1222234444444444444444444444 8 8996323665666666467676666672 7 100 90 * 80 * 70 * 60 * 50 ********* ******#*** * 40 *####################* * 30 *** **####################* * 20 *##########################* * 10 ###########################* # 0. 5. 1. 1. 2. 2. 3. 3. 4. 4. 5. 5. 0 5 0 5 0 5 0 5 0 5 CPU% per minute (last 60 minutes) * = maximum CPU% # = average CPU%Поток recieve
c:\ttcp>PCATTCP.exe -r -f m PCAUSA Test TCP Utility V2.01.01.08 TCP Receive Test Local Host : host-1 ************** Listening. On port 5001 Accept : TCP Поток transmitc:\ttcp>PCATTCP.exe -t -f m -n 122070 10.0.1.2 PCAUSA Test TCP Utility V2.01.01.08 TCP Transmit Test Transmit : TCP -> 10.0.1.2:5001 Buffer Size : 8192; Alignment: 16384/0 TCP_NODELAY : DISABLED (0) Connect : Connected to 10.0.1.2:5001 Send Mode : Send Pattern; Number of Buffers: 122070 Statistics : TCP -> 10.0.1.2:5001 999997440 bytes in 1605.27 real seconds = 4.75 Mbit/sec +++ numCalls: 122070; msec/call: 13.47; calls/sec: 76.04Исследование утечек памяти в Go с помощью pprof
В Go непросто получить полный дамп памяти, из-за чего сложно найти утечки. Рассмотрим, как это сделать с помощью pprof на примере реального проекта.
Я работал с Go достаточно долго, внедряя масштабируемую блокчейн-инфраструктуру в Orbs. Мы выбрали Go из-за развитого сообщества и отличного набора инструментов.
На последних стадиях разработки могут возникнуть проблемы, связанные с производительностью, в частности утечки памяти. Мы нашли такую и в нашей системе. В этой статье я расскажу, как исследовать утечку памяти в Go, описав шаги, которые мы предприняли для её поиска.
Набор инструментов Golang имеет свои ограничения, и самое большое из них — невозможность исследовать полные дампы памяти. Полный дамп памяти — это содержимое памяти, занятое процессом, выполняющим программу.
Отображение памяти можно представить в виде дерева. Проход по этому дереву проведёт вас через различные размещения объектов в памяти. Всё, что находится в корне дерева, удерживает память от очистки сборщиком мусора. В Go нет простого способа проанализировать дамп, поэтому сложно добраться до корней объекта, который не очищается как мусор.
На момент написания статьи в Интернете не удалось найти какой-либо способ, который помог бы найти корневой объект, препятствующий освобождению памяти. Поскольку у дампов памяти существует формат, и есть достаточно простой способ экспортировать его из отладочного пакета, вероятно, есть хотя бы один подобный инструмент, который используется в Google. Судя по тому, что можно найти в сети, для Go планируется разработать инструмент для просмотра дампов памяти, но не похоже, чтобы кто-то над этим работал.
Утечки памяти
Утечки памяти (или давление памяти) могут принимать разные формы. Обычно мы считаем их багами, но истинная причина возникновения может крыться ещё на стадии проектирования.
Важно построить систему таким образом, чтобы избежать преждевременных оптимизаций и позволить выполнять их позже по мере развития кода, а не перегружать его с самого начала. Некоторые распространённые примеры возникновения проблем с памятью:
- слишком большое количество выделений памяти, неверное представление данных;
- интенсивное использование рефлексии или строк;
- использование глобальных переменных;
- «осиротевшие», бесконечные горутины.
Самый простой способ создать утечку памяти в Go — определить глобальную переменную, массив, и добавить в него данные.
Golang предлагает инструмент с именем pprof . Он может помочь обнаружить проблемы с памятью. Он также может быть использован при обнаружении проблем в работе процессора.
pprof создаёт файл дампа, в который кладёт сэмпл кучи. Этот файл можно потом проанализировать/визуализировать, чтобы получить карту:
- текущего выделения памяти;
- общего (накопительного) выделения памяти.
У инструмента есть возможность сравнивать снимки, сделанные в разное время. Это может быть полезно при стрессовых сценариях для определения проблемных областей кода.
Профили pprof
pprof работает с использованием профилей.
Профиль — это набор трассировок стека, показывающих последовательности вызовов, которые привели к появлению определённого события, например к выделению памяти.
Файл runtime/pprof/pprof.go содержит подробную информацию и реализацию профилей.
Go имеет несколько встроенных профилей, которые можно использовать в обычных случаях:
- goroutine — следы всех текущих горутин;
- heap — выборка выделений памяти живых объектов;
- allocs — выборка всех прошлых выделений памяти;
- threadcreate — следы стека, которые привели к созданию новых потоков в операционной системе;
- block — следы стека, которые привели к блокировке примитивов синхронизации;
- mutex — следы стека держателей конфликтующих мьютексов.
Профиль allocs идентичен heap в отношении сбора данных. Разница заключается в том, как pprof читает во время запуска. Allocs запустит pprof в режиме, который отображает общее количество байтов, выделенных с момента запуска программы (включая байты, являющиеся мусором). Нам нужно знать выделение памяти по каждому объекту отдельно, поэтому сосредоточимся на профиле heap .
Heap
Heap (куча) — это абстрактное представление места, где операционная система хранит объекты, которые использует код. Впоследствии эта память очищается сборщиком мусора или освобождается вручную в языках программирования без сборки мусора.
Куча — не единственное место, где происходит выделение памяти. Часть также выделяется на стеке. Его цель — быстрый доступ к памяти. В Go стек обычно используется для присвоений, которые происходят в рамках функции. Другой момент, где Go использует стек, — когда компилятор «знает», сколько памяти необходимо зарезервировать перед выполнением (например для массивов фиксированного размера).
Данные кучи должны быть освобождены с использованием сборки мусора, в то время как данные стека — нет. Поэтому гораздо эффективнее использовать стек там, где это возможно.
Получение данных кучи с помощью pprof
Есть два основных способа полученить данные. Первый обычно используют в качестве части теста, и он включает импорт runtime/pprof и затем вызов pprof.WriteHeapProfile(some_file) для записи информации в кучу.
// Функция lookup() берёт профиль namepprof.Lookup("heap").WriteTo(some_file, 0)
WriteHeapProfile() существует для обратной совместимости. Остальные профили не имеют таких возможностей, и вы должны использовать функцию Lookup() , чтобы получить данные профилей.
Второй, более интересный способ — пустить его через HTTP (по веб-адресу). Это позволит извлекать конкретные данные из запущенного контейнера в тестовой или e2e-среде или даже из продакшна. Всю документацию пакета pprof можно не читать, но как его включить, следует знать.
import ( "net/http" _ "net/http/pprof" ) . func main()
«Побочным эффектом» импорта net/http/pprof является регистрация конечных адресов на веб-сервере в корневом каталоге /debug/pprof . Используя curl , можно получить файлы с информацией для анализа.
$ curl -sK -v http://localhost:8080/debug/pprof/heap > heap.out
Добавление http.ListenAndServe() в примере выше требуется только в случае, если ваша программа ранее не имела прослушивателя HTTP-сервера. Существуют также способы настроить его с помощью ServeMux.HandleFunc() , который понятнее для более сложной программы с поддержкой HTTP.
Использование pprof
Есть две основные стратегии анализа памяти с помощью pprof . Одна из них называется inuse и заключается в рассмотрении текущих выделений памяти (байтов или количества объектов). Другая носит название alloc и заключается в просматривании всех выделенных байтов или количества объектов во время выполнения программы.
Профиль heap является выборкой выделения памяти. «За кулисами» pprof использует функцию runtime.MemProfile() , которая по умолчанию собирает информацию о предоставлении памяти на каждые 512 КБ выделенных байтов. Можно изменить MemProfile() для сбора информации обо всех объектах, но скорее всего это замедлит работу приложения.
Как только файл профиля собран, пришло время загрузить его в интерактивную консоль pprof .
$ go tool pprof heap.out
Посмотрим на отображаемую информацию:
Type: inuse_space Time: Jan 22, 2019 at 1:08pm (IST) Entering interactive mode (type "help" for commands, "o" for options) (pprof)
Здесь важно отметить Type: inuse_space . Мы смотрим на данные выделения памяти в определённый момент (когда мы захватили профиль). Тип является значением конфигурации sample_index , а возможными значениями могут быть:
- inuse_space — объём выделенной и ещё не освобождённой памяти;
- inuse_object s — количество выделенных и ещё не освобождённых объектов;
- alloc_space — общий объём выделенной памяти (независимо от освобождённой);
- alloc_objects — общее количество выделенных объектов (независимо от освобождённых).
Теперь введите top в интерактивной консоли, и на выводе будут главные потребители памяти.
Можно увидеть строку, показывающую Dropped Nodes (сброшенные узлы). Узел — это выделение объекта или «узел» в дереве. Удаление узлов — хорошая идея, чтобы уменьшить количество мусора, но иногда это может скрывать основную причину утечек памяти.
Если хотите включить все данные профиля, добавьте опцию -nodefraction=0 при запуске pprof или введите nodefraction=0 в интерактивной консоли.
В выводимом списке можно увидеть два значения — flat и cum .
- flat означает, что память выделена функцией и удерживается ей;
- cum означает, что память выделена функцией или функцией, которая была вызвана стеком.
Этой информации может быть достаточно, чтобы понять, есть ли проблема. Например, функция отвечает за выделение большого объёма памяти, но не удерживает её. Это значит, что какой-то другой объект указывает на эту память и удерживает её, то есть может возникнуть утечка памяти или баг.
Команда top в интерактивной консоли по умолчанию выводит первые 10 позиций потребителей памяти. Но эта команда поддерживает формат topN , где N — количество записей, которые вы хотите увидеть. Например, при наборе top70 , будут выведены все узлы.
Графическое представление потоков выделения памяти
Команда topN предоставляет текстовый список, но есть несколько полезных опций для визуального представления, которые есть в pprof . Можно использовать .png или .gif и многое другое (полный список можно увидеть по команде go tool pprof -help ).
В нашей системе визуализация по умолчанию выглядит примерно так:
Это визуализация потоков выделения памяти в программе согласно трассировкам стека. Прочитать график не так сложно, как кажется. Белый квадрат с номером показывает выделенное пространство и совокупный объём памяти, который он занимает прямо сейчас. А каждый более широкий прямоугольник показывает выделившую память функцию.
Стоит отметить, что png-изображение выше было снято в режиме inuse_space . Ещё обратите внимание на inuse_objects , это также может помочь в поиске проблем с выделением.
Копаем глубже, чтобы найти первопричину
В нашем случае membuffers (библиотека сериализации данных) удерживает память. Но это не значит, что обязательно есть утечка в сегменте кода. Это значит, что память удерживается функцией. Важно понимать, как читать граф и вывод pprof в целом. В случае сериализации данных выделяется память для структур и примитивных объектов (int, string) и никогда не освобождается.
Неверно истолковав график, можно предположить, что один из узлов на пути к сериализации отвечает за сохранение памяти, например:
Где-то в цепочке можно увидеть библиотеку логирования, занимающую > 50 Мб выделенной памяти. Это память, которая выделяется функциями. Логгер в процессе своей работы вызывает выделение памяти, поскольку ему необходимо сериализовать данные для вывода их в журнал.
Из графа также видно, что память удерживается только сериализацией и больше ничем. Объём памяти самого логгера составляет около 30 % от общего объёма. Это значит, что проблема не в писателе. Он регистрирует что-то, чего не должно быть. А значит, утечка памяти не в журнале логов.
Знакомьтесь с командой list . Она принимает регулярное выражение, которое будет фильтровать то, что надо отобразить. Список (list) в действительности представляет собой исходный код с комментариями, относящийся к выделению. В контексте изучаемого логгера выполним list RequestNew , чтобы увидеть вызовы, сделанные в регистраторе. Эти вызовы поступают из двух функций, которые начинаются с одного и того же префикса.
Выделения памяти находятся в столбце cum . Это значит, что выделенная память сохраняется в стеке вызовов. Это соответствует тому, что показывает график. Причина выделения памяти писателем заключается в том, что мы отправили ему весь «блокирующий» объект. Нужно было как минимум сериализовать некоторые его части.
List может найти исходный код, если искать его в среде GOPATH . В случаях, когда корневой объект не совпадает (зависит от вашего сборщика), вы можете использовать опцию -trim_path . Она поможет исправить код и позволит увидеть аннотированный исходный код. Не забудьте установить свой Git на правильный коммит, который работал во время захвата профиля heap.
Так почему память удерживается?
В случае с Java или .Net можно использовать какой-нибудь анализатор корневых объектов и добраться до объекта, который создаёт утечку. Но с Go это невозможно из-за проблем со встроенными инструментами и из-за низкоуровневого представления памяти.
Не вдаваясь в детали, мы не думаем, что Go запоминает, какой объект по какому адресу хранится (за исключением, возможно, указателей). Для понимания, по какому адресу памяти хранится член объекта (структуры), потребуется карта вывода из профиля heap . Значит, перед захватом полного дампа ядра следует также захватить профиль heap , чтобы адреса могли быть сопоставлены с выделившими память строкой и файлом, а следовательно и объектом, представленным в памяти.
Установив значение nodefraction=0 , можно увидеть всю карту выделенных объектов, включая самые маленькие.
У нас есть два новых поддерева. Более длинное новое дерево зеленого цвета, которое полностью отсоединено от остальной системы, является тестовым прогоном, оно нам не интересно.
Небольшое поддерево синего цвета, соединённое ребром со всей системой, — это inMemoryBlockPersistance . Это бэкенд, который хранит все данные в памяти, но не сохраняет их на диске. Можно сразу увидеть, что в нём находятся два больших объекта. Два — потому что размер объекта составляет 1,28 Мб, а функция сохраняет 2,57 Мб, то есть в два раза больше.
Теперь проблема отчётливо ясна. Можно использовать отладчик и увидеть, что всему виной массив, который удерживает все блоки для постоянства памяти.
Что можно исправить?
Десериализованные данные занимали слишком много памяти. Откуда взялось 142 Мб для чего-то, что должно занимать существенно меньше памяти? Здесь может помочь pprof — он существует именно для того, чтобы точно отвечать на такие вопросы.
Чтобы просмотреть исходный код функции, запустим lazyCalcOffsets() . Теперь можем увидеть, что flat и cum одинаковы. Это указывает на то, что выделенная память также сохраняется этими точками выделения. Функция make() тоже занимает немного памяти, т. к. это указатель на структуру данных. Ещё можно увидеть, что занимает память выделение в строке 43.
Следует отметить, что функция make() в Go позволяет делать не только отображения, но и срезы. Присвоение отображению не то же самое, что присвоение простой переменной — использование переменных предполагает большие издержки ресурсов. Чем больше элементов, тем больше будут эти издержки по сравнению со срезом.
При использовании map[int]T когда данные не редки или могут быть преобразованы в последовательные индексы и потребление памяти является важным фактором, для большей эффективности следует использовать срез. Однако большой срез при расширении данных может замедлить операцию, в то время как для отображения это замедление будет незначительным. Как вы уже поняли, не существует волшебной формулы для оптимизации.
В нашей системе мы теперь используем срез вместо отображения. Из-за способа получения данных и того, как мы получаем к ним доступ, кроме пары строк и структуры данных, никаких других изменений кода не потребовалось. Посмотрим, как это повлияло на потребление памяти.
Взглянем на benchcmp для пары тестов.
Тесты на чтение инициализируют структуру данных, которая создаёт выделения. Время выполнения улучшилось на ~30 %, выделение сократилось на 50 %, а потребление памяти > 90 %.
Поскольку отображение (теперь уже срез) никогда не было заполнено большим количеством элементов, цифры показывают то, что мы увидим в продакшене. Результат зависит от энтропии данных, но могут быть случаи, когда улучшение как выделения, так и потребления памяти было бы ещё больше.
Ещё раз задействовав pprof и захватив профиль heap из того же теста, можно увидеть, что теперь потребление памяти фактически сократилось на ~90 %.
Вывод прост — для небольших наборов данных не следует использовать отображения, достаточно срезов. Отображения имеют большие издержки.
Полный дамп памяти
Именно здесь можно наблюдать самое большое ограничение инструментов Go. Этот язык развивается большими темпами, но это развитие имеет свою цену в случае полного дампа и выделения памяти. Формат полного дампа кучи по мере своих обновлений является обратно не совместимым. Помните это, когда будете использовать последнюю версию. Для записи полного дампа кучи вы можете использовать debug.WriteHeapDump() .
Следует также отметить, что не существует хорошего решения для изучения полных дампов. Вот некоторые вещи, которые стоит игнорировать, если собираетесь попробовать открыть полный дамп самостоятельно, начиная с Go 1.11:
- В macOS нет способа открыть и отладить полный дамп ядра, это работает только в Linux.
- Инструменты в этом репозитории предназначены для Go 1.3. Существует форк для 1.7+, но он также не работает должным образом (не полностью).
- ViewCore из репозитория Go на самом деле не компилируется. Это достаточно легко исправить, указав внутренние пакеты на golang.org вместо github.com. Но это также не работает на macOS и может быть работает на Linux.
- Также corelib не работает на macOS.
Ещё одна важная деталь о pprof — это его интерфейс. Он может сэкономить много времени при исследовании проблем профилей, созданных с помощью pprof .
Check heaps что за процесс
PostgreSQL имеет возможность отслеживать выполнение определённых команд. В настоящее время такое отслеживание поддерживает только команда VACUUM , но в будущем сфера его применения может быть расширена.
28.4.1. Отслеживание выполнения VACUUM
Во время выполнения VACUUM представление pg_stat_progress_vacuum будет содержать по одной строке для каждого обслуживающего процесса (включая рабочие процессы автоочистки), производящего очистку. Таблицы ниже показывают, какая информация будет отслеживаться, и рассказывают, как её интерпретировать. В настоящее время отслеживание выполнения не поддерживается для команды VACUUM FULL , так что процессы, выполняющие VACUUM FULL , не будут видны в этом представлении.
Таблица 28.20. Представление pg_stat_progress_vacuum
| Столбец | Тип | Описание |
|---|---|---|
| pid | integer | Идентификатор (PID) обслуживающего процесса |
| datid | oid | OID базы данных, к которой подключён этот обслуживающий процесс. |
| datname | name | Имя базы данных, к которой подключён этот обслуживающий процесс. |
| relid | oid | OID очищаемой таблицы. |
| phase | text | Текущая фаза очистки. См. Таблицу 28.21. |
| heap_blks_total | bigint | Общее число блоков кучи в таблице. Это число отражает состояние в начале сканирования; блоки, добавленные позже, не будут (и не должны) обрабатываться текущей командой VACUUM . |
| heap_blks_scanned | bigint | Число просканированных блоков кучи. Так как для оптимизации сканирования применяется карта видимости, некоторые блоки могут пропускаться без осмотра; пропущенные блоки входят в это общее число, так что по завершении очистки это число станет равно heap_blks_total . Этот счётчик увеличивается только в фазе scanning heap . |
| heap_blks_vacuumed | bigint | Число очищенных блоков кучи. Если в таблице нет индексов, этот счётчик увеличивается только в фазе vacuuming heap (очистка кучи). Блоки, не содержащие «мёртвых» кортежей, при этом пропускаются, так что этот счётчик иногда может увеличиваться резкими рывками. |
| index_vacuum_count | bigint | Количество завершённых циклов очистки индекса. |
| max_dead_tuples | bigint | Число «мёртвых» кортежей, которое мы можем сохранить, прежде чем потребуется выполнить цикл очистки индекса, в зависимости от maintenance_work_mem. |
| num_dead_tuples | bigint | Число «мёртвых» кортежей, собранных со времени последнего цикла очистки индекса. |
Таблица 28.21. Фазы VACUUM
| Фаза | Описание |
|---|---|
| initializing | Инициализация — VACUUM готовится начать сканирование кучи. Эта фаза должна быть очень быстрой. |
| scanning heap | Сканирование кучи — VACUUM в настоящее время сканирует кучу. При этом будет очищена и, если требуется, дефрагментирована каждая страница, а возможно, также будет произведена заморозка. Отслеживать процесс сканирования можно, следя за содержимым столбца heap_blks_scanned . |
| vacuuming indexes | Очистка индексов — VACUUM в настоящее время очищает индексы. Если у таблицы есть какие-либо индексы, эта фаза будет наблюдаться минимум единожды в процессе очистки, после того, как куча будет просканирована полностью. Она может повторяться несколько раз в процессе очистки, если объёма maintenance_work_mem (или, в случае автоочистки, autovacuum_work_mem, если он задан) оказывается недостаточно для сохранения всех найденных «мёртвых» кортежей. |
| vacuuming heap | Очистка кучи — VACUUM в настоящее время очищает кучу. Очистка кучи отличается от сканирования, так как она происходит после каждой операции очистки индексов. Если heap_blks_scanned меньше чем heap_blks_total , система вернётся к сканированию кучи после завершения этой фазы; в противном случае она начнёт уборку индексов. |
| cleaning up indexes | Уборка индексов — VACUUM в настоящее время производит уборку в индексах. Это происходит после завершения полного сканирования кучи и очистки индексов и кучи. |
| truncating heap | Усечение кучи — VACUUM в настоящее время усекает кучу, чтобы возвратить операционной системе объём пустых страниц в конце отношения. Это происходит после уборки индексов. |
| performing final cleanup | Выполнение окончательной очистки — VACUUM выполняет окончательную очистку. На этой стадии VACUUM очищает карту свободного пространства, обновляет статистику в pg_class и передаёт статистику сборщику статистики, После этой фазы VACUUM завершит свою работу. |
| Пред. | Наверх | След. |
| 28.3. Просмотр информации о блокировках | Начало | 28.5. Динамическая трассировка |