Share This
//PHP Generators

PHP Generators

Đã bao giờ các bạn gặp phải tình huống này chưa?
Đây là lỗi mà bất cứ lập trình viên PHP nào cũng có thể gặp nếu tiến trình đang thực thi sử dụng bộ nhớ RAM vượt quá giới hạn cho phép.

Chúng ta cùng đi đến 1 ví dụ cụ thể nhé:

private function range() {
    $a = [];
 
    for ($i = 0; $i < PHP_INT_MAX; $i++) {
        $a[] = $i;
    }
 
    return $a;
}
 
foreach ($this->range() as $value) {
    echo $value;
}

Đoạn code trên sẽ tạo một array từ 0 đến PHP_INT_MAX (là giá trị số nguyên cực đại mà version PHP hiện tại cung cấp) và in giá trị ra màn hình. Khi chúng ta chạy đoạn code trên thì sẽ gặp phải lỗi như đã đề cập trước đó.

Vậy làm sao để có thể giải quyết lỗi này nếu như vô tình gặp phải? Có 1 cách là tăng giới hạn bộ nhớ “memory_limit” lên trong config php.ini.

; Maximum amount of memory a script may consume
; https://php.net/memory-limit
 memory_limit = 128M

Nhưng đây không phải là cách tối ưu để giải quyết vấn đề. Chúng ta chỉ mới chạy 1 đoạn code nhỏ đã xảy ra lỗi tràn bộ nhớ thì có vẻ không ổn lắm. Vậy nên, thay vì tăng giới hạn bộ nhớ thì chúng ta hãy thử sử dụng PHP Generators để giảm bộ nhớ được sử dụng xem hiệu quả như thế nào nhé!

PHP GENERATORS LÀ GÌ?

PHP Generators là một tính năng mạnh mẽ được giới thiệu trong PHP 5.5. Tính năng này cho phép bạn tạo ra các hàm generator, các hàm generator không trả về toàn bộ danh sách giá trị cùng một lúc, thay vào đó hàm sẽ tạo và trả về từng giá trị một khi cần thiết. Chính điều này giúp tiết kiệm bộ nhớ đáng kể, cho phép xử lý dữ liệu mà không cần lưu trữ toàn bộ tập dữ liệu trong bộ nhớ.

SỬ DỤNG PHP GENERATORS

Quay lại đoạn code trên chúng ta hãy thay đổi ở hàm “range()”, thay vì tạo 1 array (chuỗi) và return (trả về) tất cả giá trị trong array thì chúng ta chỉ lặp qua các giá trị với từ khóa yield. Có thể hiểu đơn giản yield sẽ trả về giá trị nhưng chỉ khi ta gọi đến nó mà không cần phải lưu tất cả giá trị vào trong bộ nhớ như đoạn code ban đầu và lúc này function của chúng ta sẽ trở thành 1 generator function.

private function range() {
    for ($i = 0; $i < PHP_INT_MAX; $i++) {
        yield $i;
    }
}
 
foreach ($this->range() as $value) {
    echo $value;
}

CÁC PHƯƠNG THỨC CỦA PHP GENERATORS

public current(): mixed
public getReturn(): mixed
public key(): mixed
public next(): void
public rewind(): void
public send(mixed $value): mixed
public throw(Throwable $exception): mixed
public valid(): bool
public __wakeup(): void

CÁCH THỨC HOẠT ĐỘNG

Hãy thử 1 ví dụ khác:

function myGeneratorFunction()
{
      echo 'One' . "<br>";
      yield 'first return value' . "<br>";
 
      echo 'Two' . "<br>";
      yield 'second return value' . "<br>";
 
      echo 'my return value' ;
}
 
$iterator = myGeneratorFunction();
 
$firstValue = $iterator->current();
echo $firstValue;
 
$iterator->next();
$secondValue = $iterator->current();
echo $secondValue;
 
$iterator->next();
echo $iterator->getReturn();

Output

One
first return value
Two
second return value
my return value

Khi chúng ta gọi $iterator->current() thì function sẽ thực thi và hiển thị ra giá trị “One”, sau đó sẽ dừng lại khi gặp từ khóa yield đầu tiên. Giá trị của từ khóa yield đầu tiên sẽ được trả về và gán vào $firstValue.

Kế tiếp khi ta gọi $iterator->next(); thì generator sẽ thực thi function trước đó ngay tại điểm mà chúng ta đã dừng ở từ khóa yield đầu tiên. Lúc này sẽ in ra màn hình giá trị ‘Two’ và trả về giá trị của từ khóa yield thứ 2 vào $secondValue. Tiếp tục như thế, function sẽ lấy giá trị trả về từ keyword return để gọi $iterator->next(); và dùng $iterator->getReturn(); lấy giá trị trả về.

Qua ví dụ trên chúng ta có thể hiểu đơn giản là từ khóa yield như 1 nút pause function, function sẽ tạm dừng thực thi khi gặp từ khóa yield này và sẽ tiếp tục khi chúng ta duyệt qua bằng cách gọi $iterator->next().

RETURNING KEYS

Sử dụng yield trả về key ⇒ value

private function range()
{
    for ($i = 0; $i < PHP_INT_MAX; $i++) {
        yield "key {$i}" => "value {$i}";
    }
}
 
foreach ($this->rangeKeyValue() as $key => $value) {
  echo "{$key} -> {$value} <br>";
}

