github.com/moontrade/unsafe@v0.9.1/memory/heap/class_test.go (about) 1 package heap 2 3 import ( 4 "fmt" 5 "sort" 6 "strconv" 7 "strings" 8 "testing" 9 ) 10 11 const ( 12 SMALL_DIV int = 4 13 SMALL_MAX int = 508 14 MEDIUM_DIV int = 256 15 MEDIUM_MAX int = 16380 16 LARGE_MAX int = 65536 * 256 17 HUGE_MAX int = 65536 * 256 18 ) 19 20 // divRoundUp returns ceil(n / a). 21 func divRoundUpInt(n, a int) int { 22 // a is generally a power of two. This will get inlined and 23 // the compiler will optimize the division. 24 return (n + a - 1) / a 25 } 26 27 func nextPowerOf2(v uint32) uint32 { 28 v-- 29 v |= v >> 1 30 v |= v >> 2 31 v |= v >> 4 32 v |= v >> 8 33 v |= v >> 16 34 return v + 1 35 } 36 37 var quark = []int{ 38 12, 28, 60, 124, 39 } 40 41 var nano = []int{ 42 12, 28, 44, 60, 124, 252, 508, 1020, 43 } 44 var nano16 = []int{ 45 14, 30, 46, 62, 126, 254, 510, 1020, 46 } 47 48 var micro = []int{ 49 8, 12, 16, 20, 28, 36, 44, 60, 76, 92, 50 124, 160, 208, 252, 380, 508, 764, 1020, 51 2044, 4092, 8188, 52 } 53 54 type Nano struct { 55 Free [8]uint16 56 } 57 58 var small = []int{ 59 12, 16, 20, 24, 28, 36, 44, 60, 76, 92, 124, 156, 188, 220, 252, 300, 364, 428, 508, 764, 60 1020, 1280, 1532, 2044, 4092, 8188, 16380, 61 } 62 63 var medium = []int{ 64 12, 16, 20, 24, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 104, 112, 120, 128, 136, 144, 152, 160, 168, 176, 192, 216, 232, 256, 384, 512, 768, 1024, 65 2048, 4096, 8192, 16384, 32768, 65536, 66 } 67 68 var large = []int{ 69 12, 16, 20, 24, 28, 36, 44, 60, 76, 92, 124, 156, 188, 220, 252, 300, 364, 428, 508, 764, 70 1020, 1280, 1532, 2044, 4092, 8188, 16380, 32764, 71 65534, 131098, 262140, 524284, 1048572, 2097148, 4194300, 8388604, 16777212, 72 } 73 74 func TestGenerate(t *testing.T) { 75 //{ 76 // g := *NewSizeClassGen( 77 // 4, 78 // 4, 79 // SMALL_MAX, 80 // 256, 81 // 4096, 82 // 4096, 83 // 32768, 84 // small, 85 // //[]int{ 86 // // 12, 16, 24, 32, 48, 64, 80, 96, 128, 256, 384, 512, 1024, 87 // // 2048, 4096, 88 // // 8192, 16384, 32768}, 89 // ) 90 // 91 // runtime.SetFinalizer(&g, func(s *SizeClassGen) { 92 // fmt.Println("SetFinalizer") 93 // }) 94 // runtime.GC() 95 //} 96 //runtime.GC() 97 fmt.Println("Small Size class count:", len(small)) 98 g := NewSizeClassGen( 99 4, 100 SMALL_DIV, 101 SMALL_MAX, 102 MEDIUM_DIV, 103 small[len(small)-1]+4, 104 0, 105 0, 106 NewSizeClasses(small...), 107 //[]int{ 108 // 12, 16, 24, 32, 48, 64, 80, 96, 128, 256, 384, 512, 1024, 109 // 2048, 4096, 110 // 8192, 16384, 32768}, 111 ) 112 113 a := divRoundUpInt(3976-g.Medium.Min, MEDIUM_DIV) 114 fmt.Println(a) 115 fmt.Println(a * MEDIUM_DIV) 116 fmt.Println(a*MEDIUM_DIV + g.Medium.Min) 117 118 fmt.Println("") 119 PrintSizeClassesStructInitializer(g.Classes) 120 fmt.Println("") 121 g.Small.PrintSizeClassesStructInitializer() 122 fmt.Println("") 123 g.Medium.PrintSizeClassesStructInitializer() 124 fmt.Println("") 125 //g.Small.PrintIndexes() 126 //g.Small.PrintClasses() 127 //g.Medium.PrintIndexes() 128 //g.Medium.PrintClasses() 129 130 //g.printSizeClass(0) 131 //g.printSizeClass(1) 132 //g.printSizeClass(9) 133 //g.printSizeClass(12) 134 //g.printSizeClass(13) 135 //g.printSizeClass(21) 136 //g.printSizeClass(29) 137 //g.printSizeClass(33) 138 //g.printSizeClass(36) 139 //g.printSizeClass(43) 140 //g.printSizeClass(59) 141 //g.printSizeClass(78) 142 //g.printSizeClass(256) 143 //g.printSizeClass(768) 144 //g.printSizeClass(1024) 145 //g.printSizeClass(1025) 146 g.printSizeClass(3976) 147 } 148 149 func (s *SizeClassGen) printSizeClass(size int) { 150 151 cls := s.Get(size) 152 if cls == nil { 153 fmt.Println("Size:", size, " is out of bounds!") 154 return 155 } 156 fmt.Println("["+strconv.Itoa(cls.Index)+"]"+" Size:", size, " Class:", cls.Size, " Shift:", cls.Shift) 157 } 158 159 type SizeClass struct { 160 Index int 161 Shift int 162 Size int 163 } 164 165 func NewSizeClasses(sizes ...int) []SizeClass { 166 sort.Ints(sizes) 167 classes := make([]SizeClass, len(sizes)) 168 for i := 0; i < len(sizes); i++ { 169 classes[i] = SizeClass{ 170 Index: i, 171 Shift: 31 - i, 172 Size: sizes[i], 173 } 174 } 175 return classes 176 } 177 178 type SizeClassGen struct { 179 wordSize int 180 Classes []SizeClass 181 Small *ClassRange 182 Medium *ClassRange 183 Large *ClassRange 184 smallBoundary int 185 mediumBoundary int 186 largeBoundary int 187 } 188 189 func NewSizeClassGen( 190 wordSize int, 191 smallSizeDiv int, 192 smallSizeMax int, 193 mediumSizeDiv int, 194 mediumSizeMax int, 195 largeSizeDiv int, 196 largeSizeMax int, 197 classes []SizeClass) *SizeClassGen { 198 199 if smallSizeMax < 8 || smallSizeDiv < 2 { 200 return nil 201 } 202 203 s := &SizeClassGen{wordSize: wordSize, Classes: classes} 204 s.Small = NewClassRange("small", 0, smallSizeMax, smallSizeDiv, classes) 205 206 if mediumSizeMax > 0 && closestFit(smallSizeMax+mediumSizeDiv, classes).Size > 0 { 207 s.Medium = NewClassRange("medium", smallSizeMax, mediumSizeMax, mediumSizeDiv, classes) 208 } 209 if mediumSizeMax > 0 && largeSizeMax > 0 && closestFit(mediumSizeMax+largeSizeDiv, classes).Size > 0 { 210 s.Large = NewClassRange("large", mediumSizeMax, largeSizeMax, largeSizeDiv, classes) 211 } 212 s.smallBoundary = smallSizeMax + 1 213 if s.Medium != nil { 214 s.mediumBoundary = mediumSizeMax + 1 215 } else { 216 s.mediumBoundary = 0 217 } 218 if s.Large != nil { 219 s.largeBoundary = largeSizeMax + 1 220 } else { 221 s.largeBoundary = 0 222 } 223 224 return s 225 } 226 227 func (s *SizeClassGen) Get(size int) *SizeClass { 228 if size < s.smallBoundary { 229 return s.Small.Get(size) 230 } else if size < s.mediumBoundary { 231 return s.Medium.Get(size) 232 } else if size < s.largeBoundary { 233 return s.Large.Get(size) 234 } 235 return nil 236 } 237 238 type ClassRange struct { 239 Name string 240 Div int 241 Min int 242 Max int 243 //Map []int 244 Classes []SizeClass 245 } 246 247 func NewClassRange(name string, min, max, div int, classes []SizeClass) *ClassRange { 248 max = max / div * div 249 r := &ClassRange{ 250 Name: name, 251 Min: min, 252 Max: max, 253 Div: div, 254 //Map: make([]int, (max-min)/div), 255 Classes: make([]SizeClass, (max-min)/div), 256 } 257 for index := 0; index < len(r.Classes); index++ { 258 size := min + (index * div) 259 //if size == 0 { 260 // small[0] = 0 261 // continue 262 //} 263 //size = divRoundUpInt(size, div)*div + min 264 265 // Find closes size 266 classIndex := closestFit(size, classes) 267 r.Classes[index] = classIndex 268 } 269 return r 270 } 271 272 func (c *ClassRange) Get(size int) *SizeClass { 273 index := divRoundUpInt(size-c.Min, c.Div) 274 return &c.Classes[index] 275 } 276 277 func (c *ClassRange) PrintSizeClassesStructInitializer() { 278 PrintSizeClassesStructInitializer(c.Classes) 279 } 280 281 func PrintSizeClassesStructInitializer(classes []SizeClass) { 282 b := strings.Builder{} 283 for i, cls := range classes { 284 if i%3 == 0 && i > 0 { 285 b.WriteString("\n") 286 } 287 288 b.WriteString("{") 289 b.WriteString(strconv.Itoa(cls.Index)) 290 b.WriteString(",") 291 b.WriteString(strconv.Itoa(cls.Shift)) 292 b.WriteString(",") 293 b.WriteString(strconv.Itoa(cls.Size)) 294 b.WriteString("},") 295 296 //if i < 4 { 297 // if i == 2 { 298 // b.WriteString("\n") 299 // } 300 // //if i == 2 { 301 // // b.WriteString("\n") 302 // //} 303 //} else if i%3 == 0 { 304 // b.WriteString("\n") 305 //} 306 } 307 fmt.Println(b.String()) 308 } 309 310 func (c *ClassRange) PrintClasses() { 311 PrintSizeClassesStructInitializer(c.Classes) 312 } 313 314 func closestFit(size int, classes []SizeClass) SizeClass { 315 for i := 0; i < len(classes); i++ { 316 cls := classes[i] 317 if size <= cls.Size { 318 return cls 319 } 320 } 321 return SizeClass{} 322 }