Go: Why is my hashtable implementation so slow? - hash

So I'm trying to make a super light, deliberately memory heavy, yet very fast hashtable for very fast lookups where I don't care about memory usage and I don't care if it makes a rare mistake.
Basically it just creates a ginormous array (yes array, not slice), hashes a string using a modified FNVa hash (modified to give only a hash within the array bounds) and then saves or lookups up the value using the hash as the array index. In theory this should be the fastest possible way to store and retrieve a key=>value pair.
This is my benchmark:
package main
import (
"fmt"
"time"
)
const dicsize250 = 2097152000 // tested 115 collisions
type Dictionary250_uint16 struct {
dictionary [dicsize250]uint16
}
func (d *Dictionary250_uint16) Add(s string, v uint16) {
i := id(s,dicsize250)
d.dictionary[i]=v
return
}
func (d *Dictionary250_uint16) Delete(s string) {
i := id(s,dicsize250)
d.dictionary[i]=0
return
}
func (d *Dictionary250_uint16) Exists(s string) bool {
i := id(s,dicsize250)
if d.dictionary[i]==0 {
return false
} else {
return true
}
}
func (d *Dictionary250_uint16) Find(s string) uint16 {
i := id(s,dicsize250)
return d.dictionary[i]
}
// This is a FNVa hash algorithm, modified to limit to dicsize
func id(s string, dicsize uint64) uint64 {
var hash uint64 = 2166136261
for _, c := range s {
hash = (hash^uint64(c))*16777619
}
return hash%dicsize
}
var donothing bool
func main() {
dic := new(Dictionary250_uint16)
dic.Add(`test1`,10)
dic.Add(`test2`,20)
dic.Add(`test3`,30)
dic.Add(`test4`,40)
dic.Add(`test5`,50)
mc := make(map[string]uint16)
mc[`test1`]=10
mc[`test2`]=10
mc[`test3`]=10
mc[`test4`]=10
mc[`test5`]=10
var t1 uint
var t2 uint
var t3 uint
donothing = true
// Dic hit
t1 = uint(time.Now().UnixNano())
for i:=0; i<50000000; i++ {
if dic.Exists(`test4`) {
donothing = true
}
}
t3 = uint(time.Now().UnixNano())
t2 = t3-t1
fmt.Println("Dic (hit) took ",t2)
// Dic miss
t1 = uint(time.Now().UnixNano())
for i:=0; i<50000000; i++ {
if dic.Exists(`whate`) {
donothing = true
}
}
t3 = uint(time.Now().UnixNano())
t2 = t3-t1
fmt.Println("Dic (miss) took ",t2)
// Map hit
t1 = uint(time.Now().UnixNano())
for i:=0; i<50000000; i++ {
_,ok := mc[`test4`]
if ok {
donothing=true
}
}
t3 = uint(time.Now().UnixNano())
t2 = t3-t1
fmt.Println("Map (hit) took ",t2)
// Map miss
t1 = uint(time.Now().UnixNano())
for i:=0; i<50000000; i++ {
_,ok := mc[`whate`]
if ok {
donothing=true
}
}
t3 = uint(time.Now().UnixNano())
t2 = t3-t1
fmt.Println("Map (miss) took ",t2)
donothing = false
}
The results I get are:
Dic (hit) took 2,858,604,059
Dic (miss) took 2,457,173,526
Map (hit) took 1,574,306,146
Map (miss) took 2,525,206,080
Basically my hashtable implementation is a lot slower, especially on hits, than just using a map. I don't see how this is possible since map is a heavy implementation (in comparison) which doesn't ever have any collisions, and does a lot more calculations. Whereas my implementation is super simple and relies on having a massive array of all possible indices.
What I am doing wrong?

