swapoff นั้นจะช้าได้อย่างไร?


77

อย่างใดฉันเกิดขึ้นเพื่อสลับหน่วยความจำ 14 GB หลังจากฆ่าผู้กระทำความผิดฉันมีหน่วยความจำว่างอีกครั้งดังนั้นฉันจึงคิดว่าฉันสามารถนำข้อมูลสำคัญอีกครั้ง ดังนั้นด้วยการใช้ 5 GB จาก 32 GB และใช้พื้นที่ swap 14 GB ฉันจึงวิ่งswapoff -a.... และ 4 ชั่วโมงต่อมาประมาณครึ่งหนึ่งของงานก็เสร็จ

ซึ่งหมายความว่าน้อยกว่า 1 MB / s ในขณะที่ฉันสามารถคัดลอก 200 MB / s swap ของฉันถูกเข้ารหัส แต่เช่นเดียวกับทุกพาร์ติชันปกติและด้วยaes-niมันทำให้ไม่มีโหลดซีพียูที่สังเกตได้ (และการเติมพื้นที่สว็อปใช้เวลาเพียงไม่กี่นาที) ฉันเห็นว่าไม่มีเหตุผลพิเศษในการเพิ่มประสิทธิภาพswapoffแต่ฉันสงสัยว่ามันจะช้าขนาดนั้นได้อย่างไร


เพียงแค่เพิ่มข้อมูลเพิ่มเติม: หน่วยความจำหลักของฉันคือ 32 GB และฉันมีพื้นที่สว็อป swap ขนาด 32 GB ในแต่ละฮาร์ดดิส 4 ตัว (แน่นอนว่า overkill แต่ใครสนใจล่ะ) พื้นที่สว็อปทั้งหมดสามารถ (ถอดรหัสและ) อ่านในเวลาน้อยกว่า 5 นาที:

time -p sudo sh -c 'for i in /dev/mapper/cryptswap?; do md5sum $i & done; wait'
014a2b7ef300e11094134785e1d882af  /dev/mapper/cryptswap1
a6d8ef09203c1d8d459109ff93b6627c  /dev/mapper/cryptswap4
05aff81f8d276ddf07cf26619726a405  /dev/mapper/cryptswap3
e7f606449327b9a016e88d46049c0c9a  /dev/mapper/cryptswap2
real 264.27

การอ่านส่วนหนึ่งของพาร์ติชั่นต้องไม่ช้ากว่าการอ่านทุกอย่าง แต่การอ่านประมาณ 1 ใน 10 ของมันใช้เวลานานกว่าประมาณ 100 เท่า

ฉันสังเกตว่าระหว่างswapoffซีพียูนั้นส่วนใหญ่ไม่ได้ใช้งาน (อาจจะ 10% ของหนึ่งคอร์) และก็เป็นดิสก์ ("วัด" โดยไฟ LED) ฉันยังเห็นว่าพื้นที่สว็อปถูกปิดหนึ่งครั้ง


1
ฉันสงสัยว่าปรากฏการณ์เดียวกันนี้เกิดขึ้นเมื่อระบบโหลดหน้าเว็บที่เปลี่ยนกลับไปเป็น RAM ด้วยตัวเองหรือไม่? ตัวอย่างเช่นถ้าฉันระบบถูกระงับไปยังดิสก์จากนั้นเริ่มต้นทุกอย่างถูกสลับและมันจะถูกโหลดกลับไปที่ RAM ดูเหมือนว่าจะช้ามากสำหรับฉันเช่นกัน
Petr Pudlák

อุปกรณ์ swap ทั้งหมดเปิดใช้งานโดยมีลำดับความสำคัญเท่ากันหรือไม่
นิลส์

@Petr Pudlák: การระงับไปยังดิสก์นั้นแตกต่างกันเล็กน้อยเพียงแค่เขียนเนื้อหา RAM ลงในพื้นที่ว่างในพื้นที่ swap และสิ่งนี้ (และยกเลิกการระงับ) อาจเร็วกว่ามาก ฉันไม่สามารถลองได้เพราะมันใช้ไม่ได้กับการสลับแบบเข้ารหัส
maaartinus

