github.com/coyove/sdss@v0.0.0-20231129015646-c2ec58cca6a2/contrib/bitmap/utils.go (about)

     1  package bitmap
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"math/bits"
     8  	"os"
     9  	"time"
    10  
    11  	"github.com/coyove/sdss/contrib/clock"
    12  )
    13  
    14  type Values struct {
    15  	Oneof []uint64
    16  	Major []uint64
    17  	Exact []uint64
    18  }
    19  
    20  type meterWriter struct {
    21  	io.Writer
    22  	size int
    23  }
    24  
    25  func (m *meterWriter) Close() error {
    26  	return nil
    27  }
    28  
    29  func (m *meterWriter) Write(p []byte) (int, error) {
    30  	n, err := m.Writer.Write(p)
    31  	m.size += n
    32  	return n, err
    33  }
    34  
    35  func h16(v uint32, ts int64) (out [4]uint32) {
    36  	const mask = 0xffffffff
    37  	out[0] = combinehash(v, uint32(ts)) & mask
    38  	out[1] = combinehash(v, out[0]) & mask
    39  	out[2] = combinehash(v, out[1]) & mask
    40  	out[3] = combinehash(v, out[2]) & mask
    41  	return
    42  }
    43  
    44  func icmp(a, b int64) int {
    45  	if a > b {
    46  		return 1
    47  	}
    48  	if a < b {
    49  		return -1
    50  	}
    51  	return 0
    52  }
    53  
    54  func h32(index uint32, hash uint32) (out uint32) {
    55  	return index<<17 | hash&0x1ffff
    56  }
    57  
    58  func combinehash(k1, seed uint32) uint32 {
    59  	h1 := seed
    60  
    61  	k1 *= 0xcc9e2d51
    62  	k1 = bits.RotateLeft32(k1, 15)
    63  	k1 *= 0x1b873593
    64  
    65  	h1 ^= k1
    66  	h1 = bits.RotateLeft32(h1, 13)
    67  	h1 = h1*4 + h1 + 0xe6546b64
    68  
    69  	h1 ^= uint32(4)
    70  
    71  	h1 ^= h1 >> 16
    72  	h1 *= 0x85ebca6b
    73  	h1 ^= h1 >> 13
    74  	h1 *= 0xc2b2ae35
    75  	h1 ^= h1 >> 16
    76  
    77  	return h1
    78  }
    79  
    80  type KeyIdScore struct {
    81  	Key   Key
    82  	Id    int64
    83  	Score int
    84  }
    85  
    86  type JoinMetrics struct {
    87  	BaseStart   int64
    88  	Start       int64
    89  	Desc        bool
    90  	Values      Values
    91  	FastElapsed time.Duration
    92  	Elapsed     time.Duration
    93  	Slots       [slotNum]struct {
    94  		Scans, Hits int
    95  		Elapsed     time.Duration
    96  	}
    97  }
    98  
    99  func (jm JoinMetrics) String() string {
   100  	dir := "asc"
   101  	if jm.Desc {
   102  		dir = "desc"
   103  	}
   104  	x := fmt.Sprintf("join map [%d] start at %d (%s) in %vus",
   105  		jm.BaseStart, jm.Start, dir, jm.Elapsed.Microseconds())
   106  	x += fmt.Sprintf("\n\tinput: oneof=%d, major=%d (min=%d), exact=%d",
   107  		len(jm.Values.Oneof), len(jm.Values.Major), jm.Values.majorScore(), len(jm.Values.Exact))
   108  	x += fmt.Sprintf("\n\tfast lookup: %vus", jm.FastElapsed.Microseconds())
   109  
   110  	c := 0
   111  	for i := len(jm.Slots) - 1; i >= 0; i-- {
   112  		s := jm.Slots[i]
   113  		if s.Scans > 0 {
   114  			x += fmt.Sprintf("\n\tsubrange [%02d]: %4dus, %d out of %d",
   115  				i, s.Elapsed.Microseconds(), s.Hits, s.Scans)
   116  			if s.Hits == 0 {
   117  				x += " (NO HITS)"
   118  			}
   119  			c++
   120  		}
   121  	}
   122  	if c == 0 {
   123  		x += " (NO HITS)"
   124  	}
   125  	return x
   126  }
   127  
   128  func (b *Range) Save(path string, compress bool) (int, error) {
   129  	b.mfmu.Lock()
   130  	defer b.mfmu.Unlock()
   131  
   132  	bakpath := fmt.Sprintf("%s.%d.mtfbak", path, clock.Unix())
   133  
   134  	f, err := os.Create(bakpath)
   135  	if err != nil {
   136  		return 0, err
   137  	}
   138  	sz, err := b.Marshal(f, compress)
   139  	f.Close()
   140  	if err != nil {
   141  		return 0, err
   142  	}
   143  
   144  	if err := os.Remove(path); err != nil {
   145  		if !os.IsNotExist(err) {
   146  			return 0, err
   147  		}
   148  	}
   149  	return sz, os.Rename(bakpath, path)
   150  }
   151  
   152  func Load(path string) (*Range, error) {
   153  	f, err := os.Open(path)
   154  	if err != nil {
   155  		if os.IsNotExist(err) {
   156  			return nil, nil
   157  		}
   158  		return nil, err
   159  	}
   160  	defer f.Close()
   161  	return Unmarshal(f)
   162  }
   163  
   164  type bitmap1024 [fastSlotNum / 64]uint64
   165  
   166  func (b *bitmap1024) add(index uint16) { // [0, fastSlotNum)
   167  	(*b)[index/64] |= 1 << (index % 64)
   168  }
   169  
   170  func (b *bitmap1024) contains(index uint16) bool {
   171  	return (*b)[index/64]&(1<<(index%64)) > 0
   172  }
   173  
   174  func (b *bitmap1024) iterate(f func(uint16) bool) {
   175  	for si, s := range *b {
   176  		for i := 0; i < 64; i++ {
   177  			if s&(1<<i) > 0 {
   178  				if !f(uint16(si*64 + i)) {
   179  					return
   180  				}
   181  			}
   182  		}
   183  	}
   184  }
   185  
   186  func (b *bitmap1024) and(b2 *bitmap1024) {
   187  	for i := range *b {
   188  		(*b)[i] &= (*b2)[i]
   189  	}
   190  }
   191  
   192  func (b *bitmap1024) or(b2 *bitmap1024) {
   193  	for i := range *b {
   194  		(*b)[i] |= (*b2)[i]
   195  	}
   196  }
   197  
   198  func (b bitmap1024) String() string {
   199  	buf := bytes.NewBufferString("{fast bitmap")
   200  	for i := 0; i < fastSlotNum; i++ {
   201  		if b.contains(uint16(i)) {
   202  			fmt.Fprintf(buf, " %d", i)
   203  		}
   204  	}
   205  	buf.WriteString("}")
   206  	return buf.String()
   207  }
   208  
   209  func (vs *Values) majorScore() int {
   210  	s := len(vs.Major)
   211  	if s <= 2 {
   212  		return s
   213  	}
   214  	if s <= 4 {
   215  		return s - 1
   216  	}
   217  	return s * 4 / 5
   218  }
   219  
   220  func (v *Values) Clean() {
   221  	m := map[uint64]byte{}
   222  
   223  	add := func(a []uint64, typ byte) {
   224  		for _, v := range a {
   225  			m[v] = typ
   226  		}
   227  	}
   228  	remove := func(a []uint64, typ byte) []uint64 {
   229  		for i := len(a) - 1; i >= 0; i-- {
   230  			if m[a[i]] != typ {
   231  				a = append(a[:i], a[i+1:]...)
   232  			}
   233  		}
   234  		return a
   235  	}
   236  
   237  	add(v.Oneof, 'o')
   238  	add(v.Major, 'm')
   239  	add(v.Exact, 'e')
   240  
   241  	v.Oneof = remove(v.Oneof, 'o')
   242  	v.Major = remove(v.Major, 'm')
   243  	v.Exact = remove(v.Exact, 'e')
   244  }