>  기사  >  백엔드 개발  >  루프 본문 내에서 array_push()를 사용하지 마세요.

루프 본문 내에서 array_push()를 사용하지 마세요.

藏色散人
藏色散人앞으로
2019-10-30 14:08:362518검색

제목은 루프 본문에 array_push()를 사용하지 마세요입니다. 사실 이것은 이 기사의 결론 중 하나일 뿐입니다.

PHP 언어에서 배열에 요소를 추가하는 방법을 살펴보겠습니다.

배열에 요소 추가

우리는 PHP를 알고 있습니다. 배열 스택의 끝에 요소를 추가하는 방법에는 두 가지가 있습니다

$a = []; array_push($a,'test');
$a[] = 'test';

이 두 방법의 차이점은 무엇인가요?

먼저 성능을 비교해 보겠습니다

ArrayPush
一个 ArrayPush 类
pushEachOne() 循环体中使用 array_push() 来为 $a 追加元素
pushEachTwo() 循环体中使用 $a[] = $var 来为 $a 追加元素
/**
 * Class ArrayPush
 */
class ArrayPush
{
    /**
     * @param int $times
     * @return array
     */
    public static function pushEachOne(int $times): array
    {
        $a = [];
        $b = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
        for ($i = 0; $i < $times; $i++) {
            array_push($a, $b[$i % 10]);
        }
        return $a;
    }
    /**
     * @param int $times
     * @return array
     */
    public static function pushEachTwo(int $times): array
    {
        $a = [];
        $b = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
        for ($i = 0; $i < $times; $i++) {
            $a[] = $b[$i % 10];
        }
        return $a;
    }
}

테스트할 코드 작성

1백만 개의 요소를 추가하는 루프

ini_set(&#39;memory_limit&#39;, &#39;4000M&#39;);
$timeOne = microtime(true);
$a       = ArrayPush::pushEachOne(1000000);
echo &#39;count pushEachOne result | &#39; . count($a) . PHP_EOL;
$timeTwo = microtime(true);
$b       = ArrayPush::pushEachTwo(1000000);
echo &#39;count pushEachTwo result | &#39; . count($b) . PHP_EOL;
$timeThree = microtime(true);
echo PHP_EOL;
echo &#39;pushEachOne | &#39; . ($timeTwo - $timeOne) . PHP_EOL;
echo &#39;pushEachTwo | &#39; . ($timeThree - $timeTwo) . PHP_EOL;
echo PHP_EOL;

결과

결과는 자명합니다. $a[] = 사용하는 것보다 빠릅니다. array_push() 거의 세 번

count pushEachOne result | 1000000
count pushEachTwo result | 1000000
pushEachOne | 1.757071018219
pushEachTwo | 0.67165303230286

Analytic

array_push () 왜 느린가요? 너무 느린데, 사용할 수 있는 시나리오가 있나요?

공식 매뉴얼

array_push — 将一个或多个单元压入数组的末尾(入栈)
array_push ( array &$array , mixed $value1 [, mixed $... ] ) : int
array_push() 将 array 当成一个栈,并将传入的变量压入 array 的末尾。array 的长度将根据入栈变量的数目增加。和如下效果相同:
<?php$array[] = $var;?>

을 입력하고 각 입력 값에 대해 위 작업을 반복하세요.

● 참고: array_push()를 사용하여 배열에 유닛을 추가하는 경우, 함수를 호출하는데 추가적인 부담이 없기 때문에 $array[] =를 사용하는 것이 더 좋습니다.

● 참고: array_push()는 첫 번째 인수가 배열이 아닌 경우 경고를 발행합니다. 이는 새 배열을 생성하는 $var[]의 동작과 다릅니다.

공식 소스 코드

소스 코드에서 array_push()

/* {{{ proto int array_push(array stack, mixed var [, mixed ...])
   Pushes elements onto the end of the array */
PHP_FUNCTION(array_push)
{
    zval   *args,       /* Function arguments array */
           *stack,      /* Input array */
            new_var;    /* Variable to be pushed */
    int i,              /* Loop counter */
        argc;           /* Number of function arguments */
    //这一段是函数的参数解析
    ZEND_PARSE_PARAMETERS_START(2, -1)
        Z_PARAM_ARRAY_EX(stack, 0, 1)
        Z_PARAM_VARIADIC(&#39;+&#39;, args, argc)
    ZEND_PARSE_PARAMETERS_END();
    /* For each subsequent argument, make it a reference, increase refcount, and add it to the end of the array */
    for (i = 0; i < argc; i++) {
        //拷贝一个
        ZVAL_COPY(&new_var, &args[i]);
        //插入新数值,自动
        if (zend_hash_next_index_insert(Z_ARRVAL_P(stack), &new_var) == NULL) {
            if (Z_REFCOUNTED(new_var)) Z_DELREF(new_var);
            php_error_docref(NULL, E_WARNING, "Cannot add element to the array as the next element is already occupied");
            RETURN_FALSE;
        }
    }
    /* Clean up and return the number of values in the stack */
    RETVAL_LONG(zend_hash_num_elements(Z_ARRVAL_P(stack)));
}
/* }}} */

$a[] =를 살펴보세요. 구현은 지정된 변수 유형에 따라 일련의 Zend_API 함수 add_next_index_*를 호출하는 것입니다. 앞으로는 zend_hash_next_index_insert가 직접 호출될 예정입니다

ZEND_API int add_next_index_long(zval *arg, zend_long n) /* {{{ */
{
    zval tmp;
    ZVAL_LONG(&tmp, n);
    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
}
/* }}} */
ZEND_API int add_next_index_null(zval *arg) /* {{{ */
{
    zval tmp;
    ZVAL_NULL(&tmp);
    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
}
/* }}} */
ZEND_API int add_next_index_bool(zval *arg, int b) /* {{{ */
{
    zval tmp;
    ZVAL_BOOL(&tmp, b);
    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
}
/* }}} */
ZEND_API int add_next_index_resource(zval *arg, zend_resource *r) /* {{{ */
{
    zval tmp;
    ZVAL_RES(&tmp, r);
    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
}
/* }}} */
ZEND_API int add_next_index_double(zval *arg, double d) /* {{{ */
{
    zval tmp;
    ZVAL_DOUBLE(&tmp, d);
    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
}
/* }}} */
ZEND_API int add_next_index_str(zval *arg, zend_string *str) /* {{{ */
{
    zval tmp;
    ZVAL_STR(&tmp, str);
    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
}
/* }}} */
ZEND_API int add_next_index_string(zval *arg, const char *str) /* {{{ */
{
    zval tmp;
    ZVAL_STRING(&tmp, str);
    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
}
/* }}} */
ZEND_API int add_next_index_stringl(zval *arg, const char *str, size_t length) /* {{{ */
{
    zval tmp;
    ZVAL_STRINGL(&tmp, str, length);
    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
}
/* }}} */
ZEND_API int add_next_index_zval(zval *arg, zval *value) /* {{{ */
{
    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), value) ? SUCCESS : FAILURE;
}
/* }}} */

Summary

위의 분석 결과 array_push()는 존재 의미가 없는 것 같습니다.

● 일반적으로 array_push()의 성능이 너무 낮으므로 $array[] =를 사용하여 교체해야 합니다.

● 한 번에 여러 단위를 추가하는 경우 array_push()를 사용하세요

위 내용은 루프 본문 내에서 array_push()를 사용하지 마세요.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 learnku.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제