@ ไม่มี: ใช่ลำดับความสำคัญเท่ากันและเป็นดิสก์และการแบ่งพาร์ติชัน
maaartinus

นั่นทำให้แปลกขึ้น ในกรณีนี้การสลับจะถูกสตริปในดิสก์ทั้งหมด - ซึ่งควรเร็วมาก ไม่iostat -d 5แสดง IO ต่ำบนดิสก์ในระหว่างการswapoffด้วยหรือไม่
นิลส์

คำตอบ:


53

อันดับแรกให้ดูสิ่งที่คุณคาดหวังจากฮาร์ดไดรฟ์ของคุณ ฮาร์ดไดรฟ์ของคุณสามารถทำ 200 MB / s ตามลำดับ เมื่อคุณปัจจัยขอเวลาในการที่จะสามารถมากช้าลง ในการเลือกตัวอย่างโดยพลการดูข้อมูลจำเพาะสำหรับหนึ่งในดิสก์ 3TB อันทันสมัยของ Seagate นั่นคือST3000DM001 :

  • อัตราข้อมูลสูงสุดที่ยั่งยืน: 210 MB / s

  • หาค่าเฉลี่ยอ่าน: <8.5 ms

  • จำนวนไบต์ต่อเซ็กเตอร์: 4,096

หากคุณไม่ต้องการค้นหาและหากการแลกเปลี่ยนของคุณอยู่ใกล้กับขอบของดิสก์คุณสามารถคาดหวังได้ถึงอัตราสูงสุด = 210 MB / s

แต่ถ้าข้อมูลสว็อปของคุณมีการแยกส่วนอย่างสิ้นเชิงในสถานการณ์กรณีที่เลวร้ายที่สุดคุณจะต้องค้นหาทุกภาคส่วนที่คุณอ่าน นั่นหมายความว่าคุณจะได้รับการอ่าน 4 KB ทุก ๆ 8.5 มิลลิวินาทีหรือ 4 KB / 0.0085 = 470 KB / s

ดังนั้นขวาปิดค้างคาวก็ไม่นึกไม่ถึงว่าคุณอยู่ในความเป็นจริงการทำงานขึ้นกับความเร็วในฮาร์ดไดรฟ์


ที่กล่าวว่าดูเหมือนโง่ที่swapoffจะทำงานช้าและต้องอ่านหน้าตามลำดับโดยเฉพาะหากพวกเขาเขียนได้อย่างรวดเร็ว (ซึ่งหมายถึงตามลำดับ) แต่นั่นอาจเป็นวิธีที่เคอร์เนลทำงาน รายงานข้อผิดพลาดของ Ubuntu # 486666กล่าวถึงปัญหาเดียวกัน:

The swap is being removed at speed of 0.5 MB/s, while the
hard drive speed is 60 MB/s;
No other programs are using harddrive a lot, system is not under
high load etc.

Ubuntu 9.10 on quad core.

Swap partition is encrypted.
Top (atop) shows near 100% hard drive usage
  DSK | sdc | busy 88% | read 56 | write 0 | avio 9 ms |
but the device transfer is low (kdesysguard)
  0.4 MiB/s on /dev/sdc reads, and 0 on writes

หนึ่งในคำตอบคือ:

It takes a long time to sort out because it has to rearrange and flush the
memory, as well as go through multiple decrypt cycles, etc. This is quite
normal

รายงานข้อผิดพลาดปิดไม่ได้รับการแก้ไข

หนังสือของ Mel Gorman "การทำความเข้าใจกับ Linux Virtual Memory Manager " ค่อนข้างล้าสมัย แต่ยอมรับว่านี่เป็นการทำงานที่ช้า:

sys_swapoff()ฟังก์ชั่นความรับผิดชอบในการปิดใช้งานในพื้นที่ให้มีการคาดการณ์มากพอที่เรียกว่า ฟังก์ชั่นนี้เกี่ยวข้องกับการอัพเดตเป็นswap_info_structหลัก งานที่สำคัญของเพจในแต่ละหน้าเพจออกเป็นความรับผิดชอบของtry_to_unuse()ซึ่งเป็น อย่างมากที่มีราคาแพง

