주어진 변수가 얼마나 많은 메모리를 사용하는지 알아내는 함수가 PHP (또는 PHP 확장)에 있습니까? sizeof
요소 / 속성 수만 알려줍니다.
memory_get_usage
전체 스크립트에서 사용하는 메모리 크기를 제공한다는 점에서 도움이됩니다 . 단일 변수에 대해 이것을 수행하는 방법이 있습니까?
이것은 개발 시스템에 있으므로 확장 또는 디버그 도구를로드 할 수 있습니다.
주어진 변수가 얼마나 많은 메모리를 사용하는지 알아내는 함수가 PHP (또는 PHP 확장)에 있습니까? sizeof
요소 / 속성 수만 알려줍니다.
memory_get_usage
전체 스크립트에서 사용하는 메모리 크기를 제공한다는 점에서 도움이됩니다 . 단일 변수에 대해 이것을 수행하는 방법이 있습니까?
이것은 개발 시스템에 있으므로 확장 또는 디버그 도구를로드 할 수 있습니다.
답변:
아마도 메모리 프로파일 러가 필요할 것입니다. 나는 정보를 수집했지만 도움이 될만한 몇 가지 중요한 것을 복사했습니다.
아시다시피 Xdebug는 2. * 버전부터 메모리 프로파일 링 지원을 중단했습니다. 여기에서 "제거 된 기능"문자열을 검색하십시오 : http://www.xdebug.org/updates.php
제거 된 기능
제대로 작동하지 않았기 때문에 메모리 프로파일 링에 대한 지원을 제거했습니다.
https://github.com/arnaud-lb/php-memory-profiler . 이 기능을 활성화하기 위해 Ubuntu 서버에서 수행 한 작업입니다.
sudo apt-get install libjudy-dev libjudydebian1
sudo pecl install memprof
echo "extension=memprof.so" > /etc/php5/mods-available/memprof.ini
sudo php5enmod memprof
service apache2 restart
그리고 내 코드에서 :
<?php
memprof_enable();
// do your stuff
memprof_dump_callgrind(fopen("/tmp/callgrind.out", "w"));
마지막으로 KCachegrind로callgrind.out
파일을 엽니 다.
먼저 https://code.google.com/p/gperftools/ 에서 최신 패키지를 다운로드하여 Google gperftools 를 설치합니다 .
그리고 언제나처럼 :
sudo apt-get update
sudo apt-get install libunwind-dev -y
./configure
make
make install
이제 코드에서 :
memprof_enable();
// do your magic
memprof_dump_pprof(fopen("/tmp/profile.heap", "w"));
그런 다음 터미널을 열고 실행하십시오.
pprof --web /tmp/profile.heap
pprof 는 아래와 같이 기존 브라우저 세션에 새 창을 만듭니다.
로 Xhprof 및 Xhgui 그 문제 순간에 있다면 당신은뿐만 아니라하거나 메모리 사용량 CPU 사용량을 프로파일 링 할 수 있습니다. 매우 완벽한 솔루션이며 완전한 제어권을 제공하며 로그는 mongo 또는 파일 시스템 모두에서 작성할 수 있습니다.
자세한 내용 은 여기를 참조하십시오 .
Blackfire는 Symfony2 사용자 인 SensioLabs의 PHP 프로파일 러입니다. https://blackfire.io/
puphpet 을 사용 하여 가상 머신을 설정하면 지원된다는 사실에 기뻐할 것입니다 ;-)
XDEBUG2 는 PHP 용 확장입니다. Xdebug를 사용하면 매개 변수 및 반환 값을 포함한 모든 함수 호출을 다른 형식의 파일에 기록 할 수 있습니다. 세 가지 출력 형식이 있습니다. 하나는 사람이 읽을 수있는 추적을 의미하고 다른 하나는 구문 분석하기가 더 쉽기 때문에 컴퓨터 프로그램에 더 적합하며 마지막 하나는 추적 형식을 지정하기 위해 HTML을 사용합니다. 설정을 통해 두 가지 형식 사이를 전환 할 수 있습니다. 여기에 예제가 있습니다 .
forp 단순하고, 비침 입적 이며, 프로덕션 지향적 인 PHP 프로파일 러입니다. 일부 기능은 다음과 같습니다.
시간 측정 및 각 기능에 할당 된 메모리
CPU 사용량
함수 호출의 파일 및 줄 번호
Google의 추적 이벤트 형식으로 출력
기능 설명
기능 그룹화
함수 별칭 (익명 함수에 유용)
DBG 는 완전한 기능을 갖춘 PHP 디버거로, PHP 스크립트를 디버깅하는 데 도움이되는 대화 형 도구입니다. 프로덕션 및 / 또는 개발 웹 서버에서 작동하며 IDE 또는 콘솔에서 로컬 또는 원격으로 스크립트를 디버그 할 수 있으며 그 기능은 다음과 같습니다.
원격 및 로컬 디버깅
명시 적 및 암시 적 활성화
함수 호출, 동적 및 정적 메서드 호출을 포함한 호출 스택 (파라미터 포함)
해당 (중첩 된) 위치에서 변수를 평가할 수있는 기능으로 호출 스택 탐색
Step in / Step out / Step over / Run to cursor 기능
조건부 중단 점
글로벌 중단 점
오류 및 경고 로깅
병렬 디버깅을위한 다중 동시 세션
GUI 및 CLI 프런트 엔드 지원
IPv6 및 IPv4 네트워크 지원
디버거에 의해 전송 된 모든 데이터는 선택적으로 SSL로 보호 될 수 있습니다.
단일 변수의 메모리 사용량을 얻는 직접적인 방법은 없지만 Gordon이 제안했듯이 memory_get_usage
. 할당 된 총 메모리 양을 반환하므로 해결 방법을 사용하여 단일 변수의 사용량을 얻기 위해 전후 사용량을 측정 할 수 있습니다. 이것은 약간 해키하지만 작동합니다.
$start_memory = memory_get_usage();
$foo = "Some variable";
echo memory_get_usage() - $start_memory;
이것은 신뢰할 수있는 방법이 아니며 변수를 할당하는 동안 다른 어떤 것도 메모리에 영향을주지 않는다는 것을 확신 할 수 없으므로 근사값으로 만 사용해야합니다.
함수 내부에 변수의 복사본을 만들고 사용 된 메모리를 측정하여 실제로이를 함수로 바꿀 수 있습니다. 이것을 테스트하지는 않았지만 원칙적으로 나는 그것에 대해 잘못된 것을 보지 못했습니다.
function sizeofvar($var) {
$start_memory = memory_get_usage();
$tmp = unserialize(serialize($var));
return memory_get_usage() - $start_memory;
}
$tmp = $var
얕은 복사본을 만듭니다. $ tmp가 수정 될 때까지 더 많은 메모리를 할당하지 않습니다.
$tmp = unserialize(serialize($var))
? 이것은 위의 Aistina의 접근 방식을 결합합니다.
$var
이미 함수에 전달 된 내용의 얕은 복사본 또는 참조 $tmp
이므로은 필요하지 않지만에 다시 할당 할 수 있습니다 $var
. 내부 참조를에서 $tmp
로 저장합니다 $var
.
$tmp
로부터는 $var
?
아니 없어. 그러나 근사치에 대한 결과를 serialize($var)
확인할 수 있습니다 strlen
.
strlen(serialize(array(1,2,3)))
30 바이트 입니다.
Tatu Ulmanens에 대한 답변 :
그 $start_memory
자체가 메모리 ( PHP_INT_SIZE * 8
)를 차지 한다는 점에 유의해야합니다 .
따라서 전체 기능은 다음과 같아야합니다.
function sizeofvar($var) {
$start_memory = memory_get_usage();
$var = unserialize(serialize($var));
return memory_get_usage() - $start_memory - PHP_INT_SIZE * 8;
}
추가 답변으로 추가해서 죄송합니다. 아직 답변에 대해 댓글을 달 수 없습니다.
업데이트 : * 8은 명확하지 않습니다. 그것은 분명히 php 버전과 아마도 64/32 비트에 의존 할 수 있습니다.
* 8
시겠습니까? 감사!
PHP_INT_SIZE
바이트 만 차지하는 것이 아니라 PHP_INT_SIZE*8
. 이 함수를 호출하여 시도 할 수 있습니다. 0을 반환해야합니다.function sizeofvar() { $start_memory = memory_get_usage(); return memory_get_usage() - $start_memory - PHP_INT_SIZE*8; }
8
일정하지 않습니다. 내 개발 시스템 (PHP 5.6.19)의 주석 기능에 따라 -16
. 또한 흥미롭게도에서 php -a
함수의 두 줄을 호출하면 다양한 값이 제공됩니다.
보다:
memory_get_usage()
— PHP에 할당 된 메모리 양을 반환합니다.memory_get_peak_usage()
— PHP가 할당 한 최대 메모리를 반환합니다.이것은 특정 변수의 메모리 사용량을 제공하지 않습니다. 그러나 변수를 할당하기 전후에이 함수를 호출 한 다음 값을 비교할 수 있습니다. 사용 된 메모리에 대한 아이디어를 얻을 수 있습니다.
PECL 확장 Memtrack을 볼 수도 있지만 문서는 말할 필요도없이 거의 존재하지 않지만 약간 부족합니다.
콜백 반환 값에 대한 메모리 차이를 계산하도록 선택할 수 있습니다. PHP 5.3 이상에서 사용할 수있는보다 우아한 솔루션입니다.
function calculateFootprint($callback) {
$startMemory = memory_get_usage();
$result = call_user_func($callback);
return memory_get_usage() - $startMemory;
}
$memoryFootprint = calculateFootprint(
function() {
return range(1, 1000000);
}
);
echo ($memoryFootprint / (1024 * 1024)) . ' MB' . PHP_EOL;
두 변수가 메모리에서 동일한 할당 공간을 공유 할 수 있으므로 변수의 정확한 풋 프린트를 소급하여 계산할 수 없습니다.
두 배열간에 메모리를 공유해 보겠습니다. 두 번째 배열을 할당하면 첫 번째 배열의 메모리의 절반이 소모됩니다. 첫 번째 설정을 해제해도 거의 모든 메모리가 두 번째 메모리에서 사용됩니다.
echo memory_get_usage()."\n"; // <-- 433200
$c=range(1,100);
echo memory_get_usage()."\n"; // <-- 444348 (+11148)
$d=array_slice($c, 1);
echo memory_get_usage()."\n"; // <-- 451040 (+6692)
unset($c);
echo memory_get_usage()."\n"; // <-- 444232 (-6808)
unset($d);
echo memory_get_usage()."\n"; // <-- 433200 (-11032)
그래서 우리는 두 번째 배열이 메모리의 절반을 사용한다는 결론을 내릴 수 없습니다. 첫 번째 배열을 해제하면 거짓이되기 때문입니다.
PHP에서 메모리가 할당되는 방식과 용도에 대한 전체보기를 보려면 다음 기사를 읽어 보시기 바랍니다. PHP 배열 (및 값)이 실제로 얼마나 큰가? (힌트 : BIG!)
PHP 문서 의 Reference Counting Basics 에는 메모리 사용에 대한 많은 정보와 공유 데이터 세그먼트에 대한 참조 수가 있습니다.
여기에 공개 된 다른 솔루션은 근사치에는 좋지만 PHP 메모리의 미묘한 관리를 처리 할 수있는 솔루션은 없습니다.
할당 후 새로 할당 된 공간을 원하면 할당 전후에 사용해야 memory_get_usage()
합니다. 사본과 함께 사용하면 현실을 잘못 볼 수 있기 때문입니다.
// open output buffer
echo "Result: ";
// call every function once
range(1,1); memory_get_usage();
echo memory_get_usage()."\n";
$c=range(1,100);
echo memory_get_usage()."\n";
첫 번째의 결과를 저장하려면 memory_get_usage()
변수가 이전에 이미 존재해야하고 memory_get_usage()
이전에 또 다른 함수를 호출해야하며 다른 모든 함수도 호출해야합니다.
위의 예와 같이 에코하려면 출력 버퍼를 여는 데 필요한 계산 메모리를 피하기 위해 출력 버퍼가 이미 열려 있어야합니다.
함수를 사용하여 변수 사본을 저장하는 데 필요한 공간을 계산하려면 다음 코드가 다양한 최적화를 처리합니다.
<?php
function getMemorySize($value) {
// existing variable with integer value so that the next line
// does not add memory consumption when initiating $start variable
$start=1;
$start=memory_get_usage();
// json functions return less bytes consumptions than serialize
$tmp=json_decode(json_encode($value));
return memory_get_usage() - $start;
}
// open the output buffer, and calls the function one first time
echo ".\n";
getMemorySize(NULL);
// test inside a function in order to not care about memory used
// by the addition of the variable name to the $_GLOBAL array
function test() {
// call the function name once
range(1,1);
// we will compare the two values (see comment above about initialization of $start)
$start=1;
$start=memory_get_usage();
$c=range(1,100);
echo memory_get_usage()-$start."\n";
echo getMemorySize($c)."\n";
}
test();
// same result, this works fine.
// 11044
// 11044
변수 이름의 크기는 할당 된 메모리에서 중요합니다.
변수는 PHP 소스 코드에서 사용되는 내부 C 구조에 의해 정의 된 기본 크기를 갖습니다. 이 크기는 숫자의 경우 변동하지 않습니다. 문자열의 경우 문자열 길이를 추가합니다.
typedef union _zvalue_value {
long lval; /* long value */
double dval; /* double value */
struct {
char *val;
int len;
} str;
HashTable *ht; /* hash table value */
zend_object_value obj;
} zvalue_value;
변수 이름의 초기화를 고려하지 않으면 변수가 사용하는 양을 이미 알고 있습니다 (숫자와 문자열의 경우).
숫자의 경우 44 바이트
+ 문자열의 경우 24 바이트
+ 문자열의 길이 (최종 NUL 문자 포함)
(이 숫자는 PHP 버전에 따라 변경 될 수 있습니다)
메모리 정렬로 인해 4 바이트의 배수로 반올림해야합니다. 변수가 전역 공간 (함수 내부가 아님)에 있으면 64 바이트를 더 할당합니다.
따라서이 페이지에있는 코드 중 하나를 사용하려면 간단한 테스트 케이스 (문자열 또는 숫자)를 사용한 결과가이 게시물의 모든 표시 ($ _GLOBAL 배열, 첫 번째 함수 호출, 출력 버퍼, ...)
zvalue
, is_ref
그리고 copy-on-write 의 내부에 들어가기 전 입니다. 감사합니다.
비슷한 문제가 있었고 내가 사용한 해결책은 변수를 파일에 쓴 다음 파일에 파일 크기 ()를 실행하는 것이 었습니다. 대략 다음과 같습니다 (테스트되지 않은 코드).
function getVariableSize ( $foo )
{
$tmpfile = "temp-" . microtime(true) . ".txt";
file_put_contents($tmpfile, $foo);
$size = filesize($tmpfile);
unlink($tmpfile);
return $size;
}
이 솔루션은 디스크 IO를 포함하기 때문에 그렇게 빠르지는 않지만 memory_get_usage 트릭보다 훨씬 더 정확한 것을 제공해야합니다. 필요한 정밀도에 따라 다릅니다.
strlen
이 더 쉬울 것입니다.
시도한 적이 없지만 xdebug.collect_assignment를 사용하는 Xdebug 추적으로 충분할 수 있습니다.
function mesure($var){
$start = memory_get_usage();
if(is_string($var)){
$newValue = $var . '';
}elseif(is_numeric($var)){
$newValue = $var + 0;
}elseif(is_object($var)){
$newValue = clone $var;
}elseif(is_array($var)){
$newValue = array_flip($var, []);
}
return memory_get_usage() - $start;
}
다음 스크립트는 단일 변수의 총 메모리 사용량을 보여줍니다.
function getVariableUsage($var) {
$total_memory = memory_get_usage();
$tmp = unserialize(serialize($var));
return memory_get_usage() - $total_memory;
}
$var = "Hey, what's you doing?";
echo getVariableUsage($var);
이것 좀 봐