/
cache.go
87 lines (80 loc) 路 2.77 KB
/
cache.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package strategies
import (
"context"
"github.com/1pkg/gopium/collections"
"github.com/1pkg/gopium/gopium"
)
// list of cache presets
var (
cachel1d = cache{line: 1, div: true}
cachel2d = cache{line: 2, div: true}
cachel3d = cache{line: 3, div: true}
cachebd = cache{div: true}
cachel1f = cache{line: 1, div: false}
cachel2f = cache{line: 2, div: false}
cachel3f = cache{line: 3, div: false}
cachebf = cache{div: false}
)
// cache defines strategy implementation
// that fits structure into cpu cache line
// by adding bottom rounding cpu cache padding
type cache struct {
curator gopium.Curator `gopium:"filter_pads,memory_pack,cache_rounding_cpu_l1_discrete,struct_annotate_comment,add_tag_group_force"`
line uint `gopium:"filter_pads,memory_pack,cache_rounding_cpu_l1_discrete,struct_annotate_comment,add_tag_group_force"`
bytes uint `gopium:"filter_pads,memory_pack,cache_rounding_cpu_l1_discrete,struct_annotate_comment,add_tag_group_force"`
div bool `gopium:"filter_pads,memory_pack,cache_rounding_cpu_l1_discrete,struct_annotate_comment,add_tag_group_force"`
_ [31]byte `gopium:"filter_pads,memory_pack,cache_rounding_cpu_l1_discrete,struct_annotate_comment,add_tag_group_force"`
} // struct size: 64 bytes; struct align: 8 bytes; struct aligned size: 64 bytes; - 馃尯 gopium @1pkg
// Bytes erich cache strategy with custom bytes
func (stg cache) Bytes(bytes uint) cache {
stg.bytes = bytes
return stg
}
// Curator erich cache strategy with curator instance
func (stg cache) Curator(curator gopium.Curator) cache {
stg.curator = curator
return stg
}
// Apply cache implementation
func (stg cache) Apply(ctx context.Context, o gopium.Struct) (gopium.Struct, error) {
// copy original structure to result
r := collections.CopyStruct(o)
// calculate aligned size of structure
var alsize int64
collections.WalkStruct(r, 0, func(pad int64, fields ...gopium.Field) {
// add pad to aligned size
// only if it's not last pad
if len(fields) > 0 {
alsize += pad
}
// go through all fields
for _, f := range fields {
// add field size aligned sizes
alsize += f.Size
}
})
// check if cache line size or bytes are valid
if cachel := stg.curator.SysCache(stg.line); cachel > 0 || stg.bytes > 0 {
if stg.line == 0 {
cachel = int64(stg.bytes)
}
// if fractional cache line is allowed
if stg.div {
// find smallest size of fraction for cache line
if alsize > 0 && cachel > alsize {
for cachel >= alsize && cachel > 1 {
cachel /= 2
}
cachel *= 2
}
}
// get number of padding bytes
// to fill cpu cache line
// if padding is valid append it
if pad := alsize % cachel; pad > 0 {
pad = cachel - pad
r.Fields = append(r.Fields, collections.PadField(pad))
}
}
return r, ctx.Err()
}