It looks making a slice with size 32768+1 will allocate with one memory page as needed

245 views
Skip to first unread message

tapi...@gmail.com

unread,
Jun 11, 2021, 12:38:35 PM6/11/21
to golang-nuts
package allocate

import "testing"
import "os"
import "fmt"

func init() {
    fmt.Println("OS page size:", os.Getpagesize())
}

var r1 []byte

func BenchmarkCount1(b *testing.B) {
    for i := 0; i < b.N; i++ {
        r1 = make([]byte, 32768+1)
    }
}

var r2 []byte

func BenchmarkCount2(b *testing.B) {
    for i := 0; i < b.N; i++ {
        r2 = make([]byte, 40)
    }
}

The output:

OS page size: 32768
BenchmarkCount1-4         166443          7312 ns/op       40960 B/op           1 allocs/op
BenchmarkCount2-4       31465389            36.88 ns/op          48 B/op           1 allocs/op

In fact, a memory block with size 36864 is enough to carry the elements of a byte slice with size 32768+1. Why to allocate one more page for them?

Ian Lance Taylor

unread,
Jun 11, 2021, 2:00:03 PM6/11/21
to tapi...@gmail.com, golang-nuts
Memory blocks larger than 32768 bytes flip over to the "large
allocation" model. See _MaxSmallSize in runtime/sizeclasses.go (a
generated file). This requires an extra span. I haven't tried to
work it out in detail, but it probably has something to do with that.

Ian

tapi...@gmail.com

unread,
Jun 11, 2021, 7:59:27 PM6/11/21
to golang-nuts
Yes, that is why I chose a size 32768+1.
I understand that the large memory block will be a multiple of page size.
What I haven't get is why one more page is allocated.

I will try to read the source to get the answer.

BTW, sorry, I missed a "more" in the thread title.

tapi...@gmail.com

unread,
Jun 12, 2021, 2:20:43 AM6/12/21
to golang-nuts
It looks the _PageSize constant used in allocating large memory block is declared as 8192 in code, but os.Getpagesize() returns 4096.

const (
    ...
    _PageShift      = 13
    _PageSize = 1 << _PageShift
    ...
)

Is this intended?

Ian Lance Taylor

unread,
Jun 12, 2021, 12:04:21 PM6/12/21
to tapi...@gmail.com, golang-nuts
On Fri, Jun 11, 2021 at 11:21 PM tapi...@gmail.com <tapi...@gmail.com> wrote:
>
> It looks the _PageSize constant used in allocating large memory block is declared as 8192 in code, but os.Getpagesize() returns 4096.
>
> const (
> ...
> _PageShift = 13
> _PageSize = 1 << _PageShift
> ...
> )
>
> Is this intended?

Yes. _PageSize is the page size that the memory allocator uses.
os.Getpagesize returns the page size that the system uses to map
pages. In the runtime that is known as physPageSize. There is no
necessary relationship between the two, although heapArenaBytes should
be a multiple of both.

Ian
> --
> You received this message because you are subscribed to the Google Groups "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/76e112a7-9e1a-46ed-bcb3-03c0ff33beacn%40googlegroups.com.

tapi...@gmail.com

unread,
Jun 12, 2021, 8:56:02 PM6/12/21
to golang-nuts
On Saturday, June 12, 2021 at 12:04:21 PM UTC-4 Ian Lance Taylor wrote:
On Fri, Jun 11, 2021 at 11:21 PM tapi...@gmail.com <tapi...@gmail.com> wrote:
>
> It looks the _PageSize constant used in allocating large memory block is declared as 8192 in code, but os.Getpagesize() returns 4096.
>
> const (
> ...
> _PageShift = 13
> _PageSize = 1 << _PageShift
> ...
> )
>
> Is this intended?

Yes. _PageSize is the page size that the memory allocator uses.
os.Getpagesize returns the page size that the system uses to map
pages. In the runtime that is known as physPageSize. There is no
necessary relationship between the two, although heapArenaBytes should
be a multiple of both.

Ian

Thanks for the clarification.
Reply all
Reply to author
Forward
0 new messages