2010-05-11 30 views
7

Tôi đang viết một trình phân tích cú pháp trong PHP mà phải có khả năng xử lý các chuỗi trong bộ nhớ lớn, vì vậy đây là một vấn đề hơi quan trọng. (ví dụ, vui lòng không "tối ưu hóa sớm" hãy châm lửa cho tôi, vui lòng)Chất nền của PHP hiệu quả như thế nào?

Chức năng hoạt động của substr như thế nào? Liệu nó có tạo ra một bản sao thứ hai của dữ liệu chuỗi trong bộ nhớ, hay nó tham khảo bản gốc? Tôi có nên lo lắng về việc gọi điện, ví dụ: $str = substr($str, 1); trong vòng lặp không?

+2

tôi sẽ nghĩ rằng việc chuyển nhượng sẽ là kẻ giết người, không phải là substr. – CaffGeek

Trả lời

3

Để tiếp tục nhận xét của Chad, mã của bạn sẽ yêu cầu cả hai chuỗi (đầy đủ, và toàn-một-trừ-ký tự đầu tiên) trong bộ nhớ cùng một lúc (mặc dù không phải do sự phân công như Chad đã nêu). Xem:

$string = str_repeat('x', 1048576); 
printf("MEM: %d\nPEAK: %d\n", memory_get_usage(), memory_get_peak_usage()); 

substr($string, 1); 
printf("MEM: %d\nPEAK: %d :-(\n", memory_get_usage(), memory_get_peak_usage()); 

$string = substr($string, 1); 
printf("MEM: %d\nPEAK: %d :-(\n", memory_get_usage(), memory_get_peak_usage()); 

Đầu ra một cái gì đó tương tự (giá trị bộ nhớ là tính bằng byte):

MEM: 1093256 
PEAK: 1093488 
MEM: 1093280 
PEAK: 2142116 :-(
MEM: 1093276 
PEAK: 2142116 :-(
1

Có, bạn nên cẩn thận thực hiện bất kỳ thao tác chuỗi nào bên trong vòng lặp vì các bản sao mới của chuỗi sẽ được tạo trên mỗi lần lặp.

+0

Tôi không phải là một anh chàng php, vì vậy bạn có thể chỉ đơn giản là nói không. Trong Java, nó chỉ tạo ra một tham chiếu mới đến cùng mảng mảng bất biến. Vì vậy, trong khi nó tạo ra một đối tượng String mới, nó không lưu trữ nhiều bản sao của mảng char bên dưới. Nó chỉ đơn thuần tuyên bố sự khác biệt. Có php thực sự tạo ra một bản sao mới của mảng char? Hoặc chỉ tham khảo cùng một mảng char. – corsiKa

4

Nếu bạn đang thực sự xem xét hiệu quả, bạn sẽ cần giữ con trỏ - ý tôi là chỉ mục - với chuỗi của bạn. Nhiều hàm chuỗi chấp nhận một offset để bắt đầu hoạt động (như tham số thứ ba của strpos()). Thông thường tôi sẽ khuyên bạn nên viết một đối tượng để bọc chức năng này, nhưng nếu bạn đang mong đợi để sử dụng rất nhiều, điều đó có thể gây ra một nút cổ chai hiệu suất. Dưới đây là một ví dụ về những gì tôi có ý nghĩa (không có OO):

while ($whatever) { 
    $pos = strpos($string, $myToken, $startIndex); 
    # do something using $pos 
    $startIndex = $pos; 
} 

Nếu bạn muốn, bạn có thể viết lớp wrapper của riêng bạn mà không những chuỗi hoạt động và xem nếu nó có ảnh hưởng tốc độ:

class _String { 
    private $string; 
    private $startIndex; 
    private $length; 
    public function __construct($string) { 
     $this->string = $string; 
     $this->startIndex = 0; 
     $this->length = strlen($string); 
    } 
    public function substr($from, $length = NULL) { 
     $this->startIndex = $from; 
     if ($length !== NULL) { 
      $this->endIndex = $from + $length; 
     } 
    } 
    # other functions you might use 
    # ... 
} 
+0

Các chuỗi Java thông thường tự động thực hiện những việc này. Tại sao không PHP? – Pacerier

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