2011-06-11 26 views
5

Tôi đã cố gắng tìm ra lý do tại sao chương trình của tôi tiêu tốn rất nhiều RAM hệ thống. Tôi đang tải một tập tin từ đĩa vào một vectơ của cấu trúc của một số mảng được phân bổ động. Một tệp 16MB kết thúc tiêu thụ 280MB RAM hệ thống theo trình quản lý tác vụ. Các loại trong tập tin chủ yếu là ký tự với một số quần short và một vài dài. Có 331.000 bản ghi trong tệp có chứa trung bình khoảng 5 trường. Tôi đã chuyển đổi vector thành một cấu trúc và làm giảm bộ nhớ còn khoảng 255MB nhưng điều đó vẫn có vẻ rất cao. Với vector chiếm quá nhiều bộ nhớ, chương trình đang hết bộ nhớ nên tôi cần tìm cách để sử dụng bộ nhớ hợp lý hơn.Tại sao chương trình VC++ lưu trữ 5MB dữ liệu tiêu thụ 64MB bộ nhớ hệ thống?

Tôi đã viết một chương trình đơn giản để chỉ cần một công cụ một vector (hoặc mảng) với 1.000.000 char con trỏ. Tôi hy vọng nó sẽ phân bổ 4 + 1 byte cho mỗi 5MB bộ nhớ cần thiết để lưu trữ, nhưng trên thực tế nó đang sử dụng 64MB (phiên bản mảng) hoặc 67MB (phiên bản vectơ). Khi chương trình đầu tiên khởi động nó chỉ tiêu thụ 400K vậy tại sao có thêm 59MB cho mảng hoặc 62MB cho vectơ được phân bổ? Bộ nhớ bổ sung này có vẻ là cho mỗi thùng chứa, vì vậy nếu tôi tạo một size_check2 và sao chép tất cả mọi thứ và chạy nó chương trình sử dụng lên 135MB cho 10MB giá trị của con trỏ và dữ liệu.

Cảm ơn trước,

size_check.h

#pragma once 

#include <vector> 

class size_check 
{ 
public: 
    size_check(void); 
    ~size_check(void); 

    typedef unsigned long size_type; 

    void stuff_me(unsigned int howMany); 

private: 
    size_type**   package; 
// std::vector<size_type*> package; 
    size_type*   me; 
}; 

size_check.cpp

#include "size_check.h" 

size_check::size_check(void) 
{ 
} 

size_check::~size_check(void) 
{ 
} 

void size_check::stuff_me(unsigned int howMany) 
{ 
    package = new size_type*[howMany]; 
    for(unsigned int i = 0; i < howMany; ++i) 
    { 

     size_type *me = new size_type; 
     *me = 33; 
     package[i] = me; 
//  package.push_back(me); 
    } 
} 

main.cpp #include "size_check.h"

int main(int argc, char * argv[ ]) 
{ 
    const unsigned int buckets = 20; 
    const unsigned int size = 50000; 

    size_check* me[buckets]; 

    for(unsigned int i = 0; i < buckets; ++i) 
    { 
     me[i] = new size_check(); 
     me[i]->stuff_me(size); 
    } 
    printf("done.\n"); 
} 
+0

Tôi chưa đọc chi tiết mã của bạn, nhưng xin lưu ý rằng con trỏ cũng chiếm không gian. – slartibartfast

+0

Bạn cũng cần tính đến việc căn chỉnh và sắp xếp cấu trúc dữ liệu. – feathj

+0

@myrkos là chính xác - bốn byte, nếu tôi nhớ chính xác, trên phần cứng thông thường. Định nghĩa lớp học của bạn cũng chiếm không gian. Hãy thử làm một sizeof() của một đối tượng size_check mà bạn thực hiện và nhân số đó với số lượng cá thể bạn tạo và xem điều đó có tạo nên sự khác biệt hay không. –

Trả lời

3

Trong bài kiểm tra của tôi sử dụng VS2010, một bản dựng gỡ lỗi có kích thước thiết lập là 52.500KB. Nhưng bản phát hành bản phát hành có kích thước hoạt động là 20.944KB.

Xây dựng gỡ lỗi thường sẽ sử dụng nhiều bộ nhớ hơn so với các bản dựng được tối ưu hóa do trình quản lý heap gỡ lỗi thực hiện những việc như tạo memory fences.

Trong bản phát hành bản phát hành, tôi nghi ngờ rằng trình quản lý heap có nhiều bộ nhớ hơn bạn thực sự đang sử dụng làm tối ưu hóa hiệu suất.

+1

