Hàm Sys_PageIn () làm gì trong Quake?


8

Tôi đã nhận thấy trong quá trình khởi tạo của Quake ban đầu, hàm sau được gọi.

volatile int sys_checksum;

//  **lots of code**

void Sys_PageIn(void *ptr, int size)
{
    byte *x;
    int j,m,n;
//touch all memory to make sure its there.  The 16-page skip is to
//keep Win 95 from thinking we're trying to page ourselves in (we are
//doing that, of course, but there's no reason we shouldn't)
    x = (byte *)ptr;

    for (n=0 ; n<4 ; n++)
    {
        for (m=0; m<(size - 16 * 0x1000) ; m += 4)
        {
            sys_checksum += *(int *)&x[m];
            sys_checksum += *(int *)&x[m + 16 * 0x10000];
        }
    }
}

Tôi nghĩ rằng tôi chỉ không đủ quen thuộc với phân trang để hiểu chức năng này. void * ptr được truyền cho hàm là một phần bộ nhớ gần đây của malloc () có kích thước byte lớn. Đây là toàn bộ hàm - j là một biến không được ước tính. Dự đoán tốt nhất của tôi là int sys_checksum dễ bay hơi đang buộc hệ thống phải đọc vật lý tất cả các không gian chỉ là malloc () 'd, có lẽ để đảm bảo rằng các không gian này tồn tại trong bộ nhớ ảo? Thê nay đung không? Và tại sao ai đó sẽ làm điều này? Có phải vì một số lý do Win95 cổ?

Câu trả lời:


6

Dự đoán của bạn về cơ bản là chính xác và nó được thực hiện dưới dạng tối ưu hóa (rất có thể; tôi chỉ có thể suy đoán tất nhiên vì tôi không viết mã).

Mặc dù một ứng dụng trong Windows dường như có toàn quyền truy cập vào toàn bộ phạm vi RAM trong máy (hoặc ít nhất là phạm vi được HĐH báo cáo với nó), nhưng thực tế, HĐH đang ảo hóa quyền truy cập của ứng dụng vào bộ nhớ vật lý thực tế và sẽ lưu trữ vùng (trang) của bộ nhớ ảo vào đĩa khi cần. Quá trình chuyển các vùng này từ đĩa sang RAM vật lý thường được gọi là "phân trang" (khi chuyển từ đĩa sang RAM) hoặc "phân trang" (khi đi từ RAM sang đĩa).

Đĩa IO chậm, so với RAM, và vì vậy tránh phân trang là lý tưởng để đạt được hiệu suất tối đa. Mục đích của chức năng này dường như là cố gắng giảm thiểu phân trang trong suốt thời gian tồn tại của chương trình bằng cách buộc HĐH phải trang tất cả bộ nhớ vào lúc bắt đầu chương trình - việc ép buộc được thực hiện bằng cách cố gắng đọc từ tất cả bộ nhớ.

Có lẽ Windows 95 đã có một số loại mã để phát hiện và ngăn chặn hành vi này, điều mà bình luận cho thấy đang bị phá vỡ bằng cách đọc bộ nhớ theo một mẫu cụ thể. Điều này có ý nghĩa rằng HĐH sẽ làm điều này, bởi vì việc buộc một trang hoàn chỉnh như thế này sẽ buộc bộ nhớ các tiến trình khác được phân trang ra đĩa, có thể làm chậm chúng .

Có thể lập luận rằng đây là hành vi có thể chấp nhận được đối với trò chơi vì người dùng thường sẽ chỉ chạy trò chơi và không cố gắng thực hiện nhiều thao tác trong khi trò chơi kết thúc, do đó, hy sinh hiệu suất của các quy trình khác có thể đang chạy cái ác đó

Một số lưu ý khác:

  • Kiểu này không có khả năng hoạt động tốt như ngày hôm nay vì nó có thể đã hoạt động trở lại trong Windows 95. Bản chất của bộ lập lịch hệ điều hành đã thay đổi khá nhiều kể từ đó, vì vậy nó không nhất thiết là một kỹ thuật tôi khuyên bạn nên áp dụng trừ khi bạn có thuyết phục dữ liệu hồ sơ và số liệu để hỗ trợ thực tế rằng nỗ lực của bạn là một lợi ích.

  • volatilelà một gợi ý cho việc triển khai để tránh tối ưu hóa mạnh mẽ đối tượng được khai báo vì đối tượng đó có thể thay đổi thông qua phương tiện thực hiện không thể dự đoán được. Nói cách khác, nó giống như một lá cờ "không tối ưu hóa tôi". Bằng cách này, trình biên dịch, ngay cả khi nó nhận ra rằng về cơ bản biến không được sử dụng theo bất kỳ kiểu quan trọng nào, sẽ không tối ưu hóa các lần đọc từ bộ nhớ vào biến đó như là một phần của việc tối ưu hóa.

  • j không được sử dụng có lẽ chỉ là một sự giám sát.


1

