github.com/QuangTung97/bigcache@v0.1.0/segment_test.go (about)

     1  package bigcache
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/QuangTung97/bigcache/memhash"
     6  	"github.com/stretchr/testify/assert"
     7  	"math/rand"
     8  	"testing"
     9  	"unsafe"
    10  )
    11  
    12  func TestEntryHeaderAlign(t *testing.T) {
    13  	assert.Equal(t, 20, entryHeaderSize)
    14  	assert.Equal(t, 4, entryHeaderAlign)
    15  }
    16  
    17  func newSegment() *segment {
    18  	s := &segment{}
    19  	initSegment(s, 1024)
    20  	return s
    21  }
    22  
    23  func newSegmentSize(bufSize int) *segment {
    24  	s := &segment{}
    25  	initSegment(s, bufSize)
    26  	return s
    27  }
    28  
    29  func (s *segment) getHeader(hash uint32) *entryHeader {
    30  	offset := s.kv[hash]
    31  	var headerData [entryHeaderSize]byte
    32  	s.rb.readAt(headerData[:], offset)
    33  	return (*entryHeader)(unsafe.Pointer(&headerData[0]))
    34  }
    35  
    36  func (s *segment) getSumTotalAccessTime() uint64 {
    37  	totalAccess := uint64(0)
    38  	for _, offset := range s.kv {
    39  		header := s.getHeaderAtOffset(offset)
    40  		totalAccess += uint64(header.accessTime)
    41  	}
    42  	return totalAccess
    43  }
    44  
    45  func (s *segment) getHeaderAtOffset(offset int) *entryHeader {
    46  	var headerData [entryHeaderSize]byte
    47  	s.rb.readAt(headerData[:], offset)
    48  	return (*entryHeader)(unsafe.Pointer(&headerData[0]))
    49  }
    50  
    51  func monoGetNow(start uint32) func() uint32 {
    52  	now := start
    53  	return func() uint32 {
    54  		now++
    55  		return now
    56  	}
    57  }
    58  
    59  func TestNextNumberAlignToHeader(t *testing.T) {
    60  	result := nextNumberAlignToHeader(7)
    61  	assert.Equal(t, uint32(8), result)
    62  
    63  	result = nextNumberAlignToHeader(12)
    64  	assert.Equal(t, uint32(12), result)
    65  }
    66  
    67  func TestSegmentSizeAlignToCacheLine(t *testing.T) {
    68  	assert.Equal(t, 64*2, int(unsafe.Sizeof(segment{})))
    69  }
    70  
    71  func TestSegment_Simple_Set_Get(t *testing.T) {
    72  	s := newSegment()
    73  	s.put(40, []byte{1, 2, 3}, []byte{10, 11, 12, 13})
    74  
    75  	data := make([]byte, 10)
    76  	n, ok := s.get(40, []byte{1, 2, 3}, data)
    77  	assert.Equal(t, true, ok)
    78  	assert.Equal(t, 4, n)
    79  	assert.Equal(t, []byte{10, 11, 12, 13}, data[:n])
    80  
    81  	assert.Equal(t, 0, s.rb.getBegin())
    82  	assert.Equal(t, entryHeaderSize+8, s.rb.getEnd())
    83  	assert.Equal(t, 1024-entryHeaderSize-8, s.rb.getAvailable())
    84  
    85  	assert.Equal(t, uint64(1), s.getAccessCount())
    86  	assert.Equal(t, uint64(1), s.getHitCount())
    87  }
    88  
    89  func TestSegment_Simple_Set_With_Not_Enough_Space(t *testing.T) {
    90  	s := newSegment()
    91  	s.put(40, []byte{1, 2, 3}, []byte{10, 11, 12, 13, 14, 15})
    92  
    93  	data := make([]byte, 5)
    94  	n, ok := s.get(40, []byte{1, 2, 3}, data)
    95  	assert.Equal(t, true, ok)
    96  	assert.Equal(t, 6, n)
    97  	assert.Equal(t, []byte{10, 11, 12, 13, 14}, data)
    98  }
    99  
   100  func TestSegment_Set_Get_Not_Equal_Hash(t *testing.T) {
   101  	s := newSegment()
   102  	s.put(40, []byte{1, 2, 3}, []byte{10, 11, 12, 13})
   103  
   104  	n, ok := s.get(50, []byte{1, 2, 3}, nil)
   105  	assert.Equal(t, false, ok)
   106  	assert.Equal(t, 0, n)
   107  
   108  	assert.Equal(t, uint64(1), s.getAccessCount())
   109  	assert.Equal(t, uint64(0), s.getHitCount())
   110  }
   111  
   112  func TestSegment_Set_Get_Key_Not_Equal_Length(t *testing.T) {
   113  	s := newSegment()
   114  	s.put(40, []byte{1, 2, 3, 4, 5, 6, 7, 8}, []byte{10, 11, 12, 13})
   115  
   116  	assert.Equal(t, uint64(0), s.getAccessCount())
   117  
   118  	n, ok := s.get(40, []byte{1, 2, 3}, nil)
   119  	assert.Equal(t, false, ok)
   120  	assert.Equal(t, 0, n)
   121  
   122  	assert.Equal(t, uint64(1), s.getAccessCount())
   123  	assert.Equal(t, uint64(0), s.getHitCount())
   124  }
   125  
   126  func TestSegment_Set_Get_Not_Equal_Key(t *testing.T) {
   127  	s := newSegment()
   128  	s.put(40, []byte{1, 2, 3}, []byte{10, 11, 12, 13})
   129  
   130  	n, ok := s.get(40, []byte{1, 2, 4}, nil)
   131  	assert.Equal(t, false, ok)
   132  	assert.Equal(t, 0, n)
   133  
   134  	assert.Equal(t, uint64(1), s.getAccessCount())
   135  	assert.Equal(t, uint64(0), s.getHitCount())
   136  }
   137  
   138  func TestSegment_Get_Access_Time(t *testing.T) {
   139  	s := newSegment()
   140  	s.getNow = func() uint32 { return 120 }
   141  	s.put(40, []byte{1, 2, 3}, []byte{10, 11, 12, 13})
   142  	header := s.getHeader(40)
   143  	assert.Equal(t, &entryHeader{
   144  		hash:       40,
   145  		accessTime: 120,
   146  		keyLen:     3,
   147  		deleted:    false,
   148  		valLen:     4,
   149  		valCap:     5,
   150  	}, header)
   151  }
   152  
   153  func TestSegment_Get_Update_Access_Time(t *testing.T) {
   154  	s := newSegment()
   155  	s.getNow = func() uint32 { return 120 }
   156  
   157  	s.put(40, []byte{1, 2, 3}, []byte{10, 11, 12, 13})
   158  
   159  	s.getNow = func() uint32 { return 140 }
   160  	data := make([]byte, 4)
   161  	s.get(40, []byte{1, 2, 3}, data)
   162  
   163  	header := s.getHeader(40)
   164  	assert.Equal(t, &entryHeader{
   165  		hash:       40,
   166  		accessTime: 140,
   167  		keyLen:     3,
   168  		deleted:    false,
   169  		valLen:     4,
   170  		valCap:     5,
   171  	}, header)
   172  }
   173  
   174  func TestSegment_Put_With_Exist_Key_Same_Length(t *testing.T) {
   175  	s := newSegment()
   176  	s.put(40, []byte{1, 2, 3}, []byte{10, 11, 12, 13})
   177  	prevAvail := s.rb.getAvailable()
   178  	s.put(40, []byte{1, 2, 3}, []byte{20, 21, 22, 23})
   179  
   180  	assert.Equal(t, 1, len(s.kv))
   181  	assert.Equal(t, uint64(1), s.getTotal())
   182  	assert.Equal(t, entryHeaderSize+8, s.rb.getEnd())
   183  	assert.Equal(t, prevAvail, s.rb.getAvailable())
   184  
   185  	data := make([]byte, 100)
   186  	n, ok := s.get(40, []byte{1, 2, 3}, data)
   187  	assert.Equal(t, true, ok)
   188  	assert.Equal(t, []byte{20, 21, 22, 23}, data[:n])
   189  }
   190  
   191  func TestSegment_Put_With_Exist_Key_Same_Length_Different_Length_Still_In_Cap(t *testing.T) {
   192  	s := newSegment()
   193  	s.getNow = func() uint32 { return 100 }
   194  	s.put(40, []byte{1, 2, 3}, []byte{10, 11, 12, 13})
   195  
   196  	prevAvail := s.rb.getAvailable()
   197  
   198  	s.getNow = func() uint32 { return 110 }
   199  	s.put(40, []byte{1, 2, 3}, []byte{20, 21, 22, 23, 24})
   200  
   201  	assert.Equal(t, 1, len(s.kv))
   202  	assert.Equal(t, uint64(1), s.getTotal())
   203  	assert.Equal(t, entryHeaderSize+8, s.rb.getEnd())
   204  	assert.Equal(t, prevAvail, s.rb.getAvailable())
   205  
   206  	header := s.getHeader(40)
   207  	assert.Equal(t, &entryHeader{
   208  		hash:       40,
   209  		accessTime: 110,
   210  		keyLen:     3,
   211  		valLen:     5,
   212  		valCap:     5,
   213  	}, header)
   214  
   215  	data := make([]byte, 100)
   216  	n, ok := s.get(40, []byte{1, 2, 3}, data)
   217  	assert.Equal(t, true, ok)
   218  	assert.Equal(t, []byte{20, 21, 22, 23, 24}, data[:n])
   219  }
   220  
   221  func TestSegment_Put_With_Exist_Key_Not_In_Cap(t *testing.T) {
   222  	s := newSegment()
   223  
   224  	s.put(40, []byte{1, 2, 3}, []byte{10, 11, 12, 13})
   225  
   226  	prevAvail := s.rb.getAvailable()
   227  	s.put(40, []byte{1, 2, 3}, []byte{20, 21, 22, 23, 24, 25})
   228  
   229  	assert.Equal(t, 1, len(s.kv))
   230  	assert.Equal(t, uint64(1), s.getTotal())
   231  	assert.Equal(t, entryHeaderSize*2+8+12, s.rb.getEnd())
   232  	assert.Equal(t, prevAvail-entryHeaderSize-12, s.rb.getAvailable())
   233  
   234  	data := make([]byte, 100)
   235  	n, ok := s.get(40, []byte{1, 2, 3}, data)
   236  	assert.Equal(t, true, ok)
   237  	assert.Equal(t, []byte{20, 21, 22, 23, 24, 25}, data[:n])
   238  
   239  	header := s.getHeaderAtOffset(0)
   240  	assert.Equal(t, true, header.deleted)
   241  }
   242  
   243  func TestSegment_Put_Same_Hash_Diff_Key(t *testing.T) {
   244  	s := newSegment()
   245  	s.put(40, []byte{1, 2, 3}, []byte{10, 11, 12})
   246  	s.put(40, []byte{5, 6, 7, 8, 9}, []byte{20, 21, 22, 23})
   247  
   248  	header := s.getHeaderAtOffset(0)
   249  	assert.Equal(t, true, header.deleted)
   250  
   251  	data := make([]byte, 100)
   252  	n, ok := s.get(40, []byte{1, 2, 3}, data)
   253  	assert.Equal(t, false, ok)
   254  	assert.Equal(t, 0, n)
   255  
   256  	data = make([]byte, 100)
   257  	n, ok = s.get(40, []byte{5, 6, 7, 8, 9}, data)
   258  	assert.Equal(t, true, ok)
   259  	assert.Equal(t, []byte{20, 21, 22, 23}, data[:n])
   260  }
   261  
   262  func TestSegment_Put_Evacuate(t *testing.T) {
   263  	s := newSegmentSize(entryHeaderSize*3 + 8 + 12 + 8)
   264  	s.getNow = monoGetNow(0)
   265  
   266  	s.put(40, []byte{1, 2, 3}, []byte{10, 11, 12})
   267  	s.put(41, []byte{5, 6, 7}, []byte{20, 21, 22, 23, 24, 25})
   268  	s.put(42, []byte{8, 9, 0}, []byte{30, 31})
   269  	s.put(43, []byte{100, 101, 102}, []byte{40, 41, 42})
   270  
   271  	assert.Equal(t, 3, len(s.kv))
   272  	assert.Equal(t, uint64(3), s.getTotal())
   273  	assert.Equal(t, entryHeaderSize+8, s.rb.getBegin())
   274  
   275  	data := make([]byte, 100)
   276  	n, ok := s.get(40, []byte{1, 2, 3}, data)
   277  	assert.Equal(t, false, ok)
   278  	assert.Equal(t, 0, n)
   279  
   280  	assert.Equal(t, s.totalAccessTime, s.getSumTotalAccessTime())
   281  }
   282  
   283  func TestSegment_Put_Evacuate_Skip_Recent_Used(t *testing.T) {
   284  	const entrySize = entryHeaderSize + 8
   285  	s := newSegmentSize(entrySize * 5)
   286  	s.getNow = monoGetNow(0)
   287  
   288  	s.put(40, []byte{1, 2, 0}, []byte{101, 102, 103, 100})
   289  	s.put(41, []byte{1, 2, 1}, []byte{101, 102, 103, 101})
   290  	s.put(42, []byte{1, 2, 2}, []byte{101, 102, 103, 102})
   291  	s.put(43, []byte{1, 2, 3}, []byte{101, 102, 103, 103})
   292  	s.put(44, []byte{1, 2, 4}, []byte{101, 102, 103, 104})
   293  
   294  	assert.Equal(t, 0, s.rb.getAvailable())
   295  	assert.Equal(t, uint64(5), s.getTotal())
   296  
   297  	data := make([]byte, 100)
   298  
   299  	s.get(40, []byte{1, 2, 0}, data)
   300  	s.put(45, []byte{1, 2, 5}, []byte{101, 102, 103, 105})
   301  
   302  	assert.Equal(t, uint64(5), s.getTotal())
   303  
   304  	data = make([]byte, 100)
   305  	n, ok := s.get(40, []byte{1, 2, 0}, data)
   306  	assert.Equal(t, true, ok)
   307  	assert.Equal(t, []byte{101, 102, 103, 100}, data[:n])
   308  
   309  	_, ok = s.get(41, []byte{1, 2, 1}, data)
   310  	assert.Equal(t, false, ok)
   311  
   312  	_, ok = s.get(42, []byte{1, 2, 2}, data)
   313  	assert.Equal(t, true, ok)
   314  
   315  	assert.Equal(t, s.totalAccessTime, s.getSumTotalAccessTime())
   316  }
   317  
   318  func TestSegment_Put_Evacuate_Reach_Max_Evacuation(t *testing.T) {
   319  	const entrySize = entryHeaderSize + 8
   320  	s := newSegmentSize(entrySize * 12)
   321  	s.getNow = monoGetNow(0)
   322  
   323  	s.put(40, []byte{1, 2, 0}, []byte{101, 102, 103, 100})
   324  	s.put(41, []byte{1, 2, 1}, []byte{101, 102, 103, 101})
   325  	s.put(42, []byte{1, 2, 2}, []byte{101, 102, 103, 102})
   326  	s.put(43, []byte{1, 2, 3}, []byte{101, 102, 103, 103})
   327  
   328  	s.put(44, []byte{1, 2, 4}, []byte{101, 102, 103, 104})
   329  	s.put(45, []byte{1, 2, 5}, []byte{101, 102, 103, 105})
   330  	s.put(46, []byte{1, 2, 6}, []byte{101, 102, 103, 106})
   331  	s.put(47, []byte{1, 2, 7}, []byte{101, 102, 103, 107})
   332  
   333  	s.put(48, []byte{1, 2, 8}, []byte{101, 102, 103, 108})
   334  	s.put(49, []byte{1, 2, 9}, []byte{101, 102, 103, 109})
   335  	s.put(50, []byte{1, 2, 10}, []byte{101, 102, 103, 110})
   336  	s.put(51, []byte{1, 2, 11}, []byte{101, 102, 103, 111})
   337  
   338  	data := make([]byte, 100)
   339  	s.get(40, []byte{1, 2, 0}, data)
   340  	s.get(41, []byte{1, 2, 1}, data)
   341  	s.get(42, []byte{1, 2, 2}, data)
   342  	s.get(43, []byte{1, 2, 3}, data)
   343  
   344  	s.get(44, []byte{1, 2, 4}, data)
   345  	s.get(45, []byte{1, 2, 5}, data)
   346  
   347  	s.put(52, []byte{1, 2, 12}, []byte{101, 102, 103, 112})
   348  
   349  	data = make([]byte, 100)
   350  	n, ok := s.get(45, []byte{1, 2, 5}, data)
   351  	assert.Equal(t, false, ok)
   352  	assert.Equal(t, []byte{}, data[:n])
   353  
   354  	data = make([]byte, 100)
   355  	n, ok = s.get(46, []byte{1, 2, 6}, data)
   356  	assert.Equal(t, true, ok)
   357  	assert.Equal(t, []byte{101, 102, 103, 106}, data[:n])
   358  
   359  	assert.Equal(t, s.totalAccessTime, s.getSumTotalAccessTime())
   360  }
   361  
   362  func TestSegment_Put_Existing_Check_Total_Access_Time(t *testing.T) {
   363  	s := newSegment()
   364  	s.getNow = monoGetNow(200)
   365  
   366  	s.put(40, []byte{1, 2, 3}, []byte{101, 102, 103, 104})
   367  	s.put(40, []byte{1, 2, 3}, []byte{101, 102, 103, 0})
   368  
   369  	assert.Equal(t, s.totalAccessTime, s.getSumTotalAccessTime())
   370  }
   371  
   372  func TestSegment_Put_Same_Hash_Diff_Key_Check_Total_Access_Time(t *testing.T) {
   373  	s := newSegment()
   374  	s.getNow = monoGetNow(200)
   375  
   376  	s.put(40, []byte{1, 2, 3}, []byte{101, 102, 103, 104})
   377  	s.put(40, []byte{1, 2, 4}, []byte{101, 102, 103, 0})
   378  
   379  	assert.Equal(t, uint64(1), s.getTotal())
   380  	assert.Equal(t, s.totalAccessTime, s.getSumTotalAccessTime())
   381  }
   382  
   383  func TestSegment_Delete_Simple(t *testing.T) {
   384  	s := newSegment()
   385  	s.getNow = monoGetNow(200)
   386  
   387  	s.put(40, []byte{1, 2, 3}, []byte{101, 102, 103, 104})
   388  	affected := s.delete(40, []byte{1, 2, 3})
   389  	assert.Equal(t, true, affected)
   390  
   391  	assert.Equal(t, uint64(0), s.getTotal())
   392  
   393  	data := make([]byte, 100)
   394  	n, ok := s.get(40, []byte{1, 2, 3}, data)
   395  	assert.Equal(t, false, ok)
   396  	assert.Equal(t, 0, n)
   397  	assert.Equal(t, s.totalAccessTime, s.getSumTotalAccessTime())
   398  }
   399  
   400  func TestSegment_Delete_Different_Hash(t *testing.T) {
   401  	s := newSegment()
   402  	s.getNow = monoGetNow(200)
   403  
   404  	s.put(40, []byte{1, 2, 3}, []byte{101, 102, 103, 104})
   405  	s.put(41, []byte{1, 2, 4}, []byte{101, 102, 103, 105})
   406  
   407  	affected := s.delete(42, []byte{1, 2, 3})
   408  	assert.Equal(t, false, affected)
   409  
   410  	assert.Equal(t, uint64(2), s.getTotal())
   411  
   412  	data := make([]byte, 100)
   413  	n, ok := s.get(40, []byte{1, 2, 3}, data)
   414  	assert.Equal(t, true, ok)
   415  	assert.Equal(t, []byte{101, 102, 103, 104}, data[:n])
   416  	assert.Equal(t, s.totalAccessTime, s.getSumTotalAccessTime())
   417  }
   418  
   419  func TestSegment_Delete_Same_Hash_Diff_Key(t *testing.T) {
   420  	s := newSegment()
   421  	s.getNow = monoGetNow(200)
   422  
   423  	s.put(40, []byte{1, 2, 3}, []byte{101, 102, 103, 104})
   424  	s.put(41, []byte{1, 2, 4}, []byte{101, 102, 103, 105})
   425  
   426  	affected := s.delete(40, []byte{1, 2, 5})
   427  	assert.Equal(t, false, affected)
   428  
   429  	assert.Equal(t, uint64(2), s.getTotal())
   430  
   431  	data := make([]byte, 100)
   432  	n, ok := s.get(40, []byte{1, 2, 3}, data)
   433  	assert.Equal(t, true, ok)
   434  	assert.Equal(t, []byte{101, 102, 103, 104}, data[:n])
   435  	assert.Equal(t, s.totalAccessTime, s.getSumTotalAccessTime())
   436  }
   437  
   438  func TestSegment_Delete_Already_Deleted(t *testing.T) {
   439  	s := newSegment()
   440  	s.getNow = monoGetNow(200)
   441  
   442  	s.put(40, []byte{1, 2, 3}, []byte{101, 102, 103, 104})
   443  	s.put(41, []byte{1, 2, 4}, []byte{101, 102, 103, 105})
   444  
   445  	affected := s.delete(40, []byte{1, 2, 3})
   446  	assert.Equal(t, true, affected)
   447  
   448  	assert.Equal(t, uint64(1), s.getTotal())
   449  
   450  	affected = s.delete(40, []byte{1, 2, 3})
   451  	assert.Equal(t, false, affected)
   452  
   453  	assert.Equal(t, uint64(1), s.getTotal())
   454  
   455  	data := make([]byte, 100)
   456  	n, ok := s.get(40, []byte{1, 2, 3}, data)
   457  	assert.Equal(t, false, ok)
   458  	assert.Equal(t, 0, n)
   459  }
   460  
   461  func TestSegment_Put_Evacuate_After_Deleted(t *testing.T) {
   462  	const entrySize = entryHeaderSize + 8
   463  	s := newSegmentSize(entrySize * 5)
   464  	s.getNow = monoGetNow(0)
   465  
   466  	s.put(40, []byte{1, 2, 0}, []byte{101, 102, 103, 100})
   467  	s.put(41, []byte{1, 2, 1}, []byte{101, 102, 103, 101})
   468  	s.put(42, []byte{1, 2, 2}, []byte{101, 102, 103, 102})
   469  	s.put(43, []byte{1, 2, 3}, []byte{101, 102, 103, 103})
   470  	s.put(44, []byte{1, 2, 4}, []byte{101, 102, 103, 104})
   471  
   472  	data := make([]byte, 100)
   473  	s.get(40, []byte{1, 2, 0}, data)
   474  	s.delete(40, []byte{1, 2, 0})
   475  
   476  	assert.Equal(t, uint64(4), s.getTotal())
   477  	assert.Equal(t, 4, len(s.kv))
   478  
   479  	s.put(45, []byte{1, 2, 5}, []byte{101, 102, 103, 105})
   480  
   481  	assert.Equal(t, uint64(5), s.getTotal())
   482  	assert.Equal(t, 5, len(s.kv))
   483  
   484  	data = make([]byte, 100)
   485  	n, ok := s.get(41, []byte{1, 2, 1}, data)
   486  	assert.Equal(t, true, ok)
   487  	assert.Equal(t, []byte{101, 102, 103, 101}, data[:n])
   488  }
   489  
   490  func TestSegment_Put_Evacuate_Need_Reset_ConsecutiveEvacuation(t *testing.T) {
   491  	const entrySize = entryHeaderSize + 8
   492  	s := newSegmentSize(entrySize * 12)
   493  	s.maxConsecutiveEvacuation = 2
   494  	s.getNow = monoGetNow(0)
   495  
   496  	s.put(40, []byte{1, 2, 0}, []byte{101, 102, 103, 100})
   497  	s.put(41, []byte{1, 2, 1}, []byte{101, 102, 103, 101})
   498  	s.put(42, []byte{1, 2, 2}, []byte{101, 102, 103, 102})
   499  	s.put(43, []byte{1, 2, 3}, []byte{101, 102, 103, 103})
   500  
   501  	s.put(44, []byte{1, 2, 4}, []byte{101, 102, 103, 104})
   502  	s.put(45, []byte{1, 2, 5}, []byte{101, 102, 103, 105})
   503  	s.put(46, []byte{1, 2, 6}, []byte{101, 102, 103, 106})
   504  	s.put(47, []byte{1, 2, 7}, []byte{101, 102, 103, 107})
   505  
   506  	s.put(48, []byte{1, 2, 8}, []byte{101, 102, 103, 108})
   507  	s.put(49, []byte{1, 2, 9}, []byte{101, 102, 103, 109})
   508  	s.put(50, []byte{1, 2, 10}, []byte{101, 102, 103, 110})
   509  	s.put(51, []byte{1, 2, 11}, []byte{101, 102, 103, 111})
   510  
   511  	data := make([]byte, 100)
   512  	s.get(40, []byte{1, 2, 0}, data)
   513  	s.get(41, []byte{1, 2, 1}, data)
   514  	s.get(42, []byte{1, 2, 2}, data)
   515  	s.get(43, []byte{1, 2, 3}, data)
   516  
   517  	s.get(44, []byte{1, 2, 4}, data)
   518  
   519  	s.put(60, []byte{5, 5, 5}, []byte{10, 10, 10, 10, 10, 10})
   520  
   521  	_, ok := s.get(40, []byte{1, 2, 0}, data)
   522  	assert.Equal(t, true, ok)
   523  	_, ok = s.get(41, []byte{1, 2, 1}, data)
   524  	assert.Equal(t, true, ok)
   525  	_, ok = s.get(42, []byte{1, 2, 2}, data)
   526  	assert.Equal(t, false, ok)
   527  	_, ok = s.get(43, []byte{1, 2, 3}, data)
   528  	assert.Equal(t, true, ok)
   529  	_, ok = s.get(44, []byte{1, 2, 4}, data)
   530  	assert.Equal(t, true, ok)
   531  	_, ok = s.get(45, []byte{1, 2, 5}, data)
   532  	assert.Equal(t, false, ok)
   533  
   534  	assert.Equal(t, 11, len(s.kv))
   535  	assert.Equal(t, uint64(11), s.getTotal())
   536  	assert.Equal(t, s.totalAccessTime, s.getSumTotalAccessTime())
   537  }
   538  
   539  func fillRandom(data []byte) {
   540  	_, err := rand.Read(data)
   541  	if err != nil {
   542  		panic(err)
   543  	}
   544  }
   545  
   546  func appendKeyValue(key []byte, val []byte) []byte {
   547  	data := make([]byte, len(key)+len(val)-1)
   548  	copy(data, key)
   549  	copy(data[len(key):], val[1:])
   550  	return data
   551  }
   552  
   553  func TestAppendKeyValue(t *testing.T) {
   554  	data := appendKeyValue([]byte{1, 2, 3}, []byte{4, 5, 6, 7})
   555  	assert.Equal(t, []byte{1, 2, 3, 5, 6, 7}, data)
   556  }
   557  
   558  func TestSegment_Stress_Testing(t *testing.T) {
   559  	s := newSegmentSize(123456)
   560  	s.getNow = monoGetNow(0)
   561  
   562  	type keyUsed struct {
   563  		hash uint64
   564  		key  []byte
   565  	}
   566  
   567  	const keyCount = 10000
   568  	const touchCount = 5
   569  
   570  	keyUsedList := make([]keyUsed, 0, keyCount)
   571  
   572  	placeholder := make([]byte, 1000)
   573  
   574  	for i := 0; i < keyCount; i++ {
   575  		keyLen := 2 + rand.Intn(10)
   576  		key := make([]byte, keyLen)
   577  		fillRandom(key)
   578  		hash := memhash.Hash(key) & 0xfff
   579  		keyUsedList = append(keyUsedList, keyUsed{
   580  			key:  key,
   581  			hash: hash,
   582  		})
   583  	}
   584  
   585  	for i := 0; i < keyCount*3; i++ {
   586  		valueLen := 1 + rand.Intn(50)
   587  		value := make([]byte, valueLen)
   588  		fillRandom(value)
   589  
   590  		for k := 0; k < touchCount; k++ {
   591  			index := rand.Intn(keyCount)
   592  			e := keyUsedList[index]
   593  			s.get(uint32(e.hash), e.key, placeholder)
   594  		}
   595  
   596  		index := rand.Intn(keyCount)
   597  		e := keyUsedList[index]
   598  
   599  		h := memhash.Hash(appendKeyValue(e.key, value))
   600  		value[0] = uint8(h)
   601  
   602  		putOrDelete := rand.Intn(3)
   603  		if putOrDelete < 2 {
   604  			s.put(uint32(e.hash), e.key, value)
   605  		} else {
   606  			s.delete(uint32(e.hash), e.key)
   607  		}
   608  	}
   609  
   610  	for _, e := range keyUsedList {
   611  		data := make([]byte, 100)
   612  		n, ok := s.get(uint32(e.hash), e.key, data)
   613  		if ok {
   614  			value := data[:n]
   615  			h := memhash.Hash(appendKeyValue(e.key, value))
   616  			assert.Equal(t, uint8(h), value[0])
   617  		}
   618  	}
   619  
   620  	assert.Equal(t, uint64((touchCount*3+1)*keyCount), s.getAccessCount())
   621  	assert.Equal(t, len(s.kv), int(s.getTotal()))
   622  	assert.Equal(t, s.totalAccessTime, s.getSumTotalAccessTime())
   623  
   624  	fmt.Println(s.getHitCount())
   625  	fmt.Println(s.getAccessCount())
   626  	fmt.Println("TOTAL:", s.getTotal())
   627  	fmt.Println("LEN:", len(s.kv))
   628  }
   629  
   630  func BenchmarkSegmentPut(b *testing.B) {
   631  	b.StopTimer()
   632  
   633  	key := make([]byte, 32)
   634  	value := make([]byte, 200)
   635  	data := make([]byte, 500)
   636  
   637  	num := (*uint64)(unsafe.Pointer(&key[0]))
   638  
   639  	fillRandom(key)
   640  	fillRandom(value)
   641  
   642  	tmp := make([]byte, len(key))
   643  	copy(tmp, key)
   644  
   645  	s := newSegmentSize(2000000)
   646  
   647  	const actionCount = 10000
   648  
   649  	b.StartTimer()
   650  	hitCount := 0
   651  	for n := 0; n < b.N; n++ {
   652  		for i := 0; i < actionCount; i++ {
   653  			*num++
   654  			hash := memhash.Hash(key)
   655  			s.put(uint32(hash), key, value)
   656  		}
   657  
   658  		copy(key, tmp)
   659  
   660  		for i := 0; i < actionCount; i++ {
   661  			*num++
   662  			hash := memhash.Hash(key)
   663  			_, ok := s.get(uint32(hash), key, data)
   664  			if ok {
   665  				hitCount++
   666  			}
   667  		}
   668  	}
   669  	fmt.Println(hitCount, b.N)
   670  }