diff --git a/exchanges/orderbook/orderbook.go b/exchanges/orderbook/orderbook.go index 2bdb4567..6396148f 100644 --- a/exchanges/orderbook/orderbook.go +++ b/exchanges/orderbook/orderbook.go @@ -95,11 +95,12 @@ func (s *Service) Update(b *Base) error { } default: - s.Books[b.ExchangeName][b.Pair.Base.Item][b.Pair.Quote.Item][b.AssetType].b.Bids = b.Bids - s.Books[b.ExchangeName][b.Pair.Base.Item][b.Pair.Quote.Item][b.AssetType].b.Asks = b.Asks - s.Books[b.ExchangeName][b.Pair.Base.Item][b.Pair.Quote.Item][b.AssetType].b.LastUpdated = b.LastUpdated - ids = s.Books[b.ExchangeName][b.Pair.Base.Item][b.Pair.Quote.Item][b.AssetType].Assoc - ids = append(ids, s.Books[b.ExchangeName][b.Pair.Base.Item][b.Pair.Quote.Item][b.AssetType].Main) + book := s.Books[b.ExchangeName][b.Pair.Base.Item][b.Pair.Quote.Item][b.AssetType] + book.b.Bids = b.Bids + book.b.Asks = b.Asks + book.b.LastUpdated = b.LastUpdated + ids = book.Assoc + ids = append(ids, book.Main) } s.Unlock() return s.mux.Publish(ids, b) diff --git a/exchanges/ticker/ticker.go b/exchanges/ticker/ticker.go index 8b77f602..4ff779b6 100644 --- a/exchanges/ticker/ticker.go +++ b/exchanges/ticker/ticker.go @@ -147,19 +147,20 @@ func (s *Service) Update(p *Price) error { } default: - s.Tickers[p.ExchangeName][p.Pair.Base.Item][p.Pair.Quote.Item][p.AssetType].Last = p.Last - s.Tickers[p.ExchangeName][p.Pair.Base.Item][p.Pair.Quote.Item][p.AssetType].High = p.High - s.Tickers[p.ExchangeName][p.Pair.Base.Item][p.Pair.Quote.Item][p.AssetType].Low = p.Low - s.Tickers[p.ExchangeName][p.Pair.Base.Item][p.Pair.Quote.Item][p.AssetType].Bid = p.Bid - s.Tickers[p.ExchangeName][p.Pair.Base.Item][p.Pair.Quote.Item][p.AssetType].Ask = p.Ask - s.Tickers[p.ExchangeName][p.Pair.Base.Item][p.Pair.Quote.Item][p.AssetType].Volume = p.Volume - s.Tickers[p.ExchangeName][p.Pair.Base.Item][p.Pair.Quote.Item][p.AssetType].QuoteVolume = p.QuoteVolume - s.Tickers[p.ExchangeName][p.Pair.Base.Item][p.Pair.Quote.Item][p.AssetType].PriceATH = p.PriceATH - s.Tickers[p.ExchangeName][p.Pair.Base.Item][p.Pair.Quote.Item][p.AssetType].Open = p.Open - s.Tickers[p.ExchangeName][p.Pair.Base.Item][p.Pair.Quote.Item][p.AssetType].Close = p.Close - s.Tickers[p.ExchangeName][p.Pair.Base.Item][p.Pair.Quote.Item][p.AssetType].LastUpdated = p.LastUpdated - ids = s.Tickers[p.ExchangeName][p.Pair.Base.Item][p.Pair.Quote.Item][p.AssetType].Assoc - ids = append(ids, s.Tickers[p.ExchangeName][p.Pair.Base.Item][p.Pair.Quote.Item][p.AssetType].Main) + ticker := s.Tickers[p.ExchangeName][p.Pair.Base.Item][p.Pair.Quote.Item][p.AssetType] + ticker.Last = p.Last + ticker.High = p.High + ticker.Low = p.Low + ticker.Bid = p.Bid + ticker.Ask = p.Ask + ticker.Volume = p.Volume + ticker.QuoteVolume = p.QuoteVolume + ticker.PriceATH = p.PriceATH + ticker.Open = p.Open + ticker.Close = p.Close + ticker.LastUpdated = p.LastUpdated + ids = ticker.Assoc + ids = append(ids, ticker.Main) } s.Unlock() return s.mux.Publish(ids, p) diff --git a/exchanges/websocket/wshandler/wshandler.go b/exchanges/websocket/wshandler/wshandler.go index 1bc9502d..caa29869 100644 --- a/exchanges/websocket/wshandler/wshandler.go +++ b/exchanges/websocket/wshandler/wshandler.go @@ -92,6 +92,7 @@ func (w *Websocket) Connect() error { go w.connectionMonitor() } if w.SupportsFunctionality(WebsocketSubscribeSupported) || w.SupportsFunctionality(WebsocketUnsubscribeSupported) { + w.Wg.Add(1) go w.manageSubscriptions() } @@ -498,7 +499,6 @@ func (w *Websocket) manageSubscriptions() { w.DataHandler <- fmt.Errorf("%v does not support channel subscriptions, exiting ManageSubscriptions()", w.exchangeName) return } - w.Wg.Add(1) defer func() { if w.verbose { log.Debugf(log.WebsocketMgr, "%v ManageSubscriptions exiting", w.exchangeName) diff --git a/exchanges/websocket/wshandler/wshandler_test.go b/exchanges/websocket/wshandler/wshandler_test.go index 931ec661..dc293cf1 100644 --- a/exchanges/websocket/wshandler/wshandler_test.go +++ b/exchanges/websocket/wshandler/wshandler_test.go @@ -352,12 +352,13 @@ func TestManageSubscriptionsStartStop(t *testing.T) { ShutdownC: make(chan struct{}), Functionality: WebsocketSubscribeSupported | WebsocketUnsubscribeSupported, } + w.Wg.Add(1) go w.manageSubscriptions() close(w.ShutdownC) w.Wg.Wait() } -// TestManageSubscriptionsStartStop logic test +// TestManageSubscriptions logic test func TestManageSubscriptions(t *testing.T) { w := Websocket{ ShutdownC: make(chan struct{}), diff --git a/exchanges/websocket/wsorderbook/wsorderbook.go b/exchanges/websocket/wsorderbook/wsorderbook.go index 2422b921..e24a93ea 100644 --- a/exchanges/websocket/wsorderbook/wsorderbook.go +++ b/exchanges/websocket/wsorderbook/wsorderbook.go @@ -4,7 +4,6 @@ import ( "errors" "fmt" "sort" - "sync" "github.com/thrasher-corp/gocryptotrader/currency" "github.com/thrasher-corp/gocryptotrader/exchanges/asset" @@ -33,21 +32,22 @@ func (w *WebsocketOrderbookLocal) Update(orderbookUpdate *WebsocketOrderbookUpda } w.m.Lock() defer w.m.Unlock() - if _, ok := w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType]; !ok { + obLookup, ok := w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType] + if !ok { return fmt.Errorf("ob.Base could not be found for Exchange %s CurrencyPair: %s AssetType: %s", w.exchangeName, orderbookUpdate.CurrencyPair.String(), orderbookUpdate.AssetType) } if w.bufferEnabled { - overBufferLimit := w.processBufferUpdate(orderbookUpdate) + overBufferLimit := w.processBufferUpdate(obLookup, orderbookUpdate) if !overBufferLimit { return nil } } else { - w.processObUpdate(orderbookUpdate) + w.processObUpdate(obLookup, orderbookUpdate) } - err := w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType].Process() + err := obLookup.Process() if err != nil { return err } @@ -58,144 +58,142 @@ func (w *WebsocketOrderbookLocal) Update(orderbookUpdate *WebsocketOrderbookUpda return nil } -func (w *WebsocketOrderbookLocal) processBufferUpdate(orderbookUpdate *WebsocketOrderbookUpdate) bool { +func (w *WebsocketOrderbookLocal) processBufferUpdate(o *orderbook.Base, orderbookUpdate *WebsocketOrderbookUpdate) bool { if w.buffer == nil { - w.buffer = make(map[currency.Pair]map[asset.Item][]WebsocketOrderbookUpdate) + w.buffer = make(map[currency.Pair]map[asset.Item][]*WebsocketOrderbookUpdate) } if w.buffer[orderbookUpdate.CurrencyPair] == nil { - w.buffer[orderbookUpdate.CurrencyPair] = make(map[asset.Item][]WebsocketOrderbookUpdate) + w.buffer[orderbookUpdate.CurrencyPair] = make(map[asset.Item][]*WebsocketOrderbookUpdate) } - if len(w.buffer[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType]) <= w.obBufferLimit { - w.buffer[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType] = append(w.buffer[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType], *orderbookUpdate) - if len(w.buffer[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType]) < w.obBufferLimit { + bufferLookup := w.buffer[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType] + if len(bufferLookup) <= w.obBufferLimit { + bufferLookup = append(bufferLookup, orderbookUpdate) + if len(bufferLookup) < w.obBufferLimit { + w.buffer[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType] = bufferLookup return false } } if w.sortBuffer { // sort by last updated to ensure each update is in order if w.sortBufferByUpdateIDs { - sort.Slice(w.buffer[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType], func(i, j int) bool { - return w.buffer[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType][i].UpdateID < w.buffer[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType][j].UpdateID + sort.Slice(bufferLookup, func(i, j int) bool { + return bufferLookup[i].UpdateID < bufferLookup[j].UpdateID }) } else { - sort.Slice(w.buffer[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType], func(i, j int) bool { - return w.buffer[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType][i].UpdateTime.Before(w.buffer[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType][j].UpdateTime) + sort.Slice(bufferLookup, func(i, j int) bool { + return bufferLookup[i].UpdateTime.Before(bufferLookup[j].UpdateTime) }) } } - for i := 0; i < len(w.buffer[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType]); i++ { - w.processObUpdate(&w.buffer[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType][i]) + for i := 0; i < len(bufferLookup); i++ { + w.processObUpdate(o, bufferLookup[i]) } + w.buffer[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType] = bufferLookup return true } -func (w *WebsocketOrderbookLocal) processObUpdate(orderbookUpdate *WebsocketOrderbookUpdate) { +func (w *WebsocketOrderbookLocal) processObUpdate(o *orderbook.Base, orderbookUpdate *WebsocketOrderbookUpdate) { if w.updateEntriesByID { - w.updateByIDAndAction(orderbookUpdate) + w.updateByIDAndAction(o, orderbookUpdate) } else { - var wg sync.WaitGroup - wg.Add(2) - go w.updateAsksByPrice(orderbookUpdate, &wg) - go w.updateBidsByPrice(orderbookUpdate, &wg) - wg.Wait() + w.updateAsksByPrice(o, orderbookUpdate) + w.updateBidsByPrice(o, orderbookUpdate) } } -func (w *WebsocketOrderbookLocal) updateAsksByPrice(base *WebsocketOrderbookUpdate, wg *sync.WaitGroup) { +func (w *WebsocketOrderbookLocal) updateAsksByPrice(o *orderbook.Base, base *WebsocketOrderbookUpdate) { for j := 0; j < len(base.Asks); j++ { found := false - for k := 0; k < len(w.ob[base.CurrencyPair][base.AssetType].Asks); k++ { - if w.ob[base.CurrencyPair][base.AssetType].Asks[k].Price == base.Asks[j].Price { + for k := 0; k < len(o.Asks); k++ { + if o.Asks[k].Price == base.Asks[j].Price { found = true if base.Asks[j].Amount == 0 { - w.ob[base.CurrencyPair][base.AssetType].Asks = append(w.ob[base.CurrencyPair][base.AssetType].Asks[:k], - w.ob[base.CurrencyPair][base.AssetType].Asks[k+1:]...) + o.Asks = append(o.Asks[:k], + o.Asks[k+1:]...) break } - w.ob[base.CurrencyPair][base.AssetType].Asks[k].Amount = base.Asks[j].Amount + o.Asks[k].Amount = base.Asks[j].Amount break } } if !found { - w.ob[base.CurrencyPair][base.AssetType].Asks = append(w.ob[base.CurrencyPair][base.AssetType].Asks, base.Asks[j]) + o.Asks = append(o.Asks, base.Asks[j]) } } - sort.Slice(w.ob[base.CurrencyPair][base.AssetType].Asks, func(i, j int) bool { - return w.ob[base.CurrencyPair][base.AssetType].Asks[i].Price < w.ob[base.CurrencyPair][base.AssetType].Asks[j].Price + sort.Slice(o.Asks, func(i, j int) bool { + return o.Asks[i].Price < o.Asks[j].Price }) - wg.Done() } -func (w *WebsocketOrderbookLocal) updateBidsByPrice(base *WebsocketOrderbookUpdate, wg *sync.WaitGroup) { +func (w *WebsocketOrderbookLocal) updateBidsByPrice(o *orderbook.Base, base *WebsocketOrderbookUpdate) { for j := 0; j < len(base.Bids); j++ { found := false - for k := 0; k < len(w.ob[base.CurrencyPair][base.AssetType].Bids); k++ { - if w.ob[base.CurrencyPair][base.AssetType].Bids[k].Price == base.Bids[j].Price { + for k := 0; k < len(o.Bids); k++ { + if o.Bids[k].Price == base.Bids[j].Price { found = true if base.Bids[j].Amount == 0 { - w.ob[base.CurrencyPair][base.AssetType].Bids = append(w.ob[base.CurrencyPair][base.AssetType].Bids[:k], - w.ob[base.CurrencyPair][base.AssetType].Bids[k+1:]...) + o.Bids = append(o.Bids[:k], + o.Bids[k+1:]...) break } - w.ob[base.CurrencyPair][base.AssetType].Bids[k].Amount = base.Bids[j].Amount + o.Bids[k].Amount = base.Bids[j].Amount break } } if !found { - w.ob[base.CurrencyPair][base.AssetType].Bids = append(w.ob[base.CurrencyPair][base.AssetType].Bids, base.Bids[j]) + o.Bids = append(o.Bids, base.Bids[j]) } } - sort.Slice(w.ob[base.CurrencyPair][base.AssetType].Bids, func(i, j int) bool { - return w.ob[base.CurrencyPair][base.AssetType].Bids[i].Price > w.ob[base.CurrencyPair][base.AssetType].Bids[j].Price + sort.Slice(o.Bids, func(i, j int) bool { + return o.Bids[i].Price > o.Bids[j].Price }) - wg.Done() } // updateByIDAndAction will receive an action to execute against the orderbook // it will then match by IDs instead of price to perform the action -func (w *WebsocketOrderbookLocal) updateByIDAndAction(orderbookUpdate *WebsocketOrderbookUpdate) { +func (w *WebsocketOrderbookLocal) updateByIDAndAction(o *orderbook.Base, orderbookUpdate *WebsocketOrderbookUpdate) { switch orderbookUpdate.Action { case "update": for _, target := range orderbookUpdate.Bids { - for i := range w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType].Bids { - if w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType].Bids[i].ID == target.ID { - w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType].Bids[i].Amount = target.Amount + for i := range o.Bids { + if o.Bids[i].ID == target.ID { + o.Bids[i].Amount = target.Amount break } } } for _, target := range orderbookUpdate.Asks { - for i := range w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType].Asks { - if w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType].Asks[i].ID == target.ID { - w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType].Asks[i].Amount = target.Amount + for i := range o.Asks { + if o.Asks[i].ID == target.ID { + o.Asks[i].Amount = target.Amount break } } } case "delete": for _, target := range orderbookUpdate.Bids { - for i := 0; i < len(w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType].Bids); i++ { - if w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType].Bids[i].ID == target.ID { - w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType].Bids = append(w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType].Bids[:i], - w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType].Bids[i+1:]...) + for i := 0; i < len(o.Bids); i++ { + if o.Bids[i].ID == target.ID { + o.Bids = append(o.Bids[:i], + o.Bids[i+1:]...) i-- break } } } for _, target := range orderbookUpdate.Asks { - for i := 0; i < len(w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType].Asks); i++ { - if w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType].Asks[i].ID == target.ID { - w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType].Asks = append(w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType].Asks[:i], - w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType].Asks[i+1:]...) + for i := 0; i < len(o.Asks); i++ { + if o.Asks[i].ID == target.ID { + o.Asks = append(o.Asks[:i], + o.Asks[i+1:]...) i-- break } } } case "insert": - w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType].Bids = append(w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType].Bids, orderbookUpdate.Bids...) - w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType].Asks = append(w.ob[orderbookUpdate.CurrencyPair][orderbookUpdate.AssetType].Asks, orderbookUpdate.Asks...) + o.Bids = append(o.Bids, orderbookUpdate.Bids...) + o.Asks = append(o.Asks, orderbookUpdate.Asks...) } } @@ -227,10 +225,11 @@ func (w *WebsocketOrderbookLocal) LoadSnapshot(newOrderbook *orderbook.Base) err if w.ob[newOrderbook.Pair] == nil { w.ob[newOrderbook.Pair] = make(map[asset.Item]*orderbook.Base) } - if w.ob[newOrderbook.Pair][newOrderbook.AssetType] != nil && - (len(w.ob[newOrderbook.Pair][newOrderbook.AssetType].Asks) > 0 || - len(w.ob[newOrderbook.Pair][newOrderbook.AssetType].Bids) > 0) { - w.ob[newOrderbook.Pair][newOrderbook.AssetType] = newOrderbook + fullObLookup := w.ob[newOrderbook.Pair][newOrderbook.AssetType] + if fullObLookup != nil && + (len(fullObLookup.Asks) > 0 || + len(fullObLookup.Bids) > 0) { + fullObLookup = newOrderbook return newOrderbook.Process() } w.ob[newOrderbook.Pair][newOrderbook.AssetType] = newOrderbook diff --git a/exchanges/websocket/wsorderbook/wsorderbook_test.go b/exchanges/websocket/wsorderbook/wsorderbook_test.go index 8c0c09db..a60fd067 100644 --- a/exchanges/websocket/wsorderbook/wsorderbook_test.go +++ b/exchanges/websocket/wsorderbook/wsorderbook_test.go @@ -43,6 +43,61 @@ func createSnapshot() (obl *WebsocketOrderbookLocal, curr currency.Pair, asks, b return } +func bidAskGenerator() []orderbook.Item { + var response []orderbook.Item + randIterator := 100 + for i := 0; i < randIterator; i++ { + price := float64(rand.Intn(1000)) + if price == 0 { + price = 1 + } + response = append(response, orderbook.Item{ + Amount: float64(rand.Intn(1)), + Price: price, + ID: int64(i), + }) + } + return response +} + +func BenchmarkUpdateBidsByPrice(b *testing.B) { + ob, curr, _, _, err := createSnapshot() + if err != nil { + b.Error(err) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + bidAsks := bidAskGenerator() + update := &WebsocketOrderbookUpdate{ + Bids: bidAsks, + Asks: bidAsks, + CurrencyPair: curr, + UpdateTime: time.Now(), + AssetType: asset.Spot, + } + ob.updateBidsByPrice(ob.ob[curr][asset.Spot], update) + } +} + +func BenchmarkUpdateAsksByPrice(b *testing.B) { + ob, curr, _, _, err := createSnapshot() + if err != nil { + b.Error(err) + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + bidAsks := bidAskGenerator() + update := &WebsocketOrderbookUpdate{ + Bids: bidAsks, + Asks: bidAsks, + CurrencyPair: curr, + UpdateTime: time.Now(), + AssetType: asset.Spot, + } + ob.updateAsksByPrice(ob.ob[curr][asset.Spot], update) + } +} + // BenchmarkBufferPerformance demonstrates buffer more performant than multi // process calls func BenchmarkBufferPerformance(b *testing.B) { @@ -50,6 +105,42 @@ func BenchmarkBufferPerformance(b *testing.B) { if err != nil { b.Fatal(err) } + obl.bufferEnabled = true + cp := currency.NewPairFromString("BTCUSD") + // This is to ensure we do not send in zero orderbook info to our main book + // in orderbook.go, orderbooks should not be zero even after an update. + dummyItem := orderbook.Item{ + Amount: 1333337, + Price: 1337.1337, + ID: 1337, + } + obl.ob[cp][asset.Spot].Bids = append(obl.ob[cp][asset.Spot].Bids, dummyItem) + update := &WebsocketOrderbookUpdate{ + Bids: bids, + Asks: asks, + CurrencyPair: curr, + UpdateTime: time.Now(), + AssetType: asset.Spot, + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + randomIndex := rand.Intn(4) + update.Asks = itemArray[randomIndex] + update.Bids = itemArray[randomIndex] + err = obl.Update(update) + if err != nil { + b.Fatal(err) + } + } +} + +// BenchmarkBufferSortingPerformance benchmark +func BenchmarkBufferSortingPerformance(b *testing.B) { + obl, curr, asks, bids, err := createSnapshot() + if err != nil { + b.Fatal(err) + } + obl.bufferEnabled = true obl.sortBuffer = true cp := currency.NewPairFromString("BTCUSD") // This is to ensure we do not send in zero orderbook info to our main book @@ -67,8 +158,9 @@ func BenchmarkBufferPerformance(b *testing.B) { UpdateTime: time.Now(), AssetType: asset.Spot, } + b.ResetTimer() for i := 0; i < b.N; i++ { - randomIndex := rand.Intn(5) + randomIndex := rand.Intn(4) update.Asks = itemArray[randomIndex] update.Bids = itemArray[randomIndex] err = obl.Update(update) @@ -79,14 +171,23 @@ func BenchmarkBufferPerformance(b *testing.B) { } // BenchmarkBufferSortingPerformance benchmark -func BenchmarkBufferSortingPerformance(b *testing.B) { +func BenchmarkBufferSortingByIDPerformance(b *testing.B) { obl, curr, asks, bids, err := createSnapshot() if err != nil { b.Fatal(err) } - obl.sortBuffer = true obl.bufferEnabled = true - obl.obBufferLimit = 5 + obl.sortBuffer = true + obl.sortBufferByUpdateIDs = true + cp := currency.NewPairFromString("BTCUSD") + // This is to ensure we do not send in zero orderbook info to our main book + // in orderbook.go, orderbooks should not be zero even after an update. + dummyItem := orderbook.Item{ + Amount: 1333337, + Price: 1337.1337, + ID: 1337, + } + obl.ob[cp][asset.Spot].Bids = append(obl.ob[cp][asset.Spot].Bids, dummyItem) update := &WebsocketOrderbookUpdate{ Bids: bids, Asks: asks, @@ -94,8 +195,9 @@ func BenchmarkBufferSortingPerformance(b *testing.B) { UpdateTime: time.Now(), AssetType: asset.Spot, } + b.ResetTimer() for i := 0; i < b.N; i++ { - randomIndex := rand.Intn(5) + randomIndex := rand.Intn(4) update.Asks = itemArray[randomIndex] update.Bids = itemArray[randomIndex] err = obl.Update(update) @@ -128,8 +230,9 @@ func BenchmarkNoBufferPerformance(b *testing.B) { UpdateTime: time.Now(), AssetType: asset.Spot, } + b.ResetTimer() for i := 0; i < b.N; i++ { - randomIndex := rand.Intn(5) + randomIndex := rand.Intn(4) update.Asks = itemArray[randomIndex] update.Bids = itemArray[randomIndex] err = obl.Update(update) diff --git a/exchanges/websocket/wsorderbook/wsorderbook_types.go b/exchanges/websocket/wsorderbook/wsorderbook_types.go index 8fa4f35c..6766c797 100644 --- a/exchanges/websocket/wsorderbook/wsorderbook_types.go +++ b/exchanges/websocket/wsorderbook/wsorderbook_types.go @@ -13,7 +13,7 @@ import ( // appending and deleting changes and updates the main store in wsorderbook.go type WebsocketOrderbookLocal struct { ob map[currency.Pair]map[asset.Item]*orderbook.Base - buffer map[currency.Pair]map[asset.Item][]WebsocketOrderbookUpdate + buffer map[currency.Pair]map[asset.Item][]*WebsocketOrderbookUpdate obBufferLimit int bufferEnabled bool sortBuffer bool