>백엔드 개발 >PHP 튜토리얼 >생성기 및 Nikic/ITER로 메모리 성능이 향상됩니다

생성기 및 Nikic/ITER로 메모리 성능이 향상됩니다

Joseph Gordon-Levitt
Joseph Gordon-Levitt원래의
2025-02-16 09:17:10386검색
PHP 반복자 및 생성기 : 대형 데이터 세트의 효율적인 처리를위한 강력한 도구 배열 및 반복은 모든 응용 프로그램의 초석입니다. 새로운 도구를 얻으면 배열을 사용하는 방식도 향상되어야합니다. 예를 들어 생성기는 새로운 도구입니다. 처음에는 배열 만있는 다음 자신의 클래스 어레이 구조 (반복자라고 함)를 정의 할 수 있습니다. 그러나 PHP 5.5 이후, 우리는 발전기라는 클래스 반복 구조를 신속하게 만들 수 있습니다.

생성기는 함수처럼 보이지만 반복자로 사용할 수 있습니다. 그들은 우리에게 본질적으로 중단 가능하고 반복 가능한 함수를 만들기위한 간단한 구문을 제공합니다. 그들은 놀랍습니다!

우리는 발전기를 사용할 수있는 여러 영역을 살펴보고 발전기를 사용할 때주의를 기울여야하는 몇 가지 문제를 탐색합니다. 마지막으로, 우리는 재능있는 Nikita Popov가 만든 훌륭한 도서관을 배울 것입니다.

샘플 코드는 https://github.com/sitepoint-editors/generators-and-기에서 찾을 수 있습니다. Memory Performance Boosts with Generators and Nikic/Iter 키 포인트

Generator (PHP 5.5 이후 사용 가능)는 중단 가능하고 반복 가능한 함수를 생성하고 대규모 데이터 세트의 처리를 단순화하며 메모리 성능을 향상시키는 반복기를 만드는 강력한 도구입니다.

Nikita Popov는 반복자 및 발전기와 함께 사용할 수있는 기능을 소개하는 Nikic/Iter 라이브러리를 생성하여 불필요한 중간 배열 생성을 피함으로써 크게 메모리를 저장합니다.

생성기 및 Nikic/ITER 라이브러리는 대형 CSV 파일로 작업 할 때 특히 유용하며, 이는 한 번에 메모리에 모두로드하지 않고 큰 데이터 세트를 처리 할 수 ​​있습니다.

생성기는 메모리 성능을 크게 향상시킬 수 있지만 및 와 호환되지 않는 것과 같은 일부 고유 한 도전을 제시하며, Nikic/Iter와 같은 다른 도구가 그러한 데이터를 처리하기 위해 필요합니다.

질문

