append()
's đã là O (1) vì nó phát triển mảng bởi một mỗi lần tỷ lệ phần trăm. Khi mảng được lớn hơn, phát triển nó trở nên đắt hơn nhưng tỉ lệ hiếm hơn. Một lát cắt 10M sẽ đắt gấp 10 lần để phát triển hơn 1M slice, nhưng vì dung lượng bổ sung mà chúng tôi đang phân bổ tỷ lệ thuận với kích thước, nó cũng sẽ gấp 10 lần các cuộc gọi append(slice, item)
cho đến lần tiếp theo . Chi phí ngày càng tăng và tần suất giảm của các lần phân bổ lại bị hủy bỏ, để lại hằng số chi phí trung bình, tức là O (1).
Ý tưởng tương tự cũng áp dụng các mảng có kích thước động của các ngôn ngữ khác: Ví dụ: triển khai của Microsoft std::vector
dường như tăng mảng lên 50% mỗi lần. Phân bổ O (1) không có nghĩa là bạn không phải trả gì cho phân bổ, chỉ rằng bạn tiếp tục thanh toán với cùng tốc độ trung bình khi mảng của bạn lớn hơn.
Trên máy tính xách tay của tôi, tôi có thể chạy một triệu slice = append(slice, someStaticString)
s trong 77ms. Một lý do nó nhanh chóng, mà siritinga lưu ý dưới đây, là "sao chép" chuỗi để mở rộng mảng thực sự chỉ cần sao chép tiêu đề chuỗi (một con trỏ/chiều dài cặp), không sao chép nội dung. 100.000 tiêu đề chuỗi vẫn dưới 2MB để sao chép, không phải là một vấn đề lớn so với số lượng dữ liệu khác mà bạn đang làm việc.
container/list
tắt ~ 3x chậm hơn cho tôi trong một microbenchmark; liên kết danh sách liên kết cũng là thời gian liên tục, tất nhiên, nhưng tôi tưởng tượng append
có hằng số thấp hơn vì thường có thể chỉ ghi vào một vài từ bộ nhớ và không cấp phát một mục danh sách, v.v. Mã thời gian sẽ không hoạt động trong sân chơi nhưng bạn có thể sao chép này tại địa phương và chạy nó để xem bản thân: http://play.golang.org/p/uYyMScmOjX
nhưng bạn đang hỏi một câu hỏi cụ thể hơn ở đây về một ứng dụng grep
-like (và cảm ơn cho hỏi một câu hỏi chi tiết với ngữ cảnh). Đối với điều đó, khuyến nghị cuối cùng là nếu bạn đang tìm kiếm các hợp đồng biểu diễn của các bản ghi, có lẽ tốt nhất là tránh đệm toàn bộ đầu ra trong RAM.
Bạn có thể viết điều gì đó để truyền trực tuyến kết quả dưới dạng một chức năng duy nhất: logparser.Grep(in io.Reader, out io.Writer, patterns []regexp.Regexp)
; bạn có thể thực hiện theo cách khác là out
a chan []byte
hoặc func(match []byte) (err error)
nếu bạn không muốn mã gửi kết quả quá bị ghim với mã grep.
(Trên []byte
vs string
: a []byte
dường như thực hiện công việc ở đây và tránh []byte
< =>string
chuyển đổi khi bạn làm I/O, vì vậy tôi muốn mà tôi không biết những gì tất cả các bạn'. làm lại, mặc dù, và nếu bạn cần string
nó là tốt.)
Nếu bạn giữ nguyên toàn bộ danh sách đối sánh trong RAM, hãy lưu ý rằng việc giữ một tham chiếu đến một phần của một chuỗi lớn hoặc lát byte giữ toàn bộ nguồn chuỗi/slice từ rác được thu thập. Vì vậy, nếu bạn đi tuyến đường đó, sau đó ngược lại bạn thực sự có thể muốn để sao chép các kết quả phù hợp để tránh lưu giữ tất cả dữ liệu nhật ký nguồn trong RAM.
Với khối lượng tb xử lý tôi phải hạn chế số dòng quét trong một lần chạy (lý do phải rõ ràng: lấy trung bình tải I/O, tải CPU và kích thước bộ thường trú) đỉnh cao) vì vậy tôi không phải thực sự phát trực tiếp. Nhưng điều quan trọng hơn ở đây với tôi là tôi không thực sự hiểu những gì bạn có nghĩa là nếu tôi tràn 1M hàng op tiếp theo sẽ không được phân bổ hàng 1.25M + sao chép 1M hàng? Xem bình luận tiếp theo để tính toán. – LetMeSOThat4U
Trong Python: a = 1; cumul = 0. Sau đó, 'cho i trong phạm vi (10): in 'hàng% .2f cumul% .2f'% (a, cumul) ,; cumul + = a; a = a * 1,25'. Kết quả: hàng 1,00 cumul 0,00 hàng 1,25 cumul 1,00 hàng 1,56 cumul 2,25 hàng 1,95 cumul 3,81 hàng 2,44 cumul 5,77 hàng 3,05 cumul 8,21 hàng 3,81 cumul 11,26 hàng 4,77 cumul 15,07 hàng 5,96 cumul 19,84 hàng 7,45 cumul 25,80.Vì vậy, nếu tôi bắt đầu với 1M hàng lát và có 8 triệu trận đấu sẽ yêu cầu sao chép lát 10 lần và có tổng số 25 triệu hàng được sao chép. Nó không phải là một chi phí rất tốt so với danh sách liên kết nói .. – LetMeSOThat4U
Tôi nghĩ rằng một chuỗi các chuỗi là nội bộ một lát con trỏ đến chuỗi, trong ý nghĩa rằng mở rộng các lát sẽ không thực sự sao chép các chuỗi, chỉ là con trỏ đến chuỗi, do đó, mỗi mục nhập sẽ là 4 hoặc 8 byte (tùy thuộc vào kiến trúc hệ thống), do đó, nó phải được nhanh chóng. – siritinga