For one thing, you're using a very large amount of memory compared to the built-in map, but that's a trade-of you mentioned you wanted to make.
Use the standard libraries benchmark utilities. It will give you a solid base to work from, easier profiling access, and remove a lot of guesswork. I had a moment to cut&paste some of your code into a benchmark:
func BenchmarkDictHit(b *testing.B) {
donothing = true
dic := new(Dictionary250_uint16)
dic.Add(`test1`, 10)
dic.Add(`test2`, 20)
dic.Add(`test3`, 30)
dic.Add(`test4`, 40)
dic.Add(`test5`, 50)
// The initial Dict allocation is very expensive!
b.ResetTimer()
for i := 0; i < b.N; i++ {
if dic.Exists(`test4`) {
donothing = true
}
}
}
func BenchmarkDictMiss(b *testing.B) {
donothing = true
dic := new(Dictionary250_uint16)
dic.Add(`test1`, 10)
dic.Add(`test2`, 20)
dic.Add(`test3`, 30)
dic.Add(`test4`, 40)
dic.Add(`test5`, 50)
// The initial Dict allocation is very expensive!
b.ResetTimer()
for i := 0; i < b.N; i++ {
if dic.Exists(`test6`) {
donothing = true
}
}
}
func BenchmarkMapHit(b *testing.B) {
donothing = true
mc := make(map[string]uint16)
mc[`test1`] = 10
mc[`test2`] = 10
mc[`test3`] = 10
mc[`test4`] = 10
mc[`test5`] = 10
b.ResetTimer()
// Map hit
for i := 0; i < b.N; i++ {
_, ok := mc[`test4`]
if ok {
donothing = true
}
}
donothing = false
}
func BenchmarkMapMiss(b *testing.B) {
donothing = true
mc := make(map[string]uint16)
mc[`test1`] = 10
mc[`test2`] = 10
mc[`test3`] = 10
mc[`test4`] = 10
mc[`test5`] = 10
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, ok := mc[`test6`]
if ok {
donothing = true
}
}
donothing = false
}
Without the ResetTimer() call, the initial allocation of your backing slice dominates the benchmark time, and even when amortized across the runs it skew the results heavily. After the reset, the benchmark times look in order:
BenchmarkDictHit 50000000 39.6 ns/op 0 B/op 0 allocs/op
BenchmarkDictMiss 50000000 39.1 ns/op 0 B/op 0 allocs/op
BenchmarkMapHit 100000000 22.9 ns/op 0 B/op 0 allocs/op
BenchmarkMapMiss 50000000 36.8 ns/op 0 B/op 0 allocs/op
Your id function needs to iterate over a string. With strings, range doesn't iterate bytes, it looks for runes which is going to be more expensive. You will want to index the string directly, or possibly use []byte throughout (about the same cost-wise). With better string handling, these are the final timings from my test.
BenchmarkDictHit 100000000 17.8 ns/op 0 B/op 0 allocs/op
BenchmarkDictMiss 100000000 17.2 ns/op 0 B/op 0 allocs/op

Here are the results from my version of JimB's original version of your benchmark:
BenchmarkDictHit 30000000 40.8 ns/op 0 B/op 0 allocs/op
BenchmarkDictMiss 30000000 40.6 ns/op 0 B/op 0 allocs/op
BenchmarkMapHit 100000000 20.3 ns/op 0 B/op 0 allocs/op
BenchmarkMapMiss 50000000 29.5 ns/op 0 B/op 0 allocs/op
Under favorable circumstances, Go's map implementation can be quite fast. Overall, your benchmark is contrived and meaningless.

Related

How can I write the code of Bessel function with 10 term in swift?

