Làm thế nào có thể hoán đổi là chậm?


77

Bằng cách nào đó tôi đã tình cờ trao đổi 14 GB bộ nhớ. Sau khi giết được thủ phạm, tôi lại có hàng tấn bộ nhớ trống, vì vậy tôi nghĩ rằng tôi có thể mang lại dữ liệu quan trọng một lần nữa. Vì vậy, với 5 GB trong số 32 GB được sử dụng và 14 GB dung lượng trao đổi được sử dụng, tôi đã chạy swapoff -a.... và 4 giờ sau đó, khoảng một nửa công việc đã hoàn thành.

Điều này có nghĩa là ít hơn 1 MB / s, trong khi tôi có thể dễ dàng sao chép 200 MB / s. Trao đổi của tôi được mã hóa nhưng tất cả các phân vùng bình thường và với aes-ni, điều đó dẫn đến không có tải CPU đáng chú ý (và lấp đầy không gian trao đổi chỉ mất vài phút). Tôi thấy rằng không có lý do đặc biệt để tối ưu hóa swapoff, tuy nhiên tôi tự hỏi làm thế nào nó có thể chậm như vậy?


Chỉ cần thêm một số dữ liệu: Bộ nhớ chính của tôi là 32 GB và tôi có dung lượng trao đổi 32 GB trên mỗi 4 ổ cứng (chắc chắn là quá mức cần thiết, nhưng ai quan tâm?). Toàn bộ không gian hoán đổi có thể được (giải mã và) đọc trong vòng chưa đầy 5 phút:

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

Đọc một phần của phân vùng không thể chậm hơn đọc tất cả. Tuy nhiên, đọc khoảng 1/10 của nó mất khoảng 100 lần lâu hơn.

Tôi quan sát thấy rằng trong swapoffcả hai CPU hầu hết đều không hoạt động (có thể là 10% của một lõi) và các đĩa ("được đo" bằng đèn LED) cũng vậy. Tôi cũng thấy rằng các không gian hoán đổi đã bị tắt lần lượt.


1
Tôi tự hỏi, liệu hiện tượng tương tự có xảy ra khi hệ thống tải các trang bị tráo đổi trở lại vào RAM không? Ví dụ: nếu hệ thống của tôi bị treo vào đĩa và sau đó khởi động, mọi thứ sẽ được hoán đổi và nó được tải trở lại RAM. Có vẻ là rất chậm với tôi quá.
Petr Pudlák

Có phải tất cả các thiết bị trao đổi được kích hoạt với cùng một ưu tiên?
Nils

@Petr Pudlák: Đình chỉ vào đĩa hơi khác một chút, nó chỉ đơn giản ghi nội dung RAM vào một không gian trống trong khu vực trao đổi, và điều này (và không bị đình chỉ) có lẽ nhanh hơn nhiều. Tôi không thể thử vì nó không hoạt động với trao đổi được mã hóa.
maaartinus

@Nils: Có, mức độ ưu tiên là như nhau và đĩa cũng như phân vùng của chúng cũng vậy.
maaartinus

Điều đó làm cho nó lạ hơn. Trong trường hợp này, trao đổi bị sọc trên tất cả các đĩa - điều này sẽ rất nhanh. Đã iostat -d 5hiển thị IO thấp trên các đĩa trong swapoffquá?
Nils

Câu trả lời:


53

Trước tiên, hãy nhìn vào những gì bạn có thể mong đợi từ ổ cứng của bạn. Ổ cứng của bạn có thể thực hiện tuần tự 200 MB / s . Khi bạn yếu tố tìm kiếm thời gian, nó có thể chậm hơn nhiều . Để chọn một ví dụ tùy ý, hãy xem thông số kỹ thuật cho một trong các đĩa 3TB hiện đại của Seagate, ST3000DM001 :

  • Tốc độ dữ liệu duy trì tối đa: 210 MB / s

  • Tìm kiếm trung bình đọc: <8,5 ms

  • Byte trên mỗi lĩnh vực: 4.096

Nếu bạn không bao giờ cần tìm kiếm và nếu trao đổi của bạn ở gần mép đĩa, bạn có thể thấy tốc độ tối đa = 210 MB / s

Nhưng nếu dữ liệu trao đổi của bạn hoàn toàn bị phân mảnh, trong trường hợp xấu nhất, bạn cần tìm kiếm xung quanh cho mọi lĩnh vực bạn đọc. Điều đó có nghĩa là bạn chỉ có thể đọc 4 KB cứ sau 8,5 ms hoặc 4 KB / 0,0085 = 470 KB / s

Vì vậy, ngay lập tức con dơi, không thể tin được rằng bạn thực sự đang chạy với tốc độ ổ cứng.


Điều đó nói rằng, có vẻ ngớ ngẩn swapoffsẽ chạy rất chậm và phải đọc các trang không theo thứ tự, đặc biệt là nếu chúng được viết nhanh chóng (ngụ ý theo thứ tự). Nhưng đó có thể chỉ là cách thức hoạt động của kernel. Báo cáo lỗi Ubuntu # 486666 thảo luận về cùng một vấn đề:

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

