2009-09-09 57 views
28

Tại sao một sử dụng realloc() để thay đổi kích thước một mảng cấp phát động hơn là sử dụng chức năng miễn phí() trước khi gọi malloc() chức năng một lần nữa (tức là ưu và nhược điểm, ưu điểm so với nhược điểm, vv)? Nó dành cho lập trình C, nhưng tôi không thể tìm thấy thẻ thích hợp cho nó. Cảm ơn trước.Sự khác biệt giữa việc sử dụng realloc vs miễn phí - chức năng> chức năng malloc

+0

Tại sao bạn cần bộ nhớ nếu bạn không quan tâm đến nội dung của nó? – Philip

Trả lời

20

Lợi thế là realloc sẽ giữ lại nội dung của bộ nhớ. Với miễn phí + malloc bạn cần phải thiết lập lại dữ liệu trong mảng.

+4

cũng là bất lợi. Nếu bạn không quan tâm đến việc bảo tồn dữ liệu, làm miễn phí và malloc có thể nhanh hơn trong một số trường hợp (nơi khối bộ nhớ cần được di chuyển vì kích thước tăng trưởng) – Toad

+7

Nó nhanh hơn để tái phân bổ và có thể nhanh hơn để tái phân bổ nếu có chỗ để phát triển tại chỗ. Nếu không, nó sẽ chuyển thành một malloc/copy/free. –

+1

vẫn còn ... nếu bạn không cần phải bảo tồn dữ liệu, một hình ảnh miễn phí và malloc có vẻ mô tả về những gì bạn đang làm. – Toad

6

Vâng, realloc có thể thay đổi kích thước của khối tại chỗ, hoặc phân bổ một cái mới và sao chép càng nhiều càng tốt sẽ phù hợp. Ngược lại, malloc và miễn phí với nhau chỉ có thể phân bổ một cái mới, và bạn phải làm sao chép của riêng bạn.

Để được thẳng thắn, realloc không nhận được càng nhiều sử dụng những ngày này vì nó không hoạt động tốt với C++. Kết quả là, có một xu hướng cho người quản lý bộ nhớ không tối ưu hóa cho nó.

+1

Tuyên bố của bạn về realloc và người quản lý bộ nhớ không tối ưu hóa cho nó - bạn đã đọc một cái gì đó liên quan đến điều này? – ArmenB

+0

@ArmenB. Tôi không chắc mình đang nghĩ gì trong năm 2009, nhưng tôi đã xem xét mã nguồn của TCMalloc và nó không thực sự định hướng thay đổi kích thước. –

1

"hơn là sử dụng chức năng miễn phí() trước khi gọi malloc() chức năng một lần nữa"

Nếu bạn giải phóng các mảng hiện tại, bạn đã mất tất cả nội dung của nó, vì vậy bạn không thể "phát triển" mảng trong ý nghĩa thông thường.

+0

Tôi chắc chắn rằng họ có nghĩa là họ sẽ gọi malloc, sao chép các công cụ trên, sau đó miễn phí. –

+0

Steven chỉ nói những gì tôi muốn nói. – stanigator

3

Tôi có một chương trình đang thực hiện một loạt các cuộc gọi miễn phí() và malloc() để tạo một mảng động và tôi nghĩ mình sẽ tối ưu hóa bằng cách sử dụng lại mảng hiện có khi có thể. Điểm chuẩn cho thấy rằng realloc() trung bình chậm hơn so với chỉ gọi free() và malloc(). Tôi đoán nó có ý nghĩa, vì đôi khi nó sẽ phát triển, và có thể yêu cầu sao chép.

11

Tôi biết câu hỏi này là rất cũ (nó đã được trả lời trong năm 2009) nhưng tôi hy vọng câu trả lời của tôi sẽ giúp những người tìm kiếm và bắt gặp câu hỏi này (như tôi).

Mặc dù điểm chuẩn này không xác định vì quản lý bộ nhớ khác nhau giữa các hệ thống khác nhau, ngày nay mọi thứ có xu hướng khá ổn định, vì vậy các kết quả này nên an toàn để sử dụng làm điểm tham chiếu (Nếu bạn biết trường hợp thực tế) không, xin hãy cho tôi biết). Tôi đang sử dụng Windows 7 trên một 2.10GHz QuadCore Intel Core i3 2310M với 4GB RAM. Không phải là phần cứng tốt nhất từ ​​trước đến nay, nhưng tốt nhất tôi có bây giờ.

Điểm chuẩn này bắt đầu với một lượng bộ nhớ nhất định (INITIAL_MEMORY) và được phân bổ lại nhiều lần bởi một lượng nhỏ (BYTE_STEP) cho đến khi phân bổ hoàn toàn/deallocates ALLOCATE_MEMORY. Đối với điều này, nó cố gắng 6 phương pháp tiếp cận:

  1. Tăng Lossful Malloc: free() và malloc() nhiều bộ nhớ hơn.
  2. Giảm Malloc mất mát: miễn phí() và malloc() ít bộ nhớ.
  3. Tăng Malloc: malloc() bộ nhớ hơn, sao chép dữ liệu và miễn phí() bộ nhớ trước đó.
  4. Giảm Malloc: malloc() ít bộ nhớ, sao chép dữ liệu và bộ nhớ trước miễn phí().
  5. Tăng Realloc: realloc() thêm bộ nhớ.
  6. Giảm realloc: realloc() ít bộ nhớ.

