2014-06-28 21 views
7

Việc thêm phần tử lên một triệu phần tử ArrayList có chi phí đặt một tham chiếu ngay bây giờ và sao chép một tham chiếu trong tương lai khi số ArrayList phải được thay đổi kích thước.Hiệu quả của việc thêm vào vectơ

Như tôi đã hiểu, việc thêm một phần tử lên một triệu phần tử PersistenVector phải tạo một đường dẫn mới, bao gồm 4 mảng kích thước 32. Điều này có nghĩa là cần phải chạm đến hơn 120 tham chiếu.

Clojure quản lý để giữ cho chi phí véc tơ "tồi tệ hơn gấp 2,5 lần" hoặc "4 lần tệ hơn" (trái ngược với "tồi tệ hơn 60 lần"), đã được xác nhận trong một số video Clojure mà tôi đã xem gần đây? Có một cái gì đó để làm với bộ nhớ đệm hoặc địa phương của tài liệu tham khảo hoặc một cái gì đó tôi không nhận thức được?

Hoặc là bằng cách nào đó có thể xây dựng một vector nội bộ với đột biến và sau đó biến nó bất biến trước khi tiết lộ nó với thế giới bên ngoài?

Tôi đã gắn thẻ câu hỏi là tốt, vì scala.collection.immutable.vector về cơ bản là giống nhau, phải không?

Trả lời

9

PersistentVector của Clojure có bộ đệm đuôi đặc biệt để cho phép hoạt động hiệu quả ở cuối vectơ. Chỉ sau khi mảng 32 phần tử này được lấp đầy thì nó được thêm vào phần còn lại của cây. Điều này giúp cho chi phí khấu hao thấp. Here là một bài viết về việc triển khai. Các source cũng đáng đọc.

Về ", bằng cách nào đó có thể xây dựng một vector nội bộ với đột biến và sau đó biến nó bất biến trước khi tiết lộ nó với thế giới bên ngoài?", Vâng! Chúng được gọi là transients trong Clojure và được sử dụng để thay đổi hàng loạt hiệu quả.

+0

Vì câu hỏi bao gồm các số, nên có thể nói rõ ràng rằng vector Clojure là một cây * của các con trỏ 32 bit, mỗi cấp trong số đó chiếm năm bit của chỉ mục. Vì vậy, cây chỉ có thể có năm hoặc sáu cấp độ sâu. – Thumbnail

+0

Điều đó có nghĩa là việc thêm vào véc tơ của Clojure chậm hơn so với nối thêm? – ZhekaKozlov

+0

@ZhekaKozlov Có, thêm vào cuối là một hoạt động liên tục thời gian. Thêm vào đầu là tuyến tính. Tuy nhiên, nếu bạn không cần kết quả là một vectơ (hoặc ít nhất là không phải ngay lập tức), bạn có thể sử dụng kết nối lười (hoặc một cấu trúc dữ liệu khác). –

7

Không thể nói về Clojure, nhưng tôi có thể đưa ra một số nhận xét về Scala Vectors.

vectơ Scala liên tục (scala.collection.immutable.Vector s) là nhiều hơn chậm hơn so với bộ đệm mảng khi nói đến phụ thêm. Trên thực tế, chúng chậm hơn 10 lần so với hoạt động chuẩn bị trước List. Chúng chậm hơn gấp 2 lần so với Conc-tree, chúng ta sử dụng trong Parallel Collections.

Nhưng, Scala cũng có mutable vectơ - chúng ẩn trong lớp VectorBuilder. Việc thêm vào các vectơ có thể thay đổi không bảo tồn được phiên bản trước của vectơ, nhưng biến đổi nó thành vị trí bằng cách giữ con trỏ tới lá tận cùng bên phải trong vectơ. Vì vậy, có - giữ vectơ có thể thay đổi nội bộ, và hơn là trả lại một tham chiếu bất biến là chính xác những gì được thực hiện trong bộ sưu tập Scala.

VectorBuilder là hơi nhanh hơn ArrayBuffer, bởi vì nó chỉ cần phân bổ mảng của nó một lần, trong khi ArrayBuffer cần phải làm trung bình hai lần (vì ngày càng tăng). Conc.Buffer s, mà chúng tôi sử dụng làm bộ kết hợp mảng song song, nhanh gấp hai lần so với VectorBuilder s.

Điểm chuẩn có tại đây. Không ai trong số các tiêu chuẩn liên quan đến bất kỳ quyền anh, họ làm việc với các đối tượng tham khảo để tránh bất kỳ sai lệch:

Nhiều bộ sưu tập benchmarks here.

Các thử nghiệm này được thực hiện bằng cách sử dụng ScalaMeter.

+0

Tôi rất ngạc nhiên khi bạn nói phụ thêm chậm hơn. Nhìn vào [bảng chính thức] (http://www.scala-lang.org/docu/files/collections-api/collections_40.html), chúng được chào hàng là 'eC' - có hiệu quả không đổi, aka O (log32N). .. Làm thế nào là một cường độ? –

+1

Vâng, đó không phải là tuyên bố cá nhân của tôi, tôi chỉ hiển thị các tiêu chí chuẩn :). Một 'cường độ chậm hơn' trong trường hợp này xuất phát từ yếu tố không đổi của hoạt động nối thêm vectơ, không phức tạp về mặt thuật toán. Ví dụ, một hoạt động 'O (n^2)' có thể nhanh hơn nhiều so với hoạt động 'O (n)' đối với một số phạm vi 'n'. Tương tự, các hoạt động thời gian chạy 'O (1)' khác nhau có thể có thời gian chạy tuyệt đối khác nhau. – axel22

+4

Không có mâu thuẫn nào giữa việc nối thêm vectơ là cả thời gian cố định và thứ tự độ lớn chậm hơn so với danh sách trước. – dfan

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