Một trong những câu trả lời là:

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

Báo cáo lỗi đã bị đóng chưa được giải quyết.

Cuốn sách " Tìm hiểu về trình quản lý bộ nhớ ảo Linux " của Mel Gorman có chút lỗi thời, nhưng đồng ý rằng đây là một hoạt động chậm:

Hàm chịu trách nhiệm hủy kích hoạt một khu vực, được dự đoán là đủ, được gọi sys_swapoff(). Chức năng này chủ yếu liên quan đến việc cập nhật swap_info_struct. Nhiệm vụ chủ yếu của phân trang trong mỗi trang paged-out là trách nhiệm của try_to_unuse()mà là cực kỳ tốn kém.

Có thêm một chút thảo luận từ năm 2007 về danh sách gửi thư linux-kernel với chủ đề " tăng tốc trao đổi " - mặc dù tốc độ mà họ đang thảo luận có cao hơn một chút so với những gì bạn đang thấy.


Đó là một câu hỏi thú vị mà có lẽ thường bị bỏ qua, vì swapoffhiếm khi được sử dụng. Tôi nghĩ rằng nếu bạn thực sự muốn theo dõi nó xuống, bước đầu tiên sẽ được cố gắng để xem đĩa thói quen sử dụng của bạn một cách cẩn thận hơn (có thể với atop, iostathoặc thậm chí công cụ mạnh mẽ hơn như perfhay systemtap). Những thứ cần tìm có thể là tìm kiếm quá mức, các thao tác I / O nhỏ, viết lại liên tục và di chuyển dữ liệu, v.v.


5
Giải thích tuyệt vời. Cần lưu ý rằng có thể tránh được phần lớn sự phân mảnh và giải phóng phần lớn trao đổi một cách nhanh chóng bằng cách loại bỏ phần lớn bộ nhớ bị tráo đổi: unix.stackexchange.com/questions/254202/ Khăn
Brandon DuPree

Đó không chỉ là sự phân mảnh / tìm kiếm thời gian. Trao đổi của tôi là trên SSD và đọc ngẫu nhiên rất nhanh, tuy nhiên lệnh hoán đổi chậm hơn mức cần thiết và tải SSD của tôi chỉ ở mức khoảng 1%. Tôi nghi ngờ có danh sách đi bộ liên quan đến một nơi nào đó trong kernel hoặc trong trao đổi (sử dụng CPU ~ 90-100%). Tất nhiên nếu tất cả các công việc được thực hiện tuần tự và tìm kiếm đĩa chậm quá thì nó có thể tăng lên đáng kể.
Thomas Guyot-Sionnest

33

Tôi đã gặp vấn đề tương tự với máy tính xách tay có ổ SSD nên việc tìm kiếm thời gian không phải là vấn đề.

Tôi tìm thấy một lời giải thích thay thế . Đây là một đoạn trích

Cách thức hoạt động của nó bây giờ, hoán đổi xem xét từng trang bộ nhớ bị tráo đổi trong phân vùng trao đổi và cố gắng tìm tất cả các chương trình sử dụng nó. Nếu nó không thể tìm thấy chúng ngay lập tức, nó sẽ xem các bảng trang của mọi chương trình đang chạy để tìm chúng. Trong trường hợp xấu nhất, nó sẽ kiểm tra tất cả các bảng trang cho mỗi trang bị tráo đổi trong phân vùng. Đúng vậy, các bảng cùng trang được kiểm tra nhiều lần.

Vì vậy, nó là một vấn đề hạt nhân chứ không phải bất cứ điều gì khác.


Không, đó không phải là vấn đề kernel IMHO. Đó là cách swapoffthực hiện. Khi quá trình hoán đổi thoát ra, nó không mất quá nhiều thời gian.
Marki555

15
Đó là một vấn đề với việc thực hiện trao đổi trong kernel - do đó là một vấn đề kernel! Bạn có thể thấy nếu bạn strace swapoffkhá nhiều tất cả những gì nó làm là gọi cuộc gọi swapoffhệ thống.
Nick Craig-Wood

1
Tôi có một máy chủ với 48 GB RAM (32 lõi), có 6 GB trao đổi lỗi miễn phí được sử dụng 0,7 GB. swappiness = 10, đã cố gắng làm cho nó 0 và cũng đã thử trao đổi để xem điều gì xảy ra. hoán đổi mất nhiều thời gian, có thể là 30 phút, giải phóng việc hoán đổi cực kỳ chậm. Tôi có SSD gần như không tải và CPU cũng tương tự, mong đợi quá trình trao đổi sẽ mất một cpu 100%.
sorin

1
Đó là vấn đề về cách thức hoán đổi được thực hiện (trong kernel). Đã có những cuộc thảo luận về cách tiếp cận tốt hơn nhiều năm trước trong kernel-dev, nhưng họ nói rằng đó là một trường hợp góc và không muốn nỗ lực thay đổi nó.
Marki555

