2009-03-17 8 views
5

Mọi văn bản tôi đã đọc về các ký hiệu Ruby đều nói về hiệu quả của các ký hiệu trên chuỗi. Nhưng, đây không phải là những năm 1970. Máy tính của tôi có thể xử lý một chút bộ sưu tập rác dư thừa. Liệu tôi có sai? Tôi có bộ xử lý lõi kép Pentium mới nhất và lớn nhất và 4 hợp đồng RAM. Tôi nghĩ rằng đó là đủ để xử lý một số Strings.Không phải máy tính hiện đại đủ mạnh để xử lý Strings mà không cần sử dụng Ký hiệu (trong Ruby)

Trả lời

17

Máy tính của bạn cũng có thể xử lý "một chút thu gom rác thải thêm", nhưng những gì về khi mà "một chút" diễn ra trong một vòng lặp bên trong mà chạy hàng triệu lần? Điều gì về khi nó đang chạy trên một hệ thống nhúng với bộ nhớ hạn chế?

Có rất nhiều địa điểm bạn có thể lấy đi bằng cách sử dụng các chuỗi có dây, nhưng trong một số bạn không thể. Tất cả phụ thuộc vào ngữ cảnh.

+0

Vâng, đó là sự thật - một vòng lặp chạy dài chắc chắn có thể ăn hết tài nguyên. Đã không nghĩ đến việc tạo ra các chuỗi bên trong một vòng lặp, nhưng chắc chắn, tôi đoán bạn có thể làm điều đó. Cảm ơn vì tiền hỗ trợ. –

2

Thật tuyệt khi các biểu tượng được đảm bảo duy nhất - có thể có một số hiệu ứng đẹp mà bạn không nhận được từ chuỗi (chẳng hạn như địa chỉ của chúng luôn chính xác như tôi tin).

Ngoài ra, chúng có ý nghĩa khác và bạn muốn sử dụng chúng ở các khu vực khác nhau, nhưng ruby ​​không quá nghiêm ngặt về loại nội dung đó, vì vậy tôi có thể hiểu câu hỏi của bạn.

13

Đó là sự thật, bạn không cần mã thông báo rất xấu vì lý do bộ nhớ. Máy tính của bạn chắc chắn có thể xử lý tất cả các loại xử lý chuỗi gnarly.

Tuy nhiên, ngoài việc nhanh hơn, mã thông báo có thêm lợi thế (đặc biệt là với màu bối cảnh) của la hét trực quan: XEM TÔI, TÔI LÀ TỪ KHÓA GIÁ TRỊ KEY-VALUE. Đó là một lý do đủ tốt để sử dụng chúng cho tôi.

Có nhiều lý do khác nữa ... và hiệu suất đạt được trên nhiều người trong số họ có thể nhiều hơn bạn nhận ra, đặc biệt là làm một cái gì đó như so sánh.

Khi so sánh hai ký hiệu ruby, trình thông dịch chỉ so sánh hai địa chỉ đối tượng. Khi so sánh hai chuỗi, thông dịch viên phải so sánh từng ký tự tại một thời điểm. Đó là loại tính toán có thể tăng lên nếu bạn đang làm rất nhiều điều này.

Ký hiệu có vấn đề về hiệu suất của riêng họ mặc dù ... chúng không bao giờ bị thu gom rác.

Đó là giá trị đọc bài viết này: http://www.randomhacks.net/articles/2007/01/20/13-ways-of-looking-at-a-ruby-symbol

+0

Thú vị. Tôi không nghĩ về thực tế rằng các biểu tượng không phải là rác thu thập được. Bài viết hay. Cảm ơn các liên kết. Đó là, "Mọi thứ bạn từng muốn biết về Ký hiệu" :) Hòa bình, dude. –

+0

Điều màu bối cảnh cũng là một điểm tốt. –

1

Một ít ký tự hơn để nhập. Đó là tất cả sự biện minh tôi cần phải sử dụng chúng trên các chuỗi cho các khóa băm, v.v.

+2

