package objectpool

import (
	"fmt"
	"math/big"
	"sync"
	"testing"
	"time"
)

func TestBigIntPool(t *testing.T) {
	var wg sync.WaitGroup

	a := time.Now().UnixNano()
	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func() {
			for i := 0; i < 1000000; i++ {
				a := new(big.Int)
				a.SetInt64(1)
				a.Add(a, a)
			}
			wg.Done()
		}()
	}
	wg.Wait()
	b := time.Now().UnixNano()
	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func() {
			for j := 0; j < 1000000; j++ {
				a := GetBigInt()
				a.SetInt64(1)
				a.Add(a, a)
				PutBigInt(a)
			}
			wg.Done()
		}()
	}
	wg.Wait()
	c := time.Now().UnixNano()
	fmt.Println("without pool ", b-a)
	fmt.Println("with    pool ", c-b)
}

func bytesFactory(n int) []byte {
	return make([]byte, n)
}
func doSomeWork(b []byte) {
	for i := 0; i < len(b); i++ {
		b[i] = byte(i)
	}
}

func TestBytesFactory(t *testing.T){
	a := 0
	fmt.Printf("%p\n",&a)
	b := bytesFactory(1024)  // b is not on stack
	fmt.Printf("%p\n", &(b[0]))
}
func TestBytesPool(t *testing.T) {
	var wg sync.WaitGroup

	a := time.Now().UnixNano()
	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func() {
			for i := 0; i < 10000; i++ {
				a := bytesFactory(1024)
				doSomeWork(a)
			}
			wg.Done()
		}()
	}
	wg.Wait()
	b := time.Now().UnixNano()
	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func() {
			for j := 0; j < 10000; j++ {
				a := GetBytes()
				doSomeWork(a)
				PutBytes(a)
			}
			wg.Done()
		}()
	}
	wg.Wait()
	c := time.Now().UnixNano()
	fmt.Println("without pool ", b-a)
	fmt.Println("with    pool ", c-b)
}


func BenchmarkBytesPool(b *testing.B) {
	for j := 0; j < 10000; j++ {
		a := GetBytes()
		doSomeWork(a)
		PutBytes(a)
	}
}
func BenchmarkBytesMake(b *testing.B) {
	for j := 0; j < 10000; j++ {
		a := bytesFactory(1024)
		doSomeWork(a)
	}
}