7
Trên máy chủ có RAM 1 TB (có, TB) và trao đổi 2 GB (yêu cầu SAP ngớ ngẩn), phải mất 12 giờ để giải phóng 5% trong số 2 GB đó (với lõi 1 lõi 100%).
Marki555

22

Yup, swapoffcơ chế là không hiệu quả khủng khiếp. Cách giải quyết rất dễ dàng: lặp qua các quy trình, thay vào đó lặp lại qua các trang bị tráo đổi. Sử dụng tập lệnh python này (Tôi không liên kết):

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

Lưu ý rằng chế độ hoạt động của daemon chỉ dành cho máy tính để bàn / máy tính xách tay thường ngủ đông. Tôi sẽ không chạy nó như một daemon trên hệ thống máy chủ - chỉ cần chạy nó ở nền trước, đợi cho đến khi nó báo cáo nó xử lý một số quy trình rồi dừng nó và thử:

swapoff /dev/x

Vì hầu hết các trang hiện đang có mặt trong cả trao đổi và trong bộ nhớ, nên swapoffcó rất ít việc phải làm và bây giờ sẽ rất nhanh (tôi đã thấy hàng trăm MB / s).

Phần lịch sử phía trước

Kịch bản python đã nói ở trên dựa trên phần còn lại của câu trả lời này, đến lượt tôi là sự cải thiện của câu trả lời cũ này của tác giả jlong . Vì kịch bản an toàn hơn nhiều, tôi khuyên bạn chỉ nên thử phần còn lại của câu trả lời là dòng phòng thủ cuối cùng :

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

Này chạy có lẽ 2 giây và sẽ không thực sự làm bất cứ điều gì, chỉ cần liệt kê 10 phân đoạn bộ nhớ hàng đầu (trên thực tế nó in nhiều hơn một lớp lót; vâng tôi làm yêu một lớp lót, chỉ cần kiểm tra các lệnh, chấp nhận rủi ro, sao chép và dán vào vỏ của bạn, những cái này thực sự sẽ đọc từ trao đổi).

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

Lớp lót chính là an toàn (đối với tôi), ngoại trừ nó đọc rất nhiều / Proc.

Các lệnh phụ được chuẩn bị cho kiểm tra thủ công của bạn không an toàn . Mỗi lệnh sẽ treo một tiến trình trong thời gian đọc một đoạn bộ nhớ từ trao đổi. Vì vậy, nó không an toàn với các quy trình không chấp nhận bất kỳ tạm dừng. Tốc độ truyền tải mà tôi thấy là ở mức 1 gigabyte mỗi phút. (Kịch bản trăn nói trên đã loại bỏ sự thiếu hụt đó).

Một nguy hiểm khác là gây quá nhiều áp lực bộ nhớ cho hệ thống, vì vậy hãy kiểm tra thông thường free -m

Nó làm gì?

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" 
        }
      }
    }
  }
}

Đầu ra của tập lệnh perl này là một chuỗi các gdblệnh dump memory (range)gọi lại các trang đã hoán đổi vào bộ nhớ.

Đầu ra bắt đầu với kích thước, do đó, đủ dễ dàng để vượt qua máng | sort -Vr | headđể có được 10 phân khúc lớn nhất theo kích thước (SSIZE). Là -Vviết tắt của phân loại phù hợp với số phiên bản, nhưng nó hoạt động cho mục đích của tôi. Tôi không thể tìm ra cách để làm việc sắp xếp số.


Bạn sẽ sử dụng sắp xếp số ở đây vớisort -t = -k 2n
Stéphane Chazelas

9
Dường như không có nhu cầu sử dụng gdb để xem trộm bộ nhớ tiến trình (ít nhất là trên các nhân gần đây). Người ta chỉ có thể mở /proc/$pid/mem, tìm kiếm và đọc trực tiếp. Đây là PoC chủ yếu dựa trên đoạn trích của bạn: gist.github.com/WGH-/91260f6d65db88be2c847053c49be5ae Quá trình này không dừng lại, AFAIK không nên có bất kỳ nguy hiểm nào do việc này gây ra.
WGH

10

Trong quá trình trao đổi, nếu phát hiện vị trí hoán đổi đang sử dụng, thì hạt nhân sẽ hoán đổi đầu tiên trong trang. Hàm unuse_ process () sau đó cố gắng tìm tất cả các mục trong bảng trang tương ứng với trang vừa tráo đổi và thực hiện cập nhật cần thiết cho các bảng trang. Việc tìm kiếm rất kỹ lưỡng và rất tốn thời gian: nó truy cập vào mọi bộ mô tả bộ nhớ (của toàn bộ hệ thống) và kiểm tra từng mục trong bảng trang của nó.

Vui lòng tham khảo trang 724 của "Tìm hiểu về Linux Kernel phiên bản thứ 3".

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.