PHP에서 불필요한 배열 최적화하기
어떤 프로그래머에게 1부터 100000000까지의 정수 합을 구하는
과제가 주어졌다고 가정해 봅시다.
우리 프로그래머는 이 문제에 대한 우아한 해결책을 작성했습니다. 다음과 같이 말이죠:
<?php
echo array_sum(range(1, 100000000));
?>
아름다운 해결책이죠, 그렇지 않나요? 한 줄에 모든 것이 담겨 있습니다. 하지만 이것은 작동하지 않습니다! 이 코드를 실행해 보면, 사용 가능한 메모리를 초과했다는 오류가 화면에 표시될 것입니다.
흠, 100000000은 그렇게 크지 않은 것 같은데?
아니면 큰 걸까요? 세어 봅시다. 함수 range는
100000000개의 숫자가 들어 있는 배열을 생성합니다.
PHP가 숫자 하나에 2바이트를 할당한다고 가정하면
우리 배열을 저장하는 데는 200000000바이트,
즉 약 200메가바이트의 RAM이 필요합니다.
하지만 실제로는 PHP에서 배열을 저장할 때 발생하는
많은 오버헤드 때문에 훨씬 더 많은 RAM이 필요합니다.
예를 들어, 제가 받은 오류 메시지에는
4294967304바이트를 할당하려고 시도했다고 나옵니다.
이는 약 4기가바이트에 해당하죠!
이제 왜 오류가 발생하는지 이해가 되시나요? 허용된 메모리 제한을 훨씬 초과했기 때문입니다.
우리 스크립트를 거의 RAM을 사용하지 않는 다른 방식으로 다시 작성하는 것은 그리 어렵지 않습니다:
<?php
$sum = 0;
for ($i = 1; $i <= 100000000; $i++) {
$sum += $i;
}
echo $sum;
?>
또는 수학적 해법을 사용하는 것이 더 낫습니다:
<?php
$n = 1000000;
$sum = $n * ($n + 1) / 2;
echo $sum;
?>
어떤 프로그래머에게 주어진 수의 팩토리얼을 구하는 과제가 주어졌습니다. 그는 다음과 같은 방식으로 문제를 해결했습니다:
<?php
$n = 100;
echo array_product(range(1, $n));
?>
이 코드의 문제점을 설명하세요. 코드를 더 최적화된 방식으로 수정하세요.
어떤 프로그래머에게 1부터 1000000까지의
모든 정수를 기록하는 데 사용할 수 있는 숫자의 개수를
찾는 과제가 주어졌습니다.
그는 다음과 같은 방식으로 문제를 해결했습니다:
<?php
echo strlen(implode('', range(1, 1000000)));
?>
이 코드의 문제점을 설명하세요. 코드를 더 최적화된 방식으로 수정하세요.
어떤 프로그래머에게 주어진 구간에서 나머지 없이
7으로 나누어지는 숫자의 개수를
찾는 과제가 주어졌습니다. 그는 다음과 같은
방식으로 문제를 해결했습니다:
<?php
$arr = [];
for ($i = 0; $i <= 1000; $i++) {
if ($i % 7 == 0) {
$arr[] = $i;
}
}
echo count($arr);
?>
이 코드의 문제점을 설명하세요. 코드를 더 최적화된 방식으로 수정하세요.
어떤 프로그래머에게 숫자의 약수의 합을 구하는 과제가 주어졌습니다. 그는 다음과 같은 방식으로 문제를 해결했습니다:
<?php
$num = 320;
$divs = [];
for ($i = 0; $i <= $num; $i++) {
if ($num % $i == 0) {
$divs[] = $i;
}
}
echo array_sum($divs);
?>
이 코드의 문제점을 설명하세요. 코드를 더 최적화된 방식으로 수정하세요.