Vì vậy, thử nghiệm đầu tiên: Bắt đầu với 2MB và phân bổ ± 1MB trong bước 1KB:

Increasing Lossful Malloc took 3 ms 
Decreasing Lossful Malloc took 5 ms 
Increasing Malloc took 1 265 ms 
Decreasing Malloc took 744 ms 
Increasing Realloc took 316 ms 
Decreasing Realloc took 0 ms 

Như chúng ta có thể thấy, sao chép bằng tay với memcpy là luôn chậm hơn so với realloc, bởi vì trong trường hợp này malloc được đảm bảo cấp phát bộ nhớ mới và bạn buộc phải sao chép dữ liệu trong mỗi phân bổ, cho chúng ta thấy rằng realloc thực sự đang sử dụng lại cùng một địa chỉ và mở rộng kích thước khối trong một số trường hợp. Vì vậy, nếu bạn muốn giữ dữ liệu của bạn, realloc có lẽ là những gì bạn muốn sử dụng. Để đơn giản hóa mọi thứ, tôi sẽ không tiếp tục thử nghiệm phương pháp tiếp cận malloc lossless này.

Hãy tiến hành các thử nghiệm tiếp theo: 32MB bộ nhớ ban đầu, phân bổ 16MB trong bước 16KB:

Increasing Lossful Malloc took 4 ms 
Decreasing Lossful Malloc took 4 ms 
Increasing Realloc took 21 453 ms 
Decreasing Realloc took 0 ms 

Bây giờ, chúng ta có thể thấy rằng việc tăng realloc mất rất nhiều thời gian so với các xét nghiệm khác. Giảm realloc thậm chí không đạt đến 1 ms. Điều này cho thấy rằng nếu bạn không muốn giữ bộ nhớ của bạn, bạn nên sử dụng một cách tiếp cận miễn phí-> malloc, hay không? Nhìn vào những kết quả này:

Increasing Lossful Malloc took 777 ms 
Decreasing Lossful Malloc took 729 ms 
Decreasing Realloc took 19 ms 

(. Các kết quả này là quá gần, vì vậy tôi chạy một số xét nghiệm và trung bình họ)

Chắc chắn giảm kích thước bộ nhớ hiệu quả hơn khi sử dụng realloc(). Đó có thể là vì realloc không cần phải tìm kiếm một khối bộ nhớ mới, nó chỉ sử dụng khối trước đó và co lại nó. Đây là một sự khác biệt lớn về hiệu suất lớn nếu bạn đang sử dụng phân bổ nhiều.

Ngoài ra, chúng ta có thể thấy rằng malloc tăng chậm hơn một chút so với giảm dần, ngay cả khi cả hai về cơ bản giống nhau: tìm một khối bộ nhớ và phân bổ nó. Sự khác biệt này có thể là do khi tìm kiếm khối malloc lớn hơn cần tìm kiếm dài hơn trung bình hơn khi tìm kiếm các khối nhỏ hơn. Ví dụ, nếu có một khối 30MB, một malloc phân bổ 16MB sẽ sử dụng nó, nhưng một malloc phân bổ 32MB sẽ phải bỏ qua nó và tiếp tục tìm kiếm và sử dụng hết thời gian. Đây có lẽ là lý do tại sao kết quả thay đổi rất nhiều trong các bài kiểm tra của tôi.

Tóm/TLDR:

  1. Nếu bạn cần để giữ cho dữ liệu của bạn, sử dụng realloc(). Nhanh hơn 4 lần so với sử dụng malloc()/free() và sao chép dữ liệu của bạn khi tăng tỷ lệ. Khi chia tỷ lệ xuống, tốc độ này nhanh hơn 10.000-100.000 lần. KHÔNG BAO GIỜ sao chép nội dung theo cách thủ công.
  2. Nếu bạn không cần phải giữ cho dữ liệu của bạn, bạn nên sử dụng malloc()/Việt() để quy mô lên (tăng kích thước bộ nhớ) nhưng sử dụng realloc() khi rộng xuống (giảm kích thước bộ nhớ).
  3. Nếu bạn không biết kích thước trước đó (bạn không biết bạn đang thu nhỏ hoặc giảm), hãy sử dụng malloc()/free(). Khi giảm tỷ lệ, realloc() nhanh hơn ~ 40 lần, nhưng khi tăng tỷ lệ, realloc() là ~ 7600 lần chậm hơn. Trừ khi chương trình của bạn thực hiện một vài phân bổ khổng lồ và rất nhiều deallocations (gấp 200 lần deallocations hơn phân bổ, trong đó có thể là), bạn nên sử dụng malloc()/free().

Đây là nguồn benchmark của tôi: test.cpp

Bây giờ, xin vui lòng, nếu tôi đã làm điều gì sai trái hoặc bạn có bất kỳ ý kiến, cảm thấy tự do để nói/chính xác cho tôi.

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