+1; Khi lần đầu tiên tôi đọc điều này, tôi tự nhủ: "Ồ, một lý do hời hợt!". Nhưng tôi càng nghĩ về nó, tôi càng nhận ra rằng đây là động lực lớn cho việc sử dụng biểu tượng của riêng tôi. Cảm ơn vì đã giúp tôi nhận ra điều gì đó về bản thân mình. –

1

Đây là lý do thực sự cho sự khác biệt: các chuỗi không bao giờ giống nhau. Mỗi trường hợp của một chuỗi là một đối tượng riêng biệt, ngay cả khi nội dung giống hệt nhau. Và hầu hết các thao tác trên chuỗi sẽ tạo các đối tượng chuỗi mới. Hãy xem xét những điều sau đây:

a = 'zowie' 
b = 'zowie' 
a == b   #=> true 

Trên bề mặt, nó muốn được dễ dàng để khẳng định rằng ab đều giống nhau. Các hoạt động thông thường nhất sẽ hoạt động như bạn mong đợi. Nhưng:

a.object_id #=> 2152589920 (when I ran this in irb) 
b.object_id #=> 2152572980 
a.equal?(b) #=> false 

Họ trông giống nhau, nhưng chúng đối tượng khác nhau. Ruby đã phải cấp phát bộ nhớ hai lần, thực hiện phương thức String#initialize hai lần, vv Chúng đang chiếm hai điểm riêng biệt trong bộ nhớ. Và hey!Nó được thậm chí nhiều niềm vui hơn khi bạn cố gắng thay đổi chúng:

a += ''  #=> 'zowie' 
a.object_id #=> 2151845240 

Ở đây chúng ta thêm -a và rời khỏi nội dung giống hệt nhau - nhưng Ruby không biết điều đó. Nó vẫn phân bổ một đối tượng String hoàn toàn mới, gán lại biến a cho nó, và đối tượng String cũ nằm xung quanh chờ đợi việc thu gom rác cuối cùng. Oh, và chuỗi rỗng '' cũng nhận được một đối tượng String tạm thời được cấp phát chỉ trong khoảng thời gian của dòng mã đó. Hãy thử và xem:

''.object_id #=> 2152710260 
''.object_id #=> 2152694840 
''.object_id #=> 2152681980 

Các đối tượng này có phân bổ nhanh trên bộ vi xử lý đa Gigahertz bóng bẩy của bạn không? Chắc chắn là vậy. Họ sẽ nhai nhiều RAM 4 GB của bạn? Không họ sẽ không. Nhưng làm điều đó một vài triệu lần, và nó bắt đầu tăng lên. Hầu hết các ứng dụng đều sử dụng các chuỗi tạm thời khắp nơi và mã của bạn có thể đầy các chuỗi ký tự trong các phương thức và vòng lặp của bạn. Mỗi chuỗi ký tự chuỗi đó sẽ phân bổ một đối tượng String mới, mỗi lần dòng mã được chạy. Vấn đề thực sự thậm chí không phải là sự lãng phí bộ nhớ; đó là thời gian lãng phí khi thu gom rác được kích hoạt quá thường xuyên và ứng dụng của bạn bắt đầu treo.

Ngược lại, hãy nhìn vào biểu tượng:

a = :zowie 
b = :zowie 
a.object_id #=> 456488 
b.object_id #=> 456488 
a == b   #=> true 
a.equal?(b) #=> true 

Khi biểu tượng :zowie được thực hiện, nó sẽ không bao giờ làm cho nhau. Mỗi khi bạn tham khảo một biểu tượng nhất định, bạn đang đề cập đến cùng một đối tượng. Không có thời gian hoặc bộ nhớ bị lãng phí khi phân bổ mới. Điều này cũng có thể là một nhược điểm nếu bạn quá điên rồ với họ - họ đang không bao giờ thu gom rác, vì vậy nếu bạn bắt đầu tạo ra vô số ký tự động từ đầu vào của người dùng, bạn đang mạo hiểm rò rỉ bộ nhớ vô tận. Nhưng đối với các chữ viết đơn giản trong mã của bạn, như các giá trị không đổi hoặc các khóa băm, chúng chỉ là hoàn hảo.

Điều đó có hữu ích không? Nó không phải về những gì ứng dụng của bạn làm một lần. Đó là về những gì nó làm hàng triệu lần.