github.com/scottcagno/storage@v1.8.0/pkg/hashmap/openaddr/rhhmap_test.go (about)

     1  package openaddr
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"github.com/scottcagno/storage/pkg/bits"
     7  	"github.com/scottcagno/storage/pkg/util"
     8  	"math/rand"
     9  	"strconv"
    10  	"testing"
    11  )
    12  
    13  // 25 words
    14  var words = []string{
    15  	"reproducibility",
    16  	"eruct",
    17  	"acids",
    18  	"flyspecks",
    19  	"driveshafts",
    20  	"volcanically",
    21  	"discouraging",
    22  	"acapnia",
    23  	"phenazines",
    24  	"hoarser",
    25  	"abusing",
    26  	"samara",
    27  	"thromboses",
    28  	"impolite",
    29  	"drivennesses",
    30  	"tenancy",
    31  	"counterreaction",
    32  	"kilted",
    33  	"linty",
    34  	"kistful",
    35  	"biomarkers",
    36  	"infusiblenesses",
    37  	"capsulate",
    38  	"reflowering",
    39  	"heterophyllies",
    40  }
    41  
    42  func Test_defaultHashFunc(t *testing.T) {
    43  	set := make(map[uint64]string, len(words))
    44  	var hash uint64
    45  	var coll int
    46  	for _, word := range words {
    47  		hash = defaultHashFunc(word)
    48  		if old, ok := set[hash]; !ok {
    49  			set[hash] = word
    50  		} else {
    51  			coll++
    52  			fmt.Printf(
    53  				"collision: current word: %s, old word: %s, hash: %d\n", word, old, hash)
    54  		}
    55  	}
    56  	fmt.Printf("encountered %d collisions comparing %d words\n", coll, len(words))
    57  }
    58  
    59  func Test_HashMap_Del(t *testing.T) {
    60  	hm := NewHashMap(128)
    61  	for i := 0; i < len(words); i++ {
    62  		hm.Set(words[i], []byte{0x69})
    63  	}
    64  	util.AssertExpected(t, 25, hm.Len())
    65  	count := hm.Len()
    66  	var stop = hm.Len()
    67  	for i := 0; i < stop; i++ {
    68  		ret, ok := hm.Del(words[i])
    69  		util.AssertExpected(t, true, ok)
    70  		util.AssertExpected(t, []byte{0x69}, ret)
    71  		count--
    72  	}
    73  	util.AssertExpected(t, 0, count)
    74  	hm.Close()
    75  }
    76  
    77  func Test_HashMap_Get(t *testing.T) {
    78  	hm := NewHashMap(128)
    79  	for i := 0; i < len(words); i++ {
    80  		hm.Set(words[i], []byte{0x69})
    81  	}
    82  	util.AssertExpected(t, 25, hm.Len())
    83  	var count int
    84  	for i := 0; i < hm.Len(); i++ {
    85  		ret, ok := hm.Get(words[i])
    86  		util.AssertExpected(t, true, ok)
    87  		util.AssertExpected(t, []byte{0x69}, ret)
    88  		count++
    89  	}
    90  	util.AssertExpected(t, 25, count)
    91  	hm.Close()
    92  }
    93  
    94  func Test_HashMap_Len(t *testing.T) {
    95  	hm := NewHashMap(128)
    96  	for i := 0; i < len(words); i++ {
    97  		hm.Set(words[i], []byte{0x69})
    98  	}
    99  	util.AssertExpected(t, 25, hm.Len())
   100  	hm.Close()
   101  }
   102  
   103  func Test_HashMap_PercentFull(t *testing.T) {
   104  	hm := NewHashMap(0)
   105  	for i := 0; i < len(words); i++ {
   106  		hm.Set(words[i], []byte{0x69})
   107  	}
   108  	percent := fmt.Sprintf("%.2f", hm.PercentFull())
   109  	util.AssertExpected(t, "0.78", percent)
   110  	hm.Close()
   111  }
   112  
   113  func Test_HashMap_Set(t *testing.T) {
   114  	hm := NewHashMap(128)
   115  	for i := 0; i < len(words); i++ {
   116  		hm.Set(words[i], []byte{0x69})
   117  	}
   118  	util.AssertExpected(t, 25, hm.Len())
   119  	hm.Close()
   120  }
   121  
   122  func Test_HashMap_Range(t *testing.T) {
   123  	hm := NewHashMap(128)
   124  	for i := 0; i < len(words); i++ {
   125  		hm.Set(words[i], []byte{0x69})
   126  	}
   127  	util.AssertExpected(t, 25, hm.Len())
   128  	var counted int
   129  	hm.Range(func(key string, value []byte) bool {
   130  		if key != "" && bytes.Equal(value, []byte{0x69}) {
   131  			counted++
   132  			return true
   133  		}
   134  		return false
   135  	})
   136  	util.AssertExpected(t, 25, counted)
   137  	hm.Close()
   138  }
   139  
   140  var result interface{}
   141  
   142  func BenchmarkHashMap_Set1(b *testing.B) {
   143  	hm := NewHashMap(128)
   144  
   145  	b.ResetTimer()
   146  	b.ReportAllocs()
   147  
   148  	var v []byte
   149  	for n := 0; n < b.N; n++ {
   150  		// try to get key/value "foo"
   151  		v, ok := hm.Get("foo")
   152  		if !ok {
   153  			// if it doesn't exist, then initialize it
   154  			hm.Set("foo", make([]byte, 32))
   155  		} else {
   156  			// if it does exist, then pick a random number between
   157  			// 0 and 256--this will be our bit we try and set
   158  			ri := uint(rand.Intn(128))
   159  			if ok := bits.RawBytesHasBit(&v, ri); !ok {
   160  				// we check the bit to see if it's already set, and
   161  				// then we go ahead and set it if it is not set
   162  				bits.RawBytesSetBit(&v, ri)
   163  			}
   164  			// after this, we make sure to save the bitset back to the hashmap
   165  			if n < 64 {
   166  				fmt.Printf("addr: %p, %+v\n", v, v)
   167  				//PrintBits(v)
   168  			}
   169  			hm.Set("foo", v)
   170  		}
   171  	}
   172  	result = v
   173  }
   174  
   175  func BenchmarkHashMap_Set2(b *testing.B) {
   176  	hm := NewHashMap(128)
   177  
   178  	b.ResetTimer()
   179  	b.ReportAllocs()
   180  
   181  	var v []byte
   182  	for n := 0; n < b.N; n++ {
   183  		// try to get key/value "foo"
   184  		v, ok := hm.Get("foo")
   185  		if !ok {
   186  			// if it doesn't exist, then initialize it
   187  			hm.Set("foo", make([]byte, 32))
   188  		} else {
   189  			v = append(v, []byte{byte(n >> 8)}...)
   190  			// after this, we make sure to save the bitset back to the hashmap
   191  			if n < 64 {
   192  				fmt.Printf("addr: %p, %+v\n", v, v)
   193  				//PrintBits(v)
   194  			}
   195  			hm.Set("foo", v)
   196  		}
   197  	}
   198  	result = v
   199  }
   200  
   201  func TestHashMapMillionEntriesSize(t *testing.T) {
   202  	count := 1000000
   203  	hm := NewHashMap(512)
   204  	for i := 0; i < count; i++ {
   205  		_, ok := hm.Set(strconv.Itoa(i), nil)
   206  		if ok {
   207  			t.Errorf("error: could not located value for key: %q\n", strconv.Itoa(i))
   208  		}
   209  	}
   210  	if hm.Len() != count {
   211  		t.Errorf("error: incorrect count of entries\n")
   212  	}
   213  	fmt.Printf("hashmap containing %d entries is taking %d bytes (%.2f kb, %.2f mb)\n",
   214  		count, util.Sizeof(hm), float64(util.Sizeof(hm)/1024), float64(util.Sizeof(hm)/1024/1024))
   215  	for i := 0; i < count; i++ {
   216  		_, ok := hm.Get(strconv.Itoa(i))
   217  		if !ok {
   218  			t.Errorf("error: could not located value for key: %q\n", strconv.Itoa(i))
   219  		}
   220  	}
   221  	for i := 0; i < count; i++ {
   222  		_, ok := hm.Del(strconv.Itoa(i))
   223  		if !ok {
   224  			t.Errorf("error: could not remove value for key: %q\n", strconv.Itoa(i))
   225  		}
   226  	}
   227  	if hm.Len() != count-count {
   228  		t.Errorf("error: incorrect count of entries\n")
   229  	}
   230  	hm.Close()
   231  }