메모리의 Python 목록 크기
저는 방금 메모리에 있는 파이썬 데이터 구조의 크기를 실험했습니다.저는 다음과 같은 스니펫을 작성했습니다.
import sys
lst1=[]
lst1.append(1)
lst2=[1]
print(sys.getsizeof(lst1), sys.getsizeof(lst2))
다음 구성에서 다음과 같은 출력을 받았습니다.
- Windows 764(윈도우 764), Python 3. 1:
52 40
(그래서)lst1
및 52µ트및 이lst2
), 40바이트 있음) - Ubuntu 11.4 32bit with Python3.은 2: 출은입니다.
48 32
- 11 파이썬 2 우분투 11.4 32비트 파이썬 2.7:
48 36
둘 다 1을 포함하는 목록인데 왜 두 사이즈가 다른지 누가 설명해줄 수 있나요?
파이썬에 대한 getsizeof
함수 다음을 찾았습니다.
...개체가 가비지 수집기에 의해 관리되는 경우 가비지 수집기 오버헤드가 추가됩니다.
이것이 제 작은 예에 해당될 수 있을까요?
다음은 진행 상황을 설명하는 데 도움이 되는 전체 대화형 세션입니다(Windows XP 32비트의 경우 Python 2.6이지만 실제로는 중요하지 않습니다).
>>> import sys
>>> sys.getsizeof([])
36
>>> sys.getsizeof([1])
40
>>> lst = []
>>> lst.append(1)
>>> sys.getsizeof(lst)
52
>>>
빈 목록이 있는 목록보다 조금 작음을 참조하십시오.[1]
그 안에. 하지만 요소가 추가되면, 그것은 훨씬 더 커집니다.
는 그이는의 정때다문니입에 있는 사항 입니다.Objects/listobject.c
사이톤 소스서에.
빈 목록
목록이 있을 때[]
생성되고, . - 는 생됨성, 요위공할지않당음되 - 에확수있다습니인할서에서 할 수 .PyList_New
36바이트는 32비트 시스템의 목록 데이터 구조 자체에 필요한 공간입니다.
요소가 하나인 목록
요소를 가 있을 때[1]
하나의 요소에 대한 공간이 생성되고, 목록 데이터 구조 자체에 필요한 메모리 외에 추가로 할당됩니다.다시 말하지만, 이것은 다음에서 찾을 수 있습니다.PyList_New
.정해진size
인수로서, 그것은 다음을 계산합니다:
nbytes = size * sizeof(PyObject *);
그리고 다음이 있습니다.
if (size <= 0)
op->ob_item = NULL;
else {
op->ob_item = (PyObject **) PyMem_MALLOC(nbytes);
if (op->ob_item == NULL) {
Py_DECREF(op);
return PyErr_NoMemory();
}
memset(op->ob_item, 0, nbytes);
}
Py_SIZE(op) = size;
op->allocated = size;
그래서 우리는 그것을 볼 수 있습니다.size = 1
포인터 하나에 대한 공간이 할당됩니다.4바이트(32비트 상자).
빈 목록에 추가
를 부를 때append
과 같은이 발생합니다.
PyList_Append
출들app1
app1
목록의 크기를 묻습니다(응답으로 0을 받음).app1
그 다음에 전화가 옵니다.list_resize
와 함께size+1
1우리경우의 1)list_resize
에는 소스의 이 주석에 요약된 흥미로운 할당 전략이 있습니다.
여기 있습니다.
/* This over-allocates proportional to the list size, making room
* for additional growth. The over-allocation is mild, but is
* enough to give linear-time amortized behavior over a long
* sequence of appends() in the presence of a poorly-performing
* system realloc().
* The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
*/
new_allocated = (newsize >> 3) + (newsize < 9 ? 3 : 6);
/* check for integer overflow */
if (new_allocated > PY_SIZE_MAX - newsize) {
PyErr_NoMemory();
return -1;
} else {
new_allocated += newsize;
}
수학을 좀 해요.
제가 기사의 첫머리에 있는 세션에서 인용한 숫자가 어떻게 되는지 알아보겠습니다.
따라서 36바이트는 32비트의 목록 데이터 구조 자체에 필요한 크기입니다.단일 요소를 사용하면 포인터 하나에 공간이 할당되므로 4바이트가 추가됩니다. 즉, 총 40바이트입니다.지금까지는 알겠습니다.
때app1
빈 목록에 호출되면 호출됩니다.list_resize
와 함께size=1
할 ▁of의 list_resize
으로 큰 의 포인터를 됩니다. 1 다 이 로 큰 4 개 4 의= 바이트, + = 52 + = 52.4 * 4 = 16 트 36 + 16 ▁52 52
사실, 모든 것이 이치에 맞습니다 :-)
죄송합니다, 이전 댓글은 조금 퉁명스러웠습니다.
일이 는 여러분이 목록이 할당되는지를 입니다. ( 알고 거라고 합니다.) 무슨일일있당그목신록것보있입니다는다고이어이떻그경사얼것일큰세하요우용싶다보마나니입이지을었고리고단당아지신도마)sys.getsizeof()
)
목록에 무언가가 추가되면 두 가지 중 하나가 발생할 수 있습니다.
여분의 물건이 여유 공간에 들어맞습니다.
여분의 공간이 필요하기 때문에 새로운 목록이 만들어지고, 내용이 복사되고, 여분의 것이 추가됩니다.
(2)는 비용이 많이 들기 때문에(포인터도 포함하고, 복사할 항목의 수에 비례하는 시간이 소요되므로 목록이 커질수록 시간이 많이 소요됨) 우리는 이 작업을 자주 수행하지 않기를 원합니다. 따라서 공간을 조금 더 추가하는 대신 전체 청크를 추가합니다.일반적으로 추가된 양의 크기는 이미 사용 중인 것과 유사합니다. 즉, 여러 용도에 걸쳐 분산된 메모리 할당의 평균 비용이 목록 크기에 비례한다는 것이 계산 방식으로 밝혀집니다.
그래서 당신이 보고 있는 것은 이 행동과 관련이 있습니다.나는 정확한 세부 사항을 모르지만, 만약에.[]
또는[1]
(또는 둘 다)는 특수한 경우로, 메모리가 충분히 할당된 경우(이러한 일반적인 경우에는 메모리를 절약하기 위해), 추가하면 위에서 설명한 "새 청크 추가"가 수행됩니다.
하지만 저는 정확한 세부 사항은 모릅니다. 이것이 일반적으로 동적 어레이가 작동하는 방식입니다.python에서 목록의 정확한 구현은 일반적인 python 프로그램에 최적화되도록 미세 조정될 것입니다.그래서 제가 정말로 말하고 싶은 것은 목록의 크기를 신뢰할 수 없다는 것입니다. 목록에 정확히 얼마나 많은 양이 포함되어 있는지는 추가 공간이 포함되어 있을 수 있고 추가 여유 공간의 양을 판단하거나 예측하기가 어렵습니다.
을 ps 이에대깔대목만것록입다니드는을은으로 입니다.(value, pointer)
각포가다튜가쌍입다니는리키플을음. 하면 된 총 가 더 으로 늘릴 수 . (더 .)이러한 방식으로 사용되는 총 메모리가 더 높지만 점진적으로 목록을 증가시킬 수 있습니다. 이것은 링크된 목록입니다(python이 사용하는 것은 벡터 또는 동적 배열에 더 가깝습니다).
[update] Eli의 훌륭한 답변을 보십시오.그들은 둘 다 설명합니다.[]
그리고.[1]
정확히 할당되었지만, 그것은 추가됩니다.[]
. 위에서 는 " 할당이라고 하며미정합니다).코드 내의 코멘트는 위에서 제가 말하고 있는 것입니다(이것을 "과잉 할당"이라고 하며 금액은 우리가 가진 것에 비례하므로 평균적인 ("미정화"된) 비용은 크기에 비례합니다)
여기 목록의 성장 패턴에 대한 간단한 설명이 있습니다.range()에서 세 번째 인수를 변경하면 listobject.c의 주석처럼 보이지 않도록 출력이 변경되지만, 한 요소를 단순히 추가했을 때의 결과는 완벽하게 정확한 것 같습니다.
allocated = 0
for newsize in range(0,100,1):
if (allocated < newsize):
new_allocated = (newsize >> 3) + (3 if newsize < 9 else 6)
allocated = newsize + new_allocated;
print newsize, allocated
32비트 시스템의 경우 시스템 아키텍처(size-36)/4, 64비트 시스템의 경우 (size-64)/8을 기반으로 공식 변경
36,64 - 기계 기준 빈 목록 크기 4.8 - 기계 기준 목록의 단일 요소 크기
언급URL : https://stackoverflow.com/questions/7247298/size-of-a-python-list-in-memory
'programing' 카테고리의 다른 글
VB.NET 'If' 문에 'Or' 조건부가 모두 평가되었습니까? (0) | 2023.05.21 |
---|---|
HttpClient 요청에 대한 사용자 정의 헤더 (0) | 2023.05.21 |
파이썬에서 집합을 목록으로 변환하는 방법은 무엇입니까? (0) | 2023.05.21 |
git log'로 첫 번째 커밋을 표시하는 방법은 무엇입니까? (0) | 2023.05.21 |
MS SQL Server 2008용 포트를 찾는 방법은 무엇입니까? (0) | 2023.05.21 |