Output

key 0 -> value 0
key 1 -> value 1
key 2 -> value 2
key 3 -> value 3
key 4 -> value 4
key 5 -> value 5
…

TRUYỀN THAM SỐ VÀO TRONG GENERATORS

Chúng ta có thể truyền tham số vào generators để làm 1 việc gì đó như dừng function lại chẳng hạn, cách làm như sau:

private function range()
{
    for ($i = 0; $i < PHP_INT_MAX; $i++) {
         $value = yield $i;
 
         if ($value === 'stop') {
            return;
         }
    }
}
 
$generator = $this->range();
 
foreach ($generator as $value) {
    if ($value === 5) {
        $generator->send('stop');
    }
 
    echo "current value is {$value} <br>";
}

Output

current value is 0
current value is 1
current value is 2
current value is 3
current value is 4
current value is 5

LỢI ÍCH SỬ DỤNG

Khi ứng dụng của chúng ta cần xử lý một file log với kích thước lên tới hàng gigabyte để lưu vào database thì việc đọc hết nội dung trong file log một lần để xử lý sẽ dẫn đến lỗi bị tràn bộ nhớ. Việc sử dụng PHP Generators để thực hiện đọc lần lượt từng dòng trong file log để xử lý sẽ giảm thiểu tối đa bộ nhớ được sử dụng giúp cho code của chúng ta tránh được việc chiếm quá nhiều tài nguyên của hệ thống.

KẾT LUẬN

Đối với những hệ thống cần xử lý một lượng data lớn, việc cân nhắc và lựa chọn cách làm sao cho an toàn và tốt nhất là điều cần thiết.
PHP Generators cung cấp cho chúng ta 1 giải pháp mạnh mẽ nhằm tiết kiệm bộ nhớ, giúp server của chúng ta chạy mượt mà và ổn định. Cũng như tránh những lỗi quá tải có thể xảy đến với hệ thống, có thể làm gián đoạn trải nghiệm, gây mất thiện cảm của người dùng trong quá trình sử dụng.

Huỳnh Hữu Phát
Web Developer

ỨNG TUYỂN







    Chế độ phúc lợi

    CHÍNH SÁCH LƯƠNG & THƯỞNG

    Thấu hiểu tâm tư nguyện vọng của nhân viên, công ty Rivercrane Việt Nam đặc biệt thiết lập chế độ xét tăng lương định kỳ 2lần/năm. Xét đánh giá vào tháng 06 và tháng 12 hàng năm và thay đổi lương vào tháng 01 và tháng 07 hàng năm. Ngoài ra, nhân viên còn được thưởng thành tích định kỳ cho các cá nhân xuất sắc trong tháng, năm.

    CHẾ ĐỘ ĐÀO TẠO TẠI NHẬT

    Luôn luôn mong muốn các kỹ sư và nhân viên trong công ty có cái nhìn toàn diện về lập trình những mảng kỹ thuật trên thế giới, công ty Rivercrane Việt Nam quyết định chế độ 3 tháng 1 lần đưa nhân viên đi học tập tại Nhật. Các bạn kỹ sư hoàn toàn đều có thể quyết định khả năng phát triển bản thân theo hướng kỹ thuật hoặc theo hướng quản lý.

    CHẾ ĐỘ ĐI DU LỊCH HÀNG NĂM

    Không chỉ đưa đến cho nhân viên những công việc thử thách thể hiện bản thân, công ty Rivercrane Việt Nam muốn nhân viên luôn thích thú khi đến với những chuyến hành trình thú vị hàng năm. Những buổi tiệc Gala Dinner sôi động cùng với những trò chơi Team Building vui nhộn sẽ giúp cho đại gia đình Rivercrane thân thiết hơn.

    CHẾ ĐỘ EVENT CÔNG TY

    Những hoạt động Team building, Company Building, Family Building, Summer Holiday, Mid-Autumn Festival… sẽ là những khoảnh khắc gắn kết đáng nhớ của mỗi một nhân viên trong từng dự án, hoặc sẽ là những điều tự hào khi giới thiệu công ty mình với với gia đình thân thương, cùng nhau chia sẻ yêu thương với thông điệp “We are One”

    BẢO HIỂM

    Công ty Rivercrane Việt Nam đảm bảo tham gia đầy đủ chế độ Bảo hiểm xã hội, bảo hiểm y tế và bảo hiểm thất nghiệp. Cam kết chặt chẽ về mọi thủ tục phát sinh công ty đều hỗ trợ và tiến hành cho nhân viên từ đầu đến cuối. Những chế độ bảo hiểm khác công ty cũng đặc biệt quan tâm và từng bước tiến hành.

    CHẾ ĐỘ PHÚC LỢI KHÁC

    Hỗ trợ kinh phí cho các hoạt động văn hóa, văn nghệ, thể thao; Hỗ trợ kinh phí cho việc mua sách nghiên cứu kỹ thuật; Hỗ trợ kinh phí thi cử bằng cấp kỹ sư, bằng cấp dành cho ngôn ngữ. Hỗ trợ kinh phí tham gia các lớp học về quản lý kỹ thuật bên ngoài; Các hỗ trợ phúc lợi khác theo quy định công ty…

    CÔNG VIỆC TƯƠNG TỰ

    © 2012 RiverCrane Vietnam. All rights reserved.

    Close