github.com/moontrade/nogc@v0.1.7/alloc/tlsf/heap_test.go (about)

     1  package tlsf
     2  
     3  import (
     4  	"fmt"
     5  	"math/rand"
     6  	"runtime"
     7  	"sync"
     8  	"testing"
     9  	"time"
    10  )
    11  
    12  func Test_AllocatorCounts(t *testing.T) {
    13  	p := NewHeapWithConfig(1, NewSysArena(), GrowMin)
    14  	p1 := p.Alloc(38)
    15  	println("alloc size", p.AllocSize)
    16  	p2 := p.Alloc(81)
    17  	println("alloc size", p.AllocSize)
    18  	p.Free(p1)
    19  	println("alloc size", p.AllocSize)
    20  	p.Free(p2)
    21  	println("alloc size", p.AllocSize)
    22  }
    23  
    24  //func Benchmark_Ctz32(b *testing.B) {
    25  //	b.Run("bits.TrailingZeroes32", func(b *testing.B) {
    26  //		for i := 0; i < b.N; i++ {
    27  //			bits.TrailingZeros32(100)
    28  //			bits.TrailingZeros32(101)
    29  //			bits.TrailingZeros32(102)
    30  //		}
    31  //	})
    32  //
    33  //	b.Run("Ctz32", func(b *testing.B) {
    34  //		for i := 0; i < b.N; i++ {
    35  //			Ctz32(100)
    36  //			Ctz32(101)
    37  //			Ctz32(102)
    38  //		}
    39  //	})
    40  //}
    41  
    42  func Test_AllocatorThrash(t *testing.T) {
    43  	a := NewSysArena()
    44  	statsBefore := runtime.MemStats{}
    45  	runtime.ReadMemStats(&statsBefore)
    46  	thrashAllocator(NewHeapWithConfig(1, a, GrowMin), false,
    47  		1000000, 100, 15000, 21000,
    48  		randomSize(0.95, 16, 48),
    49  		randomSize(0.95, 48, 192),
    50  		randomSize(0.55, 64, 512),
    51  		//randomSize(0.70, 128, 512),
    52  		//randomSize(0.15, 128, 512),
    53  		//randomSize(0.30, 128, 1024),
    54  	)
    55  
    56  	var statsAfter runtime.MemStats
    57  	runtime.ReadMemStats(&statsAfter)
    58  	fmt.Println("SysAllocator Size", a.Size())
    59  	fmt.Println("GCStats Before", statsBefore)
    60  	fmt.Println("GCStats After", statsAfter)
    61  
    62  	//thrashAllocator(newAllocator(2), 100000, 100, 12000, 17000,
    63  	//	randomSize(0.80, 24, 96),
    64  	//	//randomSize(0.70, 128, 512),
    65  	//	//randomSize(0.15, 128, 512),
    66  	//	//randomSize(0.30, 128, 1024),
    67  	//)
    68  }
    69  
    70  type sizeClass struct {
    71  	pct      float64
    72  	min, max int
    73  	next     func() int
    74  }
    75  
    76  func randomSize(pct float64, min, max int) *sizeClass {
    77  	sz := &sizeClass{pct, min, max, nil}
    78  	sz.next = sz.nextRandom
    79  	return sz
    80  }
    81  
    82  func (s *sizeClass) nextRandom() int {
    83  	if s.max == s.min {
    84  		return s.max
    85  	}
    86  	return rand.Intn(s.max-s.min) + s.min
    87  }
    88  
    89  func thrashAllocator(
    90  	allocator *Heap, shuffle bool,
    91  	iterations, allocsPerIteration, minAllocs, maxAllocs int,
    92  	sizeClasses ...*sizeClass,
    93  ) {
    94  	type allocation struct {
    95  		ptr  uintptr
    96  		size int
    97  	}
    98  
    99  	sz := make([]int, 0, allocsPerIteration)
   100  	for _, sc := range sizeClasses {
   101  		for i := 0; i < int(float64(allocsPerIteration)*sc.pct); i++ {
   102  			sz = append(sz, sc.next())
   103  		}
   104  	}
   105  
   106  	allocs := make([]allocation, 0, maxAllocs)
   107  	allocSize := 0
   108  	totalAllocs := 0
   109  	totalFrees := 0
   110  	maxAllocCount := 0
   111  	maxAllocSize := 0
   112  
   113  	if shuffle {
   114  		rand.Seed(time.Now().UnixNano())
   115  	}
   116  
   117  	start := time.Now()
   118  	for i := 0; i < iterations; i++ {
   119  		if shuffle {
   120  			rand.Shuffle(len(sz), func(i, j int) { sz[i], sz[j] = sz[j], sz[i] })
   121  		}
   122  
   123  		for _, size := range sz {
   124  			allocs = append(allocs, allocation{
   125  				ptr:  allocator.Alloc(uintptr(size)), //tlsfalloc(uintptr(size)),
   126  				size: size,
   127  			})
   128  			allocSize += size
   129  		}
   130  		totalAllocs += len(sz)
   131  
   132  		if maxAllocCount < len(allocs) {
   133  			maxAllocCount = len(allocs)
   134  		}
   135  		if allocSize > maxAllocSize {
   136  			maxAllocSize = allocSize
   137  		}
   138  
   139  		if len(allocs) < minAllocs || len(allocs) < maxAllocs {
   140  			continue
   141  		}
   142  
   143  		//rand.Shuffle(len(allocs), func(i, j int) { allocs[i], allocs[j] = allocs[j], allocs[i] })
   144  		max := randomRange(minAllocs, maxAllocs)
   145  		//max := maxAllocs
   146  		totalFrees += len(allocs) - max
   147  		for x := max; x < len(allocs); x++ {
   148  			alloc := allocs[x]
   149  			allocator.Free(alloc.ptr)
   150  			allocSize -= alloc.size
   151  		}
   152  		allocs = allocs[:max]
   153  	}
   154  
   155  	elapsed := time.Now().Sub(start)
   156  	seconds := float64(elapsed) / float64(time.Second)
   157  	println("total time			", elapsed.String())
   158  	fmt.Printf("allocs per sec		 %.1f million / sec\n", float64(float64(totalAllocs)/seconds/1000000))
   159  	//println("allocs per sec		", float64(totalAllocs) / seconds)
   160  	println("alloc bytes			", allocSize)
   161  	println("alloc count			", len(allocs))
   162  	println("total allocs		", totalAllocs)
   163  	println("total frees			", totalFrees)
   164  	println("total frees			", totalFrees)
   165  	println("memory pages		", allocator.Pages)
   166  	println("heap size			", allocator.HeapSize)
   167  	println("free size			", allocator.FreeSize)
   168  	println("alloc size			", allocator.AllocSize)
   169  	//println("alloc size			", AllocSize)
   170  	println("max allocs			", maxAllocCount)
   171  	println("max alloc size		", allocator.PeakAllocSize)
   172  	println("fragmentation		", fmt.Sprintf("%.2f", allocator.Stats.Fragmentation()))
   173  }
   174  
   175  //func TestAllocatorKind(t *testing.T) {
   176  //	a := NewHeapWithConfig(1, NewSysArena(), GrowMin)
   177  //	s := a.ToSync()
   178  //
   179  //	p1 := toTLSFAllocator(a)
   180  //	p2 := toTLSFSyncAllocator(s)
   181  //
   182  //	p1.Free(p1.Alloc(64))
   183  //	p2.Free(p2.Alloc(128))
   184  //
   185  //	println(p1, p1|_TLSFNoSync)
   186  //	println(p2, p2|_TLSFSync, (p2|_TLSFSync) & ^_AllocatorMask)
   187  //	println((p2 | _TLSFSync) & ^_AllocatorMask)
   188  //	println((p1 | _TLSFNoSync) & _AllocatorMask)
   189  //	println((p2 | _TLSFSync) & _AllocatorMask)
   190  //}
   191  
   192  func Test_Allocator(t *testing.T) {
   193  	a := NewHeapWithConfig(1, NewSysArena(), GrowMin)
   194  	PrintDebugInfo()
   195  	ptr := a.Alloc(16)
   196  	ptr2 := a.Alloc(49)
   197  	ptr4 := a.Alloc(8224)
   198  	println("ptr", uint(ptr))
   199  	println("ptr2", uint(ptr2))
   200  	ptr3 := a.Alloc(517)
   201  	a.Free(ptr)
   202  	a.Free(ptr4)
   203  	a.Free(ptr2)
   204  	a.Free(ptr3)
   205  }
   206  
   207  func BenchmarkAllocator_Alloc(b *testing.B) {
   208  	var (
   209  		min, max    = 24, 2048
   210  		showGCStats = true
   211  	)
   212  	doAfter := func(before, after runtime.MemStats) {
   213  		if showGCStats {
   214  			fmt.Println("Before", "GC CPU", before.GCCPUFraction, "TotalAllocs", before.TotalAlloc, "Frees", before.Frees, "PauseNs Total", before.PauseTotalNs)
   215  			fmt.Println("After ", "GC CPU", after.GCCPUFraction, "TotalAllocs", after.TotalAlloc, "Frees", after.Frees, "PauseNs Total", after.PauseTotalNs)
   216  			println()
   217  		}
   218  	}
   219  	//b.Run("Random Range time", func(b *testing.B) {
   220  	//	b.ReportAllocs()
   221  	//	b.ResetTimer()
   222  	//	for i := 0; i < b.N; i++ {
   223  	//		randomRange(min, max)
   224  	//	}
   225  	//	after()
   226  	//})
   227  
   228  	randomRangeSizes := make([]uintptr, 0, 256)
   229  	for i := 0; i < 1000; i++ {
   230  		randomRangeSizes = append(randomRangeSizes, uintptr(randomRange(min, max)))
   231  	}
   232  
   233  	//b.Run("Heap alloc", func(b *testing.B) {
   234  	//	a := NewHeapWithConfig(1, NewSysArena(), GrowMin)
   235  	//	var before runtime.MemStats
   236  	//	runtime.ReadMemStats(&before)
   237  	//	b.ReportAllocs()
   238  	//	b.ResetTimer()
   239  	//	for i := 0; i < b.N; i++ {
   240  	//		size := randomRangeSizes[i%len(randomRangeSizes)]
   241  	//		b.SetBytes(int64(size))
   242  	//		a.Free(a.Alloc(uintptr(size)))
   243  	//	}
   244  	//	after(before)
   245  	//})
   246  	//b.Run("Heap allocZeroed", func(b *testing.B) {
   247  	//	a := NewHeapWithConfig(1, NewSysArena(), GrowMin)
   248  	//	var before runtime.MemStats
   249  	//	runtime.ReadMemStats(&before)
   250  	//	b.ReportAllocs()
   251  	//	b.ResetTimer()
   252  	//	for i := 0; i < b.N; i++ {
   253  	//		size := randomRangeSizes[i%len(randomRangeSizes)]
   254  	//		b.SetBytes(int64(size))
   255  	//		a.Free(a.AllocZeroed(uintptr(size)))
   256  	//	}
   257  	//	after(before)
   258  	//})
   259  	//b.Run("Allocator alloc", func(b *testing.B) {
   260  	//	al := NewHeapWithConfig(1, NewSysArena(), GrowMin)
   261  	//	a := toTLSFAllocator(al)
   262  	//	b.ReportAllocs()
   263  	//	b.ResetTimer()
   264  	//	for i := 0; i < b.N; i++ {
   265  	//		size := randomRangeSizes[i%len(randomRangeSizes)]
   266  	//		b.SetBytes(int64(size))
   267  	//		a.Free(a.Alloc(uintptr(size)))
   268  	//	}
   269  	//	after()
   270  	//})
   271  	//b.Run("Allocator allocZeroed", func(b *testing.B) {
   272  	//	al := NewHeapWithConfig(1, NewSysArena(), GrowMin)
   273  	//	a := toTLSFAllocator(al)
   274  	//	b.ReportAllocs()
   275  	//	b.ResetTimer()
   276  	//	for i := 0; i < b.N; i++ {
   277  	//		size := randomRangeSizes[i%len(randomRangeSizes)]
   278  	//		b.SetBytes(int64(size))
   279  	//		a.Free(a.AllocZeroed(uintptr(size)))
   280  	//	}
   281  	//	after()
   282  	//})
   283  	b.Run("tlsf Heap alloc", func(b *testing.B) {
   284  		a := NewHeapWithConfig(1, NewSysArena(), GrowMin) //.ToSync()
   285  		runtime.GC()
   286  		runtime.GC()
   287  		b.ReportAllocs()
   288  		b.ResetTimer()
   289  		var before runtime.MemStats
   290  		runtime.ReadMemStats(&before)
   291  		for i := 0; i < b.N; i++ {
   292  			size := randomRangeSizes[i%len(randomRangeSizes)]
   293  			b.SetBytes(int64(size))
   294  			a.Free(a.Alloc(uintptr(size)))
   295  		}
   296  		b.StopTimer()
   297  		var after runtime.MemStats
   298  		runtime.ReadMemStats(&after)
   299  		doAfter(before, after)
   300  	})
   301  	//b.Run("Sync Heap allocZeroed", func(b *testing.B) {
   302  	//	a := NewHeapWithConfig(1, NewSysArena(), GrowMin).ToSync()
   303  	//	var before runtime.MemStats
   304  	//	runtime.ReadMemStats(&before)
   305  	//	b.ReportAllocs()
   306  	//	b.ResetTimer()
   307  	//	for i := 0; i < b.N; i++ {
   308  	//		size := randomRangeSizes[i%len(randomRangeSizes)]
   309  	//		b.SetBytes(int64(size))
   310  	//		a.Free(a.AllocZeroed(uintptr(size)))
   311  	//	}
   312  	//	b.StopTimer()
   313  	//	var after runtime.MemStats
   314  	//	runtime.ReadMemStats(&after)
   315  	//	doAfter(before, after)
   316  	//})
   317  	//b.Run("Sync Allocator alloc", func(b *testing.B) {
   318  	//	al := NewHeapWithConfig(1, NewSysArena(), GrowMin).ToSync()
   319  	//	a := toTLSFSyncAllocator(al)
   320  	//	b.ReportAllocs()
   321  	//	b.ResetTimer()
   322  	//	for i := 0; i < b.N; i++ {
   323  	//		size := randomRangeSizes[i%len(randomRangeSizes)]
   324  	//		b.SetBytes(int64(size))
   325  	//		a.Free(a.Alloc(uintptr(size)))
   326  	//	}
   327  	//	after()
   328  	//})
   329  	//b.Run("Sync Allocator allocZeroed", func(b *testing.B) {
   330  	//	a := NewHeapWithConfig(1, NewSysArena(), GrowMin).ToSync()
   331  	//	b.ReportAllocs()
   332  	//	b.ResetTimer()
   333  	//	for i := 0; i < b.N; i++ {
   334  	//		size := randomRangeSizes[i%len(randomRangeSizes)]
   335  	//		b.SetBytes(int64(size))
   336  	//		a.Free(a.AllocZeroed(uintptr(size)))
   337  	//	}
   338  	//	after()
   339  	//})
   340  
   341  	b.Run("Go GC pool", func(b *testing.B) {
   342  		runtime.GC()
   343  		runtime.GC()
   344  		b.ReportAllocs()
   345  		b.ResetTimer()
   346  		var before runtime.MemStats
   347  		runtime.ReadMemStats(&before)
   348  		for i := 0; i < b.N; i++ {
   349  			size := randomRangeSizes[i%len(randomRangeSizes)]
   350  			b.SetBytes(int64(size))
   351  			PutBytes(GetBytes(int(size)))
   352  		}
   353  		b.StopTimer()
   354  		var after runtime.MemStats
   355  		runtime.ReadMemStats(&after)
   356  		doAfter(before, after)
   357  	})
   358  
   359  	b.Run("Go GC alloc", func(b *testing.B) {
   360  		runtime.GC()
   361  		runtime.GC()
   362  		b.ReportAllocs()
   363  		b.ResetTimer()
   364  		var before runtime.MemStats
   365  		runtime.ReadMemStats(&before)
   366  		for i := 0; i < b.N; i++ {
   367  			size := randomRangeSizes[i%len(randomRangeSizes)]
   368  			b.SetBytes(int64(size))
   369  			_ = make([]byte, 0, size)
   370  		}
   371  		b.StopTimer()
   372  		var after runtime.MemStats
   373  		runtime.ReadMemStats(&after)
   374  		doAfter(before, after)
   375  	})
   376  }
   377  
   378  func randomRange(min, max int) int {
   379  	return rand.Intn(max-min) + min
   380  }
   381  
   382  var (
   383  	pool1 = &sync.Pool{New: func() interface{} {
   384  		return make([]byte, 1)
   385  	}}
   386  	pool2 = &sync.Pool{New: func() interface{} {
   387  		return make([]byte, 2)
   388  	}}
   389  	pool4 = &sync.Pool{New: func() interface{} {
   390  		return make([]byte, 4)
   391  	}}
   392  	pool8 = &sync.Pool{New: func() interface{} {
   393  		return make([]byte, 8)
   394  	}}
   395  	pool12 = &sync.Pool{New: func() interface{} {
   396  		return make([]byte, 12)
   397  	}}
   398  	pool16 = &sync.Pool{New: func() interface{} {
   399  		return make([]byte, 16)
   400  	}}
   401  	pool24 = &sync.Pool{New: func() interface{} {
   402  		return make([]byte, 24)
   403  	}}
   404  	pool32 = &sync.Pool{New: func() interface{} {
   405  		return make([]byte, 32)
   406  	}}
   407  	pool40 = &sync.Pool{New: func() interface{} {
   408  		return make([]byte, 40)
   409  	}}
   410  	pool48 = &sync.Pool{New: func() interface{} {
   411  		return make([]byte, 48)
   412  	}}
   413  	pool56 = &sync.Pool{New: func() interface{} {
   414  		return make([]byte, 56)
   415  	}}
   416  	pool64 = &sync.Pool{New: func() interface{} {
   417  		return make([]byte, 64)
   418  	}}
   419  	pool72 = &sync.Pool{New: func() interface{} {
   420  		return make([]byte, 72)
   421  	}}
   422  	pool96 = &sync.Pool{New: func() interface{} {
   423  		return make([]byte, 96)
   424  	}}
   425  	pool128 = &sync.Pool{New: func() interface{} {
   426  		return make([]byte, 128)
   427  	}}
   428  	pool192 = &sync.Pool{New: func() interface{} {
   429  		return make([]byte, 192)
   430  	}}
   431  	pool256 = &sync.Pool{New: func() interface{} {
   432  		return make([]byte, 256)
   433  	}}
   434  	pool384 = &sync.Pool{New: func() interface{} {
   435  		return make([]byte, 384)
   436  	}}
   437  	pool512 = &sync.Pool{New: func() interface{} {
   438  		return make([]byte, 512)
   439  	}}
   440  	pool768 = &sync.Pool{New: func() interface{} {
   441  		return make([]byte, 768)
   442  	}}
   443  	pool1024 = &sync.Pool{New: func() interface{} {
   444  		return make([]byte, 1024)
   445  	}}
   446  	pool2048 = &sync.Pool{New: func() interface{} {
   447  		return make([]byte, 2048)
   448  	}}
   449  	pool4096 = &sync.Pool{New: func() interface{} {
   450  		return make([]byte, 4096)
   451  	}}
   452  	pool8192 = &sync.Pool{New: func() interface{} {
   453  		return make([]byte, 8192)
   454  	}}
   455  	pool16384 = &sync.Pool{New: func() interface{} {
   456  		return make([]byte, 16384)
   457  	}}
   458  	pool32768 = &sync.Pool{New: func() interface{} {
   459  		return make([]byte, 32768)
   460  	}}
   461  	pool65536 = &sync.Pool{New: func() interface{} {
   462  		return make([]byte, 65536)
   463  	}}
   464  )
   465  
   466  func GetBytes(n int) []byte {
   467  	v := ceilToPowerOfTwo(n)
   468  	switch v {
   469  	case 0, 1:
   470  		return pool1.Get().([]byte)[:n]
   471  	case 2:
   472  		return pool2.Get().([]byte)[:n]
   473  	case 4:
   474  		return pool4.Get().([]byte)[:n]
   475  	case 8:
   476  		return pool8.Get().([]byte)[:n]
   477  	case 16:
   478  		return pool16.Get().([]byte)[:n]
   479  	case 24:
   480  		return pool24.Get().([]byte)[:n]
   481  	case 32:
   482  		return pool32.Get().([]byte)[:n]
   483  	case 64:
   484  		switch {
   485  		case n < 41:
   486  			return pool40.Get().([]byte)[:n]
   487  		case n < 49:
   488  			return pool48.Get().([]byte)[:n]
   489  		case n < 57:
   490  			return pool56.Get().([]byte)[:n]
   491  		}
   492  		return pool64.Get().([]byte)[:n]
   493  	case 128:
   494  		switch {
   495  		case n < 73:
   496  			return pool72.Get().([]byte)[:n]
   497  		case n < 97:
   498  			return pool96.Get().([]byte)[:n]
   499  		}
   500  		return pool128.Get().([]byte)[:n]
   501  	case 256:
   502  		switch {
   503  		case n < 193:
   504  			return pool192.Get().([]byte)[:n]
   505  		}
   506  		return pool256.Get().([]byte)[:n]
   507  	case 512:
   508  		if n <= 384 {
   509  			return pool384.Get().([]byte)
   510  		}
   511  		return pool512.Get().([]byte)[:n]
   512  	case 1024:
   513  		if n <= 768 {
   514  			return pool768.Get().([]byte)[:n]
   515  		}
   516  		return pool1024.Get().([]byte)[:n]
   517  	case 2048:
   518  		return pool2048.Get().([]byte)[:n]
   519  	case 4096:
   520  		return pool4096.Get().([]byte)[:n]
   521  	case 8192:
   522  		return pool8192.Get().([]byte)[:n]
   523  	case 16384:
   524  		return pool16384.Get().([]byte)[:n]
   525  	case 32768:
   526  		return pool32768.Get().([]byte)[:n]
   527  	case 65536:
   528  		return pool65536.Get().([]byte)[:n]
   529  	}
   530  
   531  	return make([]byte, n)
   532  }
   533  
   534  func PutBytes(b []byte) {
   535  	switch cap(b) {
   536  	case 1:
   537  		pool1.Put(b)
   538  	case 2:
   539  		pool2.Put(b)
   540  	case 4:
   541  		pool4.Put(b)
   542  	case 8:
   543  		pool8.Put(b)
   544  	case 12:
   545  		pool12.Put(b)
   546  	case 16:
   547  		pool16.Put(b)
   548  	case 24:
   549  		pool24.Put(b)
   550  	case 32:
   551  		pool32.Put(b)
   552  	case 40:
   553  		pool40.Put(b)
   554  	case 48:
   555  		pool48.Put(b)
   556  	case 56:
   557  		pool56.Put(b)
   558  	case 64:
   559  		pool64.Put(b)
   560  	case 72:
   561  		pool72.Put(b)
   562  	case 96:
   563  		pool96.Put(b)
   564  	case 128:
   565  		pool128.Put(b)
   566  	case 192:
   567  		pool192.Put(b)
   568  	case 256:
   569  		pool256.Put(b)
   570  	case 384:
   571  		pool384.Put(b)
   572  	case 512:
   573  		pool512.Put(b)
   574  	case 768:
   575  		pool768.Put(b)
   576  	case 1024:
   577  		pool1024.Put(b)
   578  	case 2048:
   579  		pool2048.Put(b)
   580  	case 4096:
   581  		pool4096.Put(b)
   582  	case 8192:
   583  		pool8192.Put(b)
   584  	case 16384:
   585  		pool16384.Put(b)
   586  	case 32768:
   587  		pool32768.Put(b)
   588  	case 65536:
   589  		pool65536.Put(b)
   590  	}
   591  }
   592  
   593  const (
   594  	bitsize       = 32 << (^uint(0) >> 63)
   595  	maxint        = int(1<<(bitsize-1) - 1)
   596  	maxintHeadBit = 1 << (bitsize - 2)
   597  )
   598  
   599  // LogarithmicRange iterates from ceiled to power of two min to max,
   600  // calling cb on each iteration.
   601  func LogarithmicRange(min, max int, cb func(int)) {
   602  	if min == 0 {
   603  		min = 1
   604  	}
   605  	for n := ceilToPowerOfTwo(min); n <= max; n <<= 1 {
   606  		cb(n)
   607  	}
   608  }
   609  
   610  // IsPowerOfTwo reports whether given integer is a power of two.
   611  func IsPowerOfTwo(n int) bool {
   612  	return n&(n-1) == 0
   613  }
   614  
   615  // Identity is identity.
   616  func Identity(n int) int {
   617  	return n
   618  }
   619  
   620  // ceilToPowerOfTwo returns the least power of two integer value greater than
   621  // or equal to n.
   622  func ceilToPowerOfTwo(n int) int {
   623  	if n&maxintHeadBit != 0 && n > maxintHeadBit {
   624  		panic("argument is too large")
   625  	}
   626  	if n <= 2 {
   627  		return n
   628  	}
   629  	n--
   630  	n = fillBits(n)
   631  	n++
   632  	return n
   633  }
   634  
   635  // FloorToPowerOfTwo returns the greatest power of two integer value less than
   636  // or equal to n.
   637  func FloorToPowerOfTwo(n int) int {
   638  	if n <= 2 {
   639  		return n
   640  	}
   641  	n = fillBits(n)
   642  	n >>= 1
   643  	n++
   644  	return n
   645  }
   646  
   647  func fillBits(n int) int {
   648  	n |= n >> 1
   649  	n |= n >> 2
   650  	n |= n >> 4
   651  	n |= n >> 8
   652  	n |= n >> 16
   653  	n |= n >> 32
   654  	return n
   655  }