มีการพูดคุยเพิ่มเติมเล็กน้อยจากปี 2550 ในรายชื่อส่งเมล linux-kernel ที่มีหัวเรื่อง " speeding up swapoff " - แม้ว่าความเร็วที่พวกเขาพูดถึงจะสูงกว่าสิ่งที่คุณเห็นอยู่เล็กน้อย


เป็นคำถามที่น่าสนใจที่อาจถูกเพิกเฉยเนื่องจากswapoffไม่ค่อยได้ใช้ ผมคิดว่าถ้าคุณอยากจะติดตามลงขั้นตอนแรกจะได้รับการพยายามที่จะดูรูปแบบการใช้ดิสก์ของคุณอย่างระมัดระวังมากขึ้น (อาจจะมีatop, iostatหรือแม้กระทั่งเครื่องมือที่มีประสิทธิภาพมากขึ้นเช่นperfหรือsystemtap) สิ่งที่มองหาอาจเป็นการแสวงหาที่มากเกินไปการทำงานของ I / O ขนาดเล็กการเขียนซ้ำอย่างต่อเนื่องและการเคลื่อนย้ายข้อมูลเป็นต้น


5
คำอธิบายที่ยอดเยี่ยม ควรสังเกตว่าเป็นไปได้ที่จะหลีกเลี่ยงการแยกส่วนใหญ่และเพิ่มการแลกเปลี่ยนส่วนใหญ่ได้อย่างรวดเร็วโดยการทิ้งการคอร์ส่วนใหญ่ของหน่วยความจำที่สลับเปลี่ยน: unix.stackexchange.com/questions/254202/
Brandon DuPree

มันไม่ใช่แค่การแยกส่วน / แสวงหาเวลา swap ของฉันอยู่บน SSD และการอ่านแบบสุ่มนั้นเร็วมาก แต่คำสั่ง swapoff นั้นช้ากว่าที่ควรและโหลด SSD ของฉันจะอยู่ที่ประมาณ 1% util ฉันสงสัยว่ามีบางคนที่เกี่ยวข้องกับ list-walking ในเคอร์เนลหรือใน swapoff (ซึ่งใช้ CPU ประมาณ 90-100%) แน่นอนถ้างานทั้งหมดทำตามลำดับและดิสก์ค้นหาช้าเกินไปก็สามารถเพิ่มขึ้นอย่างมาก
Thomas Guyot-Sionnest

33

ฉันพบปัญหาเดียวกันกับแล็ปท็อปของฉันที่มี SSD ดังนั้นการค้นหาเวลาไม่ควรเป็นปัญหา

ฉันพบคำอธิบายอื่น นี่คือข้อความที่ตัดตอนมา

วิธีการทำงานในขณะนี้ swapoff จะดูที่แต่ละหน้าหน่วยความจำที่ถูกสลับใน swap partition และพยายามค้นหาโปรแกรมทั้งหมดที่ใช้งาน หากไม่พบพวกเขาทันทีมันจะดูตารางหน้าของทุกโปรแกรมที่กำลังเรียกใช้เพื่อค้นหา ในกรณีที่เลวร้ายที่สุดมันจะตรวจสอบตารางหน้าทั้งหมดสำหรับทุกหน้าสลับในพาร์ติชัน ถูกต้อง - หน้าตารางเดียวกันถูกตรวจสอบซ้ำแล้วซ้ำอีก

ดังนั้นจึงเป็นปัญหาเคอร์เนลมากกว่าสิ่งอื่นใด


ไม่ไม่ใช่ปัญหาเคอร์เนล IMHO มันเป็นวิธีswapoffการใช้งาน เมื่อสลับกระบวนการออกจะใช้เวลาไม่นาน
Marki555

15
มันเป็นปัญหาของการใช้ swapoff ซึ่งอยู่ในเคอร์เนล - ดังนั้นจึงเป็นปัญหาของเคอร์เนล! คุณสามารถดูว่าคุณstrace swapoffสวยมากเพียงใดเรียกว่าการเรียกของswapoffระบบ
Nick Craig-Wood