Raymond Chen trả lời điều này trực tiếp trong một bài đăng sau đó trên blog của mình The Old New Thing (Maximus Minimius có nguồn chính xác, hóa ra chỉ 3 năm quá sớm để giải thích trực tiếp): https://bloss.msdn.microsoft.com/oldnewthing / 20151111-00 /? P = 91972

Những gì mã này làm là truy cập vào khối bộ nhớ được chỉ định bởi các tham số ptr và kích thước trong một mẫu không bình thường: Nó đọc byte 0, sau đó là byte ở độ lệch 16 trang, sau đó là byte một, sau đó là byte ở độ lệch 16 trang cộng một, v.v., xen kẽ giữa một byte và đối tác của nó 16 trang phía trước.

Mẫu truy cập cụ thể này trong Windows 95 đã đánh bại thuật toán phát hiện "quét bộ nhớ tuần tự".

Hãy nhớ lại rằng các máy tính trong kỷ nguyên Windows 95 có 4 MB RAM. Giả sử bạn đã làm việc trong một tài liệu trong một thời gian dài. Cuối cùng, bạn đã hoàn thành, và bạn đóng cửa sổ hoặc thu nhỏ nó. Bùng nổ, bây giờ máy tính để bàn của bạn có thể nhìn thấy và bitmap hình nền cần được phân trang. Nếu màn hình của bạn là 1024 × 768 ở mức 16 bit cho mỗi pixel, thì sẽ có tới 1,5 MB bộ nhớ. Phân trang trong 1,5 MB bộ nhớ có nghĩa là cho bitmap có nghĩa là loại bỏ 1,5 MB bộ nhớ được sử dụng cho các công cụ khác và đó là rất nhiều bộ nhớ cho một máy chỉ có 4 MB để hoạt động (đặc biệt là rất nhiều 4 MB đó thuộc về công cụ không đủ điều kiện để được phân trang). Hiện tượng chúng ta thấy là việc sơn lại máy tính để bàn của bạn sẽ làm mất phần lớn bộ nhớ của bạn.

Và sau đó, điều tiếp theo bạn làm có lẽ là khởi chạy một ứng dụng mới, nó sẽ bao phủ hình nền, vì vậy bộ nhớ hình nền sẽ không còn cần thiết nữa. Vì vậy, về cơ bản chúng tôi đã loại bỏ tất cả bộ nhớ trong hệ thống của bạn để xử lý một khối bộ nhớ khổng lồ chỉ được truy cập một lần.

Thủ thuật mà Windows 95 đã sử dụng là xem mô hình lỗi trang của bạn và nếu thấy rằng bạn đang truy cập bộ nhớ tuần tự, nó bắt đầu đánh dấu bộ nhớ 16 trang phía sau truy cập hiện tại là không truy cập gần đây . Trong trường hợp quét tuần tự thẳng, điều này có nghĩa là toàn bộ bộ đệm quay vòng qua cửa sổ bộ nhớ 64KB, bất kể kích thước bộ đệm. Với thủ thuật này, bộ đệm 4 MB cuối cùng chỉ tiêu tốn 64KB bộ nhớ, trái ngược với việc sử dụng tất cả bộ nhớ trong hệ thống của bạn.

Các Sys_Page­Inchức năng đặc biệt defeates dò tuần tự quét bằng cách cố tình đi lại 16 trang và truy cập vào trang một lần nữa. Điều này khiến nó được đánh dấu được sử dụng gần đây , chống lại việc không được sử dụng gần đây mà trình phát hiện quét tuần tự đã thực hiện. Kết quả: Tất cả các trang bộ nhớ được đánh dấu được sử dụng gần đây và không còn là ứng cử viên chính cho việc được phân trang.


0

Hồi sinh điều này, tôi nhận thấy mục này trên trang web của Raymond Chen gần đây: http://bloss.msdn.com/b/oldnewthing/archive/2012/08/13/10334566.aspx

Tại sao tôi trong các khoản tín dụng Quake? Tôi không nhớ những gì tôi đã làm cụ thể ... lời khuyên tôi đưa ra gần như chắc chắn liên quan đến quản lý bộ nhớ và trao đổi.

Điều này chỉ ra rằng có ít nhất một khả năng tốt là chức năng này là kết quả của lời khuyên của Raymond (và khi Raymond Chen nói "bạn cần phải làm điều này" thì ít nhất có khả năng là anh ta đúng).

Ngày nay thật dễ quên, nhưng vào năm 1996, PC trung bình của game thủ có thể có 16mb RAM, tối đa và Quake là một con quái vật tuyệt đối của một chương trình. Trong những ngày đó, các đĩa cứng được sử dụng để nghiền nát không ngừng do phân trang và kéo theo tất cả bộ nhớ được phân bổ theo cách này sẽ giúp (ít nhất) giúp ngăn chặn tệp trang bị chạm vào thời gian chạy, điều này có thể dẫn đến việc bị đình trệ bất cứ điều gì lên đến một giây hoặc nhiều hơn.

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.