Go가 길이가 100k인 배열보다 길이가 100k인 슬라이스에 더 적은 메모리를 사용하는 이유는 무엇입니까?

王林
풀어 주다: 2024-02-09 10:12:09
앞으로
470명이 탐색했습니다.

为什么 Go 对于长度为 100k 的切片使用的内存比长度为 100k 的数组要少?

Go 언어가 슬라이스와 배열을 처리할 때 길이가 100k인 슬라이스는 길이가 100k인 배열보다 메모리를 덜 사용합니다. 이는 슬라이스가 기본 구현에서 포인터와 길이의 조합을 사용하는 반면 배열은 데이터를 저장하기 위해 연속적인 메모리 공간이 필요하기 때문입니다. 슬라이스의 길이는 가변적이므로 메모리는 동적으로 할당 및 해제될 수 있지만 배열은 선언할 때 고정된 길이를 지정해야 합니다. 따라서 대용량 데이터를 처리할 때 슬라이싱을 사용하면 메모리 공간을 보다 효율적으로 사용하고 메모리 사용량을 줄일 수 있습니다. 이는 대용량 데이터를 처리할 때 Go 언어의 장점 중 하나이기도 합니다.

질문 내용

다음 코드를 고려하면 각각 길이가 100k인 4000개의 배열을 할당했습니다.

으아악

프로그램을 로컬에서 실행하고 메모리 사용량을 분석하면 2GB 이상의 메모리를 사용하기 시작합니다.

이제 다음과 같이 배열 슬라이스(또한 길이가 100k)를 사용하도록 코드를 약간 변경하면:

으아악

내 컴퓨터에서 메모리는 약 73MB로 최고조에 달했습니다. 이게 왜요?

다음과 같은 이유로 두 프래그먼트가 거의 동일한 메모리를 사용할 것이라고 생각합니다.

  • 두 경우 모두 go 런타임은 힙에 parentmap 的值。 go 这样做是因为如果它在堆栈上分配这些值,那么一旦当前函数超出范围,parentmap를 할당하고 모든 값이 지워집니다.
  • 그래서 첫 번째 코드 조각은 4k 배열을 힙에 직접 할당합니다.
  • 또한 두 번째 조각은 힙에 4k 슬라이스 헤더를 할당합니다. 각 슬라이스 헤더에는 100k 크기의 고유한 배열(힙에도 있음)에 대한 포인터가 있습니다.
  • 두 경우 모두 100k 크기의 힙에 4k 배열이 있습니다. 따라서 두 경우 모두 거의 동일한 양의 메모리를 사용해야 합니다.

읽었습니다: https://go.dev/blog/slices-intro. 그러나 이것을 설명하는 구현 세부 정보를 찾을 수 없습니다.

해결 방법

슬라이싱이 포함된 버전은 지연 할당의 이점을 누릴 수 있습니다. 이러한 슬라이스 중 하나에 있는 데이터 버퍼에 쓰기를 시도하는 것은 없으므로 운영 체제는 쓰기가 실제로 시도될 때까지 이러한 버퍼에 대한 메모리를 실제로 할당하지 않아도 됩니다. (운영 체제는 버퍼를 느리게 초기화하여 할당이 강제되지 않도록 할 수도 있습니다.)

한편, 배열이 있는 버전에서는 실제로 배열을 맵에 복사해야 하며, 이는 실제로 쓰기를 수행한다는 의미입니다. 쓴 값이 모두 0이더라도 여전히 쓰기이기 때문에 운영체제는 실제로 쓸 데이터를 위해 메모리를 할당해야 한다.

이 슬라이스에 데이터를 써보면 슬라이스 버전도 기가바이트의 메모리를 차지해야 합니다. (메모리 페이지당 하나의 값이면 충분하다고 생각하지만 슬라이스를 1s로 채우는 것이 더 쉬울 수도 있습니다.)

위 내용은 Go가 길이가 100k인 배열보다 길이가 100k인 슬라이스에 더 적은 메모리를 사용하는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:stackoverflow.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!