I hope you guys can check. when I use 5 as x it should be showing me -0.17749282815107623 but it returns -0.2792375. I couldn't where I have been doing the mistake.
var evenNumbers = [Int]()
for i in 2...10 {
if i % 2 == 0 {
evenNumbers.append(i)
}
}
func power(val: Float, power: Int)->Float{
var c:Float = 1
for i in 1...power {
c *= val
}
return c
}
func bessel(x: Float)->Float{
var j0:Float = 0
var counter = 1
var lastDetermVal:Float = 1
for eNumber in evenNumbers {
print(lastDetermVal)
if counter == 1 {
lastDetermVal *= power(val: Float(eNumber), power: 2)
j0 += (power(val: x, power: eNumber))/lastDetermVal
counter = -1
}else if counter == -1{
lastDetermVal *= power(val: Float(eNumber), power: 2)
j0 -= (power(val: x, power: eNumber))/lastDetermVal
counter = 1
}
}
return 1-j0
}
bessel(x: 5)
Function 1:
Your mistake seems to be that you didn't have enough even numbers.
var evenNumbers = [Int]()
for i in 2...10 {
if i % 2 == 0 {
evenNumbers.append(i)
}
}
After the above is run, evenNumbers will be populated with [2,4,6,8,10]. But to evaluate 10 terms, you need even numbers up to 18 or 20, depending on whether you count 1 as a "term". Therefore, you should loop up to 18 or 20:
var evenNumbers = [Int]()
for i in 2...18 { // I think the 1 at the beginning should count as a "term"
if i % 2 == 0 {
evenNumbers.append(i)
}
}
Alternatively, you can create this array like this:
let evenNumbers = (1..<10).map { $0 * 2 }
This means "for each number between 1 (inclusive) and 10 (exclusive), multiply each by 2".
Now your solution will give you an answer of -0.1776034.
Here's my (rather slow) solution:
func productOfFirstNEvenNumbers(_ n: Int) -> Float {
if n == 0 {
return 1
}
let firstNEvenNumbers = (1...n).map { Float($0) * 2.0 }
// ".reduce(1.0, *)" means "multiply everything"
return firstNEvenNumbers.reduce(1.0, *)
}
func nthTerm(_ n: Int, x: Float) -> Float {
let numerator = pow(x, Float(n) * 2)
// yes, this does recalculate the product of even numbers every time...
let product = productOfFirstNEvenNumbers(n)
let denominator = product * product
return numerator / (denominator) * pow(-1, Float(n))
}
func bessel10Terms(x: Float) -> Float {
// for each number n in the range 0..<10, get the nth term, add them together
(0..<10).map { nthTerm($0, x: x) }.reduce(0, +)
}
print(bessel10Terms(x: 5))
You code is a bit unreadable, however, I have written a simple solution so try to compare your intermediate results:
var terms: [Float] = []
let x: Float = 5
for index in 0 ..< 10 {
guard index > 0 else {
terms.append(1)
continue
}
// calculate only the multiplier for the previous term
// - (minus) to change the sign
// x * x to multiply nominator
// (Float(index * 2) * Float(index * 2) to multiply denominator
let termFactor = -(x * x) / (Float(index * 2) * Float(index * 2))
terms.append(terms[index - 1] * termFactor)
}
print(terms)
// sum the terms
let result = terms.reduce(0, +)
print(result)
One of the errors I see is the fact that you are actually calculating only 5 terms, not 10 (you iterate 1 to 10, but only even numbers).

display the even numbers from 1 to 500 using a while loop and the break keyword in swift

My question is as on the title. I'm trying to print even numbers from 1 to 500 suing a while loop and break keyword. Below is my best possible answer I can think of, but this only print number 2. I've been spending hours but I wasn't able to solve it.
var number = 0
while true{
number += 2
print(number)
if number % 2 == 0 && number <= 500 {
break
}
}
You can use Stride
for evenNumber in stride(from: 0, through: 500, by: 2) {
print(evenNumber)
}
To specifically do this with while and break:
var i = 0
while true {
print(i)
i += 2
if i > 500 {
break
}
}
for i in 0...500 {
if i % 2 == 0 {
print(i)
}
}
Use below code
var numbers = 0...500
for number in numbers {
if number % 2 == 0 {
print(number)
}
}
I think it's easier to use build-in stride
let arr = Array(stride(from: 0, to: 502, by: 2))
print(arr)
//
For manually
var counter = 0
var arr = [Int]()
while counter <= 500 {
if counter % 2 == 0 {
print(counter)
arr.append(counter)
}
counter += 1
}
var number = 0
while true {
number += 2
print(number)
// ↓ Your code goes here ↓
if number > 499 {
break
}
}

Running Swift code in while loop but times out

I have following code that is supposed to do two things:
1) Fire blasters when temp is under 100 and blasters are not overheated.
2) Wait out until the temp is cooled down to zero.
I am not too sure why the codes below time out. I am a real beginner with Swift (I have an intermediate background in R.)
var shields = 5
var blastersOverheating = false
var blasterFireCount = 0
var temp = 0
while shields > 0 {
temp = temp + 1
blasterFireCount = blasterFireCount + 1
if temp == 100{
blastersOverheating = true
}
if blastersOverheating{
print("Sleeping to cool down to 0")
sleep(10)
temp = 0
blasterFireCount = 0
blastersOverheating = false
continue
}
print(temp)
}
If you run this code on a free online platform (like iswift.org/playground), your program will time out because it would run forever otherwise.
To counter this problem limit your loop so it only does, for example, 1000 cycles.
View the example online: http://swift.sandbox.bluemix.net/#/repl/59123b184ee0cd258050b2cd
var coolingDown = false
var blasterFireCount = 0
var temp = 0
for _ in 0..<1000 {
if coolingDown {
temp -= 1
print("cooling down \(temp)")
if temp == 0 { coolingDown = false }
} else {
temp += 1
blasterFireCount += 1
print("fire \(blasterFireCount)")
if temp == 100 { coolingDown = true }
}
}

Refactor for-loop statement to swift 3.0