1
ฉันมีเซิร์ฟเวอร์ที่มี 48GB RAM (32 คะแนน) มีการแลกเปลี่ยนข้อผิดพลาด 6 GB ฟรีที่ใช้ 0.7GB swappiness = 10 พยายามทำให้เป็น 0 และลองสลับกันเพื่อดูว่าเกิดอะไรขึ้น swapoff ใช้เวลานาน 30 นาทีอาจปล่อยการแลกเปลี่ยนช้ามาก ฉันมี SSD ภายใต้แทบไม่มีโหลดและ CPU คล้ายกันคาดว่ากระบวนการ swapoff ซึ่งใช้ CPU หนึ่งตัว 100%
โซริน

1
มันเป็นปัญหาของการใช้ swapoff (ในเคอร์เนล) มีการพูดคุยเกี่ยวกับวิธีการที่ดีขึ้นมากเมื่อไม่กี่ปีที่ผ่านมาใน kernel-dev แต่พวกเขาบอกว่ามันเป็นเรื่องมุมและไม่ต้องการความพยายามในการเปลี่ยนแปลง
Marki555

7
บนเซิร์ฟเวอร์ที่มี 1 TB RAM (ใช่ TB) และการสลับ 2 GB (ความต้องการของ SAP ที่ไม่มีประสิทธิภาพ) ใช้เวลา 12 ชั่วโมงในการฟรี 5% ของ 2 GB นั้น (กับ 1 cpu core ที่ 100%)
Marki555

22

ใช่swapoffกลไกไม่มีประสิทธิภาพอย่างน่ากลัว วิธีแก้ปัญหาง่าย ๆ : วนซ้ำกระบวนการแทนที่จะวนซ้ำหน้าที่สลับ ใช้สคริปต์ python นี้ (ฉันไม่ได้เข้าร่วม):

git clone https://github.com/wiedemannc/deswappify-auto

โปรดทราบว่าโหมดการทำงานของ daemon นั้นใช้สำหรับเดสก์ท็อป / แล็ปท็อปที่มักจะจำศีล ฉันจะไม่เรียกใช้เป็น daemon ในระบบเซิร์ฟเวอร์ - เพียงรันในโหมดเบื้องหน้ารอจนกว่าจะรายงานว่าจัดการกระบวนการบางอย่างจากนั้นหยุดและลอง:

swapoff /dev/x

เนื่องจากหน้าเว็บส่วนใหญ่มีอยู่ทั้งในการสลับและในหน่วยความจำswapoffจึงมีน้อยมากที่ต้องทำและควรจะเร็วอย่างเห็นได้ชัด (ฉันเห็นหลายร้อย MB / s)

ส่วนประวัติล่วงหน้า

สคริปต์หลามดังกล่าวจะขึ้นอยู่กับส่วนที่เหลือของคำตอบนี้ซึ่งในทางกลับกันการปรับปรุงของฉันคำตอบที่เก่ากว่านี้ประพันธ์โดยjlong เนื่องจากสคริปต์มีความปลอดภัยมากขึ้นฉันแนะนำให้ลองใช้คำตอบที่เหลือในฐานะบรรทัดสุดท้ายของการป้องกัน :

perl -we 'for(`ps -e -o pid,args`) { if(m/^ *(\d+) *(.{0,40})/) { $pid=$1; $desc=$2; if(open F, "/proc/$pid/smaps") { while(<F>) { if(m/^([0-9a-f]+)-([0-9a-f]+) /si){ $start_adr=$1; $end_adr=$2; }  elsif(m/^Swap:\s*(\d\d+) *kB/s){ print "SSIZE=$1_kB\t gdb --batch --pid $pid -ex \"dump memory /dev/null 0x$start_adr 0x$end_adr\"\t2>&1 >/dev/null |grep -v debug\t### $desc \n" }}}}}' | sort -Vr | head

นี้ทำงานอาจจะ 2 วินาทีและจะไม่จริงทำอะไรเพียงรายการด้านบนส่วนหน่วยความจำ 10 (ที่จริงมันพิมพ์มากขึ้นหนึ่งสมุทร; ใช่ฉันไม่รักหนึ่งสมุทรเพียงแค่ตรวจสอบคำสั่งที่ยอมรับความเสี่ยงในการคัดลอกและวางลงใน เปลือกของคุณสิ่งเหล่านี้จะอ่านจากการสลับ)