@Mark: Khi bạn đặt câu hỏi và ai đó trả lời, không chỉnh sửa câu trả lời để thêm nhận xét của riêng bạn; điều đó rất khó hiểu. Sử dụng liên kết Thêm nhận xét bên dưới câu trả lời bạn muốn nhận xét. –

1

Memory Leak

package = new size_type[howMany]; // instantiate 50,000 size_type's 
for(unsigned int i = 0; i < howMany; ++i) 
{ 
    size_type *me = new size_type; // Leak: results in an extra 50k size_type's being instantiated 
    *me = 33; 
    package[i] = *me; // Set a non-pointer to what is at the address of pointer "me" 
    // Would package[i] = 33; not suffice? 
} 

Hơn nữa, chắc chắn rằng bạn đã biên soạn trong chế độ phát hành

1

Có thể có một vài lý do tại sao bạn đang nhìn thấy như một bộ nhớ lớn từ bạn chương trình kiểm tra. Bên trong bạn

void size_check::stuff_me(unsigned int howMany) 
{ 

Phương pháp này luôn nhận được gọi với howMany = 50000.

package = new size_type[howMany]; 

Giả sử đây là một thiết lập trên 32-bit tuyên bố trên sẽ phân bổ 50.000 * 4 byte.

for(unsigned int i = 0; i < howMany; ++i) 
{ 
    size_type *me = new size_type; 

Ở trên sẽ cấp phát bộ nhớ mới cho mỗi lần lặp của vòng lặp. Vì vòng lặp 50.000 này và phân bổ sẽ không bao giờ bị xóa có hiệu quả mất thêm 50.000 * 4 byte khi hoàn thành vòng lặp.

 *me = 33; 
     package[i] = *me; 
    } 
} 

Cuối cùng, vì stuff_me() được gọi 20 lần từ main() chương trình của bạn sẽ được phân bổ ít nhất ~ 8Mbytes sau khi hoàn thành. Nếu đây là hệ thống 64 bit so với dấu chân có thể sẽ tăng gấp đôi kể từ sizeof(long) == 8byte.

Mức tăng tiêu thụ bộ nhớ có thể có liên quan đến cách thức VS thực hiện phân bổ động. Vì lý do hiệu suất, có thể do nhiều cuộc gọi đến new, chương trình của bạn đang đặt thêm bộ nhớ để tránh phải cập nhật hệ điều hành mọi lúc cần thiết hơn.

FYI, khi tôi chạy chương trình thử nghiệm của bạn trên mingw-gcc 4.5.2, mức tiêu thụ bộ nhớ là ~ 20Mbyte - thấp hơn nhiều so với những gì bạn nhìn thấy nhưng vẫn là một số lượng đáng kể. Nếu tôi đã thay đổi phương thức stuff_me thành:

void size_check::stuff_me(unsigned int howMany) 
{ 
    package = new size_type[howMany]; 
    size_type *me = new size_type; 
    for(unsigned int i = 0; i < howMany; ++i) 
    { 
     *me = 33; 
     package[i] = *me; 
    } 
    delete me; 
} 

mức tiêu thụ bộ nhớ giảm xuống một chút xuống ~ 4-5mbytes.

1

Tôi nghĩ rằng tôi đã tìm thấy câu trả lời bằng cách đưa vào tuyên bố mới. Trong gỡ lỗi xây dựng có hai mục được tạo ra khi bạn làm một mới. Một là _CrtMemBlockHeader có độ dài 32 byte. Các khác là noMansLand (một hàng rào bộ nhớ) với kích thước 4 byte cho chúng ta một chi phí của 36 byte cho mỗi mới. Trong trường hợp của tôi mỗi cá nhân mới cho một char là chi phí cho tôi 37 byte. Trong bản phát hành xây dựng việc sử dụng bộ nhớ được giảm xuống còn khoảng 1/2 nhưng tôi không thể nói chính xác có bao nhiêu được phân bổ cho mỗi mới như tôi không thể có được thói quen mới/malloc.

Vì vậy, công việc của tôi xung quanh là phân bổ một khối bộ nhớ lớn để giữ tệp trong bộ nhớ. Sau đó phân tích các hình ảnh bộ nhớ điền vào một vectơ của con trỏ đến đầu mỗi bản ghi. Sau đó, theo yêu cầu, tôi xây dựng một bản ghi từ hình ảnh bộ nhớ bằng cách sử dụng con trỏ đến đầu của bản ghi đã chọn. Việc này đã làm giảm dung lượng bộ nhớ xuống < 25MB.

Cảm ơn tất cả sự trợ giúp và đề xuất của bạn.

Các vấn đề liên quan