2010-08-30 22 views
11

Trích dẫn từ PerlMonks: The difference between my and local,Làm thế nào là "của tôi" nhanh hơn "địa phương" trong Perl?

Nhưng trong cuộc sống thực, họ làm việc hầu như giống nhau không? Vâng. Sắp xếp. Vậy khi nào bạn nên sử dụng chúng?

Sử dụng của tôi khi bạn có thể (đó là nhanh hơn so với địa phương) ...

Tôi biết các từ vựng vs chênh lệch Phạm vi năng động giữa mylocal, như đã thảo luận trong this SO thread, nhưng tôi không chắc chắn lý do tại sao my là "nhanh hơn".

Chúng tôi có ý nghĩa gì khi nói rằng biến số my nhanh hơn biến số local trong Perl?

+1

Hãy là người * * địa phương - cố gắng đọc * mã * của tôi. –

+12

Không sử dụng địa phương so với của tôi bởi vì một là nhanh hơn so với khác; sử dụng bất cứ điều gì là chính xác nhất cho những gì bạn muốn đạt được (thường là của tôi). – ysth

+1

Nói cách khác: không chỉ đếm thời gian một chương trình cần chạy, trên tất cả hãy đếm thời gian cần một lập trình viên để gỡ rối và sửa chữa nó. Lập trình viên đắt hơn nhiều so với máy tính chạy chương trình. – reinierpost

Trả lời

19

Sử dụng local trên biến có nghĩa là trạng thái trước đó cần được đẩy lên ngăn xếp ở đâu đó và khôi phục lại khi phạm vi cục bộ bị thoát. Sử dụng my trên một biến chỉ đơn giản là tạo ra một biến hoàn toàn mới mà bóng biến trước đó có cùng tên - biến trước đó hoàn toàn bị ảnh hưởng, và không cần phải được lưu ở bất cứ đâu. Nó chỉ đơn giản là nằm trong chờ đợi khi phạm vi địa phương được thoát ra và nó có thể nhìn thấy một lần nữa.

Điều này đẩy/popping vào một ngăn xếp có nguồn lực; có rất nhiều công việc dưới mui xe để đảm bảo rằng nó hoạt động tốt. (Xem xét các trường hợp như ngoại lệ bị ném trong khi ở phạm vi địa phương hoặc xử lý tín hiệu đang được thực thi. Tôi chắc chắn bạn có thể nghĩ nhiều hơn.)

Ngoài hiệu quả hơn, sử dụng my là hợp lý hơn nhiều. Là một lập trình viên giới thiệu biến cục bộ $ foo, bạn không cần phải lo lắng về lý do ngữ nghĩa cho phiên bản $ foo trước đó, dữ liệu nào có thể có trong đó, hoặc thực sự nếu có một $ foo đã được tạo. Nếu đôi khi xuống đường, tuyên bố $ foo trước đó bị xóa, mã số local $foo của bạn sẽ bị hỏng, nhưng my $foo sẽ hoàn toàn hài lòng. Hãy là một lập trình viên tốt và giữ mã của bạn trong các phần được đóng gói tốt, có nghĩa là sử dụng phạm vi từ vựng nhiều nhất có thể. Có thể viết một ứng dụng lớn và không bao giờ cần các biến của gói/phạm vi toàn cục, đặc biệt khi bạn sử dụng các lớp OO được thiết kế tốt.

+3

@Evan Carroll: không, nó sử dụng một ngăn xếp được gọi là savestack – ysth

+8

Cụ thể có một "pad đầu từ vựng" đã được phân bổ cho mỗi phạm vi từ vựng mà Perl đặt từ vựng mới vào. Khi phạm vi thoát ra, miếng đệm đầu sẽ biến mất. Ngoài ra, local() phải xử lý nội địa hoá và phục hồi các phần tử băm và mảng riêng lẻ ('local $ h {key}'). Cuối cùng, các biến gắn kết được xử lý đặc biệt theo địa phương, các phương thức FETCH và STORE của chúng được gọi khi chúng được bản địa hóa và phục hồi. Bất cứ điều gì phải thậm chí xem xét buộc là chậm hơn vì nó phải kiểm tra xem một biến có bị ràng buộc hay không. – Schwern

12

local có thể chậm hơn do cần phải lưu giá trị cũ, nhưng tốc độ localmy không được đưa vào thảo luận. Tiết kiệm tốc độ là âm lượng:

  Rate local my 
local 7557305/s -- -2% 
my 7699334/s 2% -- 

và các tính năng của hai là hoàn toàn khác nhau. Kết quả ở trên đến từ điểm chuẩn sau:

#!/usr/bin/perl 

use strict; 
use warnings; 

use Benchmark; 

our $x; 

my %subs = (
    local => sub { 
     local $x = 42; 
     return $x; 
    }, 
    my => sub { 
     my $x = 42; 
     return $x; 
    } 
); 

for my $sub (keys %subs) { 
    print "$sub: ", $subs{$sub}(), "\n"; 
} 

Benchmark::cmpthese -1, \%subs; 
+3

Sự khác biệt về tốc độ sẽ trở nên rõ ràng hơn nhiều khi bạn giới thiệu một số trường hợp mà Schwern mô tả trong câu trả lời của tôi. – Ether

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