당신이 관계형 데이터가 많고 사전 로딩을하고 싶다고 가정합니다. 데이터가 쉼표로 구분되었을 수 있습니다. 각 데이터 유형을로드하고 함께 그룹화해야합니다.
    다음 간단한 코드로 시작할 수 있습니다
  • 그런 다음 반복 또는 고차 함수를 통해 관련 요소를 연결하려고 시도 할 수 있습니다.
  • 좋아 보인다? 그렇다면 많은 CSV 파일이 구문 분석 할 때 어떻게됩니까? 메모리 사용량을 조금 분석 해 봅시다 ...
  • (샘플 코드에는 <li>가 포함되어 있으며,이 CSV 파일을 생성하는 데 사용할 수 있습니다 ...) <large> 큰 CSV 파일이있는 경우이 코드는이 배열을 묶는 데 얼마나 많은 메모리가 필요한지 표시해야합니다. PHP는 모든 것을 메모리에 유지해야하기 때문에 읽어야 할 파일과 동일한 크기입니다. </large> </li> <li> 발전기가 구출됩니다! <code>array_filter 이 문제를 개선하는 한 가지 방법은 발전기를 사용하는 것입니다. 당신이 그들에게 익숙하지 않다면, 지금은 더 많은 것을 배우기에 좋은시기입니다. array_map 생성기를 사용하면 한 번에 소량의 총 데이터를로드 할 수 있습니다. 발전기와 많은 일을 할 필요가 없습니다 :

    CSV 데이터를 반복하면 필요한 메모리의 양이 즉시 줄어들 것임을 알 수 있습니다.
    <code class="language-php">function readCSV($file) {
        $rows = [];
    
        $handle = fopen($file, "r");
    
        while (!feof($handle)) {
            $rows[] = fgetcsv($handle);
        }
    
        fclose($handle);
    
        return $rows;
    }
    
    $authors = array_filter(
        readCSV("authors.csv")
    );
    
    $categories = array_filter(
        readCSV("categories.csv")
    );
    
    $posts = array_filter(
        readCSV("posts.csv")
    );</code>
    메모리 메모리 사용을 전에 본 적이 있다면 이제 킬로 바이트가 표시됩니다. 이것은 큰 개선이지만 문제가없는 것은 아닙니다.

    우선,

    <code class="language-php">function filterByColumn($array, $column, $value) {
        return array_filter(
            $array, function($item) use ($column, $value) {
                return $item[$column] == $value;
            }
        );
    }
    
    $authors = array_map(function($author) use ($posts) {
        $author["posts"] = filterByColumn(
            $posts, 1, $author[0]
        );
    
        // 对 $author 进行其他更改
    
        return $author;
    }, $authors);
    
    $categories = array_map(function($category) use ($posts) {
        $category["posts"] = filterByColumn(
            $posts, 2, $category[0]
        );
    
        // 对 $category 进行其他更改
    
        return $category;
    }, $categories);
    
    $posts = array_map(function($post) use ($authors, $categories) {
        foreach ($authors as $author) {
            if ($author[0] == $post[1]) {
                $post["author"] = $author;
                break;
            }
        }
    
        foreach ($categories as $category) {
            if ($category[0] == $post[1]) {
                $post["category"] = $category;
                break;
            }
        }
    
        // 对 $post 进行其他更改
    
        return $post;
    }, $posts);</code>
    는 발전기와 작동하지 않습니다. 이러한 유형의 데이터를 처리하기위한 다른 도구를 찾아야합니다. 다음은 시도 할 수있는 도구입니다!

    이 라이브러리는 반복자 및 발전기와 함께 사용할 수있는 일부 기능을 소개합니다. 그렇다면 메모리에 데이터를 저장하지 않고 어떻게이 관련 데이터를 모두 얻습니까?

    array_filter 이것은 더 간단 할 수 있습니다 : array_map (각 데이터 소스를 다시 읽는 것은 매번 비효율적입니다. 메모리에 작은 관련 데이터 (예 : 저자 및 범주)를 저장하는 것을 고려하십시오 ...) 다른 흥미로운 것들

    Nikic의 도서관의 경우, 이것은 빙산의 일각 일뿐입니다! 배열 (또는 반복자/생성기)을 평평하게하고 싶었던 적이 있습니까?
    <code class="language-php">function formatBytes($bytes, $precision = 2) {
        $kilobyte = 1024;
        $megabyte = 1024 * 1024;
    
        if ($bytes >= 0 && $bytes < $kilobyte) {
            return $bytes . " b";
        }
    
        if ($bytes >= $kilobyte && $bytes < $megabyte) {
            return round($bytes / $kilobyte, $precision) . " kb";
        }
    
        return round($bytes / $megabyte, $precision) . " mb";
    }
    
    print "memory:" . formatBytes(memory_get_peak_usage());</code>

    당신은 및 와 같은 함수를 사용하여 반복 가능한 변수의 조각을 반환 할 수 있습니다 :

    생성기를 더 많이 사용하면 항상 재사용 할 필요는 없습니다. 다음 예를 고려하십시오 :
    <code class="language-php">function readCSVGenerator($file) {
        $handle = fopen($file, "r");
    
        while (!feof($handle)) {
            yield fgetcsv($handle);
        }
    
        fclose($handle);
    }</code>
    코드를 실행하려고하면 "닫힌 생성기를 가로지 못하는 것"이라는 예외가 표시됩니다. 이 라이브러리의 각 반복 기능에는 교체 가능한 해당 기능이 있습니다.

    이 매핑 함수를 여러 번 사용할 수 있습니다. 당신은 당신의 자신의 발전기를 다시 표시 할 수있게 만들 수도 있습니다 :

    당신이 그것에서 얻는 것은 재사용 가능한 발전기입니다!
    <code class="language-php">foreach (readCSVGenerator("posts.csv") as $post) {
        // 使用 $post 执行某些操作
    }
    
    print "memory:" . formatBytes(memory_get_peak_usage());</code>
    결론

    고려해야 할 모든 루프 작업의 경우 생성기가 옵션 일 수 있습니다. 그들은 심지어 다른 것들에도 유용합니다. 언어 기능이 불충분 한 경우 Nikic의 라이브러리는 많은 고차 기능을 제공합니다.

    이미 발전기를 사용하고 있습니까? 성능 향상을 위해 자신의 응용 프로그램에서 구현하는 방법에 대한 더 많은 예를보고 싶습니까? 제발 알려주세요! (FAQS 부분은 원래 텍스트와 유사하며 공간을 절약하기 위해 여기서 생략됩니다. FAQ 부품은 필요에 따라 선택적으로 유지되거나 재구성 될 수 있습니다.)

위 내용은 생성기 및 Nikic/ITER로 메모리 성능이 향상됩니다의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.