I have following line in my code:
for (i = 0, j = count - 1; i < count; j = i++)
Can anyone help to remove the two compiler warnings, that i++ will be removed in Swift 3.0 and C-style for statement is depreciated?
You could use this:
var j = count-1
for i in 0..<count {
defer { j = i } // This will keep the cycle "logic" all together, similarly to "j = i++"
// Cycle body
}
EDIT
As #t0rst noted, be careful using defer, since it will be executed no matter how its enclosing scope is exited, so it isn't a 100% replacement.
So while the standard for ( forInit ; forTest ; forNext ) { … } will not execute forNext in case of a break statement inside the cycle, a return or an exception, the defer will.
Read here for more
Alternatively, lets go crazy to avoid having to declare j as external to the loop scope!
Snippet 1
let count = 10
for (i, j) in [count-1..<count, 0..<count-1].flatten().enumerate() {
print(i, j)
}
/* 0 9
1 0
2 1
3 2
4 3
5 4
6 5
7 6
8 7
9 8 */
Snippet 2
for (i, j) in (-1..<count-1).map({ $0 < 0 ? count-1 : $0 }).enumerate() {
print(i, j)
}
Trying to win the prize for the craziest solution in this thread
Snippet 1
extension Int {
func j(count:Int) -> Int {
return (self + count - 1) % count
}
}
for i in 0..<count {
print(i, i.j(count))
}
Snippet 2
let count = 10
let iList = 0..<count
let jList = iList.map { ($0 + count - 1) % count }
zip(iList, jList).forEach { (i, j) in
print(i, j)
}
You could use a helper function to abstract away the wrapping of j as:
func go(count: Int, block: (Int, Int) -> ()) {
if count < 1 { return }
block(0, count - 1)
for i in 1 ..< count {
block(i, i - 1)
}
}

Why can't I get a negative number using bit manipulation in Swift?

This is a LeetCode question. I wrote 4 answers in different versions of that question. When I tried to use "Bit manipulation", I got the error. Since no one in LeetCode can answer my question, and I can't find any Swift doc about this. I thought I would try to ask here.
The question is to get the majority element (>n/2) in a given array. The following code works in other languages like Java, so I think it might be a general question in Swift.
func majorityElement(nums: [Int]) -> Int {
var bit = Array(count: 32, repeatedValue: 0)
for num in nums {
for i in 0..<32 {
if (num>>(31-i) & 1) == 1 {
bit[i] += 1
}
}
}
var ret = 0
for i in 0..<32 {
bit[i] = bit[i]>nums.count/2 ? 1 : 0
ret += bit[i] * (1<<(31-i))
}
return ret
}
When the input is [-2147483648], the output is 2147483648. But in Java, it can successfully output the right negative number.
Swift doc says :
Even on 32-bit platforms, Int can store any value between -2,147,483,648 and 2,147,483,647, and is large enough for many integer ranges.
Well, it is 2,147,483,647, the input is 1 larger than that number. When I ran pow(2.0, 31.0) in playground, it shows 2147483648. I got confused. What's wrong with my code or what did I miss about Swift Int?
A Java int is a 32-bit integer. The Swift Int is 32-bit or 64-bit
depending on the platform. In particular, it is 64-bit on all OS X
platforms where Swift is available.
Your code handles only the lower 32 bits of the given integers, so that
-2147483648 = 0xffffffff80000000
becomes
2147483648 = 0x0000000080000000
So solve the problem, you can either change the function to take 32-bit integers as arguments:
func majorityElement(nums: [Int32]) -> Int32 { ... }
or make it work with arbitrary sized integers by computing the
actual size and use that instead of the constant 32:
func majorityElement(nums: [Int]) -> Int {
let numBits = sizeof(Int) * 8
var bit = Array(count: numBits, repeatedValue: 0)
for num in nums {
for i in 0..<numBits {
if (num>>(numBits-1-i) & 1) == 1 {
bit[i] += 1
}
}
}
var ret = 0
for i in 0..<numBits {
bit[i] = bit[i]>nums.count/2 ? 1 : 0
ret += bit[i] * (1<<(numBits-1-i))
}
return ret
}
A more Swifty way would be to use map() and reduce()
func majorityElement(nums: [Int]) -> Int {
let numBits = sizeof(Int) * 8
let bitCounts = (0 ..< numBits).map { i in
nums.reduce(0) { $0 + ($1 >> i) & 1 }
}
let major = (0 ..< numBits).reduce(0) {
$0 | (bitCounts[$1] > nums.count/2 ? 1 << $1 : 0)
}
return major
}