Commit fd283fc7 authored by Aleksey Vasenev's avatar Aleksey Vasenev
Browse files

Improved matchmaking performance

The order of combinations has changed slightly. Now the result is sorted according to the sorting of the input data.
parent a234b521
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ require (
	github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa
	github.com/jackc/pgtype v1.14.0
	github.com/jackc/pgx/v4 v4.18.1
	github.com/mowshon/iterium v1.0.0
	github.com/prometheus/client_golang v1.17.0
	github.com/rubenv/sql-migrate v1.5.2
	github.com/stretchr/testify v1.8.4
@@ -74,6 +75,7 @@ require (
	github.com/prometheus/common v0.44.0 // indirect
	github.com/prometheus/procfs v0.11.1 // indirect
	go.uber.org/multierr v1.10.0 // indirect
	golang.org/x/exp v0.0.0-20230307190834-24139beb5833 // indirect
	golang.org/x/net v0.19.0 // indirect
	golang.org/x/sys v0.15.0 // indirect
	golang.org/x/text v0.14.0 // indirect
+4 −0
Original line number Diff line number Diff line
@@ -269,6 +269,8 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mowshon/iterium v1.0.0 h1:04pku9dTNnfVvshf+DQIV3E92T/EwmnXKtXMkmZ3+5Q=
github.com/mowshon/iterium v1.0.0/go.mod h1:Bnchn9HAYNQ/7MLUwKDyvjduSuVJQQwrNxmXJDqpXg4=
github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM=
github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -394,6 +396,8 @@ golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20230307190834-24139beb5833 h1:SChBja7BCQewoTAU7IgvucQKMIXrEpFxNMs0spT3/5s=
golang.org/x/exp v0.0.0-20230307190834-24139beb5833/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+40 −19
Original line number Diff line number Diff line
@@ -16,11 +16,11 @@ package server

import (
	"math"
	"math/bits"
	"sort"
	"time"

	"github.com/blugelabs/bluge"
	"github.com/mowshon/iterium"
	"go.uber.org/zap"
)

@@ -595,33 +595,54 @@ func (m *LocalMatchmaker) processCustom(activeIndexesCopy map[string]*Matchmaker
	return matchedEntries, expiredActiveIndexes
}

func rangeCombinations[T comparable](symbols []T, max int) <-chan []T {
	type combinations[T any] struct {
		iter  iterium.Iter[[]T]
		value []T
	}

	c := make(chan []T)
	go func() {
		defer close(c)
		if len(symbols) > 0 && max > 0 {
			allCombinations := make([]combinations[T], max-1)
			for i := 0; i < max-1; i++ {
				iter := iterium.Combinations(symbols, i+2)
				value, _ := iter.Next()
				allCombinations[i] = combinations[T]{
					iter:  iter,
					value: value,
				}
			}
			for _, symbol := range symbols {
				c <- []T{symbol}
				for i := range allCombinations {
					combinations := &allCombinations[i]
					for combinations.value != nil && combinations.value[0] == symbol {
						c <- combinations.value
						combinations.value, _ = combinations.iter.Next()
					}
				}
			}
		}
	}()
	return c
}

func combineIndexes(from []*MatchmakerIndex, min, max int) <-chan []*MatchmakerIndex {
	c := make(chan []*MatchmakerIndex)

	go func() {
		defer close(c)
		length := uint(len(from))

		// Go through all possible combinations of from 1 (only first element in subset) to 2^length (all objects in subset)
		// and return those that contain between min and max elements.
	combination:
		for combinationBits := 1; combinationBits < (1 << length); combinationBits++ {
			count := bits.OnesCount(uint(combinationBits))
			if count > max {
				continue
			}

			combination := make([]*MatchmakerIndex, 0, count)
		for combination := range rangeCombinations(from, max) {
			entryCount := 0
			for element := uint(0); element < length; element++ {
				// Check if element should be contained in combination by checking if bit 'element' is set in combinationBits.
				if (combinationBits>>element)&1 == 1 {
					entryCount = entryCount + from[element].Count
			for _, element := range combination {
				entryCount = entryCount + element.Count
				if entryCount > max {
					continue combination
				}
					combination = append(combination, from[element])
				}
			}
			if entryCount >= min {
				c <- combination
+15 −0
Original line number Diff line number Diff line
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
# vendor/
+21 −0
Original line number Diff line number Diff line
MIT License

Copyright (c) 2023 Student B.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Loading