...Paste the generated one-liners...
swapoff /your/swap    # much faster now

สายการบินหลักตัวหนึ่งมีความปลอดภัย (สำหรับฉัน) ยกเว้นว่าจะอ่าน / proc จำนวนมาก

ที่คำสั่งย่อยจัดทำคู่มือสำหรับการตรวจสอบของคุณจะไม่ปลอดภัย แต่ละคำสั่งจะหยุดกระบวนการหนึ่งช่วงระยะเวลาของการอ่านส่วนหน่วยความจำจากการสลับ ดังนั้นจึงไม่ปลอดภัยกับกระบวนการที่ไม่ยอมให้หยุดทำงานชั่วคราว ความเร็วในการถ่ายโอนที่ฉันเห็นนั้นอยู่ที่ 1 กิกะไบต์ต่อนาที (สคริปต์ไพ ธ อนดังกล่าวลบข้อบกพร่องนั้น)

อันตรายอีกประการหนึ่งคือสร้างแรงกดดันต่อหน่วยความจำมากเกินไปในระบบดังนั้นให้ตรวจสอบกับปกติ free -m

มันทำอะไร?

for(`ps -e -o pid,args`) {

  if(m/^ *(\d+) *(.{0,40})/) { 
    $pid=$1; 
    $desc=$2; 

    if(open F, "/proc/$pid/smaps") { 

      while(<F>) { 

        if(m/^([0-9a-f]+)-([0-9a-f]+) /si){ 
          $start_adr=$1; 
          $end_adr=$2; 
        } elsif( m/^Swap:\s*(\d\d+) *kB/s ){
          print "SSIZE=$1_kB\t gdb --batch --pid $pid -ex \"dump memory /dev/null 0x$start_adr 0x$end_adr\"\t2>&1 >/dev/null |grep -v debug\t### $desc \n" 
        }
      }
    }
  }
}

เอาต์พุตของสคริปต์ Perl นี้คือชุดgdbคำสั่งdump memory (range)ที่เรียกคืนการสลับหน้าไปยังหน่วยความจำ

เอาต์พุตเริ่มต้นด้วยขนาดดังนั้นจึงง่ายพอที่จะผ่านร่อง| sort -Vr | headเพื่อรับเซ็กเมนต์ที่ใหญ่ที่สุด 10 อันดับแรกตามขนาด (SSIZE) -Vยืนสำหรับการเรียงลำดับรุ่นจำนวนที่เหมาะสม แต่การทำงานสำหรับวัตถุประสงค์ของฉัน ฉันไม่สามารถคิดวิธีการเรียงลำดับตัวเลขได้


คุณจะใช้การเรียงลำดับตัวเลขที่นี่กับsort -t = -k 2n
Stéphane Chazelas

9
ดูเหมือนจะไม่จำเป็นต้องใช้ gdb เพื่อสำรวจหน่วยความจำกระบวนการ (อย่างน้อยในเมล็ดล่าสุด) หนึ่งสามารถเปิด/proc/$pid/memค้นหาและอ่านโดยตรง PoC ส่วนใหญ่มาจากตัวอย่างของคุณ: gist.github.com/WGH-/91260f6d65db88be2c847053c49be5aeวิธีนี้ไม่ได้หยุดกระบวนการ AFAIK ไม่ควรมีอันตรายใด ๆ ที่เกิดจากสิ่งนี้
WGH

10

ระหว่าง swapoff หากตรวจพบสล็อต swap ที่ไม่ได้ใช้งานเคอร์เนลจะทำการสลับในหน้านั้นเป็นครั้งแรก ฟังก์ชั่น unuse_process () จากนั้นพยายามค้นหารายการตารางหน้าทั้งหมดที่ตรงกับหน้าเพียงแค่เปลี่ยนหน้าและทำการปรับปรุงที่จำเป็นในตารางหน้า การค้นหาหมดจดและใช้เวลานานมาก: เข้าชมตัวบอกความจำทุกตัว (ของระบบทั้งหมด) และตรวจสอบรายการตารางหน้าของตัวต่อตัว

โปรดดูหน้า 724 ของ "การทำความเข้าใจกับ Linux Kernel เวอร์ชัน 3"

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.