{"id":23044442,"url":"https://github.com/k8gb-io/go-weight-shuffling","last_synced_at":"2025-10-24T23:04:20.547Z","repository":{"id":50967779,"uuid":"499564679","full_name":"k8gb-io/go-weight-shuffling","owner":"k8gb-io","description":"Simple Weight Shuffling library in GO","archived":false,"fork":false,"pushed_at":"2022-09-08T14:57:21.000Z","size":49,"stargazers_count":5,"open_issues_count":0,"forks_count":1,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-05-18T20:01:54.127Z","etag":null,"topics":["go","golang","round-robin","round-robin-scheduler","shuffling","weight-round-robin","weight-shuffling"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/k8gb-io.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-06-03T15:40:26.000Z","updated_at":"2024-04-28T05:56:40.000Z","dependencies_parsed_at":"2022-09-02T07:02:12.822Z","dependency_job_id":null,"html_url":"https://github.com/k8gb-io/go-weight-shuffling","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/k8gb-io/go-weight-shuffling","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k8gb-io%2Fgo-weight-shuffling","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k8gb-io%2Fgo-weight-shuffling/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k8gb-io%2Fgo-weight-shuffling/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k8gb-io%2Fgo-weight-shuffling/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/k8gb-io","download_url":"https://codeload.github.com/k8gb-io/go-weight-shuffling/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k8gb-io%2Fgo-weight-shuffling/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270499956,"owners_count":24595149,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-14T02:00:10.309Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","golang","round-robin","round-robin-scheduler","shuffling","weight-round-robin","weight-shuffling"],"created_at":"2024-12-15T21:13:35.762Z","updated_at":"2025-10-24T23:04:20.529Z","avatar_url":"https://github.com/k8gb-io.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# go-weight-shuffling\n[![License](http://img.shields.io/:license-apache-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0.html)\n[![Go Reference](https://pkg.go.dev/badge/github.com/k8gb-io/go-weight-shuffling.svg)](https://pkg.go.dev/github.com/k8gb-io/go-weight-shuffling?branch=main)\n![Build Status](https://github.com/k8gb-io/go-weight-shuffling/actions/workflows/test.yaml/badge.svg?branch=main)\n![Linter](https://github.com/k8gb-io/go-weight-shuffling/actions/workflows/lint.yaml/badge.svg?branch=main)\n[![Go Report Card](https://goreportcard.com/badge/github.com/k8gb-io/go-weight-shuffling)](https://goreportcard.com/report/github.com/k8gb-io/go-weight-shuffling?branch=main)\n\n\nThis library provides a Weight Shuffling support function which achieves both performance and simplicity. The functionality\nis suitable for weight round-robin in a distributed environments.\n\nFor detailed information about the concept, you should take a look at the following resources:\n- [CDF x PDF](https://www.statology.org/cdf-vs-pdf/)\n- [What is Weight Round Robin?](https://www.educative.io/edpresso/what-is-the-weighted-round-robin-load-balancing-technique)\n\n## Table of Content\n- [Install](#install)\n- [Introduction](#introduction)\n- [Pick() Usage](#pick-usage)\n- [PickVector() Usage](#pickvector-usage)\n- [Examples](#examples)\n\n## Install\nWith a correctly configured Go environment:\n```\ngo get github.com/k8gb-io/go-weight-shuffling\n```\n\n## Introduction\nUse this package in case you need to select elements or balance the load with certain probability.Basically the only \nthing you need to understand is PDF distribution. The PDF - or weights - determines with what probability the individual \nelements in the array will be selected.\n\nFor example, I have a slice with these IP addresses:\n```go\nips := []string{\"10.1.0.1\",\"10.2.0.1\",\"10.3.0.1\",\"10.4.0.1\"}\n```\nI would like to pick the indexes of these addresses with a certain probability, therefore\nI'm defining `weights := {3,4,2,1}` to determine such probabilities. The chance of selecting the first index \n(address `10.1.0.1`) is 30%, the chance of selecting the second index (`10.2.0.1`) is 40%, etc. \nSo the final probability is: `{0:30%, 1:40%, 2:20%, 3:10%}`\n\nFor some reason I decide I don't want to select `10.3.0.1` anymore. Therefore, I set the weight in the \npdf to 0 for the element I no longer want to use `weights := {3,4,0,1}`. The probabilities are automatically \nrecalculated and the returned indexes will be returned with probabilities `{0:38%,1:50%, 2:0%, 3:12%}`\nvalue `2` (index of `10.3.0.1`) is dropped.\n\nThe usage is simple, the package defines two methods: \n- `Pick()` returning one index\n- `PickVector()` returning all indexes in such order that the ones with the highest weight appears at \nthe beginning of the returned slice, while the ones with the lowest weight appear at the end.\n\n![](https://user-images.githubusercontent.com/7195836/189152064-6e105001-75c1-4381-9089-5d1be556c324.png)\n\n\n## Pick() Usage\nPick returns single index with probability given by weights.\n```go\nweights := []uint32{30, 40, 20, 10}\n// handle error in real code\nw := gows.NewWS(weights)\n// the index is selected from the probability determined by the weight \nindex,_ := w.Pick()\n```\nIf the sum of the weights is equal to zero the function generates an error (there is no index to choose from if everything is 0)\n\n## PickVector(Settings) Usage\nPickVector returns slice shuffled by weights distribution. returning all indexes in such order that the ones with the \nhighest weight appears at the beginning of the returned slice, while the ones with the lowest weight appear at the end.\n```go\nweights := []int{30, 40, 20, 10}\n// handle error in real code\nws := gows.NewWS(weights)\n// the result will be slices of the index, which will be \"probably\" sorted by probability\nindexes := wrr.PickVector(gows.IncludeZeroWeights)\n```\n\nFor example: `weights={30,40,20,10}` will produce such results:\n```\n[1,2,3,0]\n[0,1,3,2]\n[0,1,2,3]\n[1,0,2,3]\n[1,3,0,2]\n[0,3,2,1]\n[1,0,2,3]\n[2,1,0,3]\n[3,0,1,2]\n...\n```\nThe function returns an index slice such that index 0 will be represented in the zero position in about 30% of cases,\nindex 1 will be in the first position in about 40% of cases, etc. Similarly, there are heavier weights in the second position. \nThe last position belongs mostly to the low weights. \n\n### Settings argument\nThe Settings argument defines how the PickVector function will return indexes. Imagine you have \na weights for three different parts and you set one of them to 0 (just turn it off, because the \nprobability of this index will be 0). The solution is not universal, each use-case requires \ndifferent behavior. Currently we define two versions of the behavior.\n\n- `IncludeZeroWeights` keeps indexes for zero weight; e.g: for `weights=[0,50,50,0,0,0]` returns only `[1,2,0,3,4,5]` or `[2,1,0,3,4,5]`\n- `DropZeroWeights` filter indexes for zero weight; e.g: for `weights=[0,50,50,0,0,0]` returns only `[1,2]` or `[2,1]`\n\n## Examples\nThis library is ideal for Weight RoundRobin. Imagine you need to balance these addresses (can be applied to whole groups\nof addresses):\n```shell\n# dig wrr.cloud.example.com +short\n10.1.0.1\n10.0.0.1\n10.2.0.1\n10.3.0.1\n```\n\nWe want to shuffle the addresses for weights `[30 40 20 10]`: The item with the highest probability (index 1 = 40%) will\noccur more often at the 0 position.\n\n```txt\n IP:      [10.0.0.1, 10.1.0.1, 10.2.0.1, 10.3.0.1]\n WEIGHTS: [30 40 20 10]\n    -----------------\n 0. [289 401 200 110] \n 1. [298 315 258 129] \n 2. [291 216 307 186] \n 3. [122 68 235 575] \n```\n\nThe example matrix was created by 1000x hitting the list of IP addresses with help of WRR.\nIf we map the indexes to a slice with IP addresses (or groups of IP addresses) the IP at\nzero index (`10.0.0.1`) is used 289x on the first position returned by DNS server (e.g: `[10.0.0.1, 10.1.0.1, 10.2.0.1, 10.3.0.1]`).\nHowever, 298x used on the second position (e.g: `[10.1.0.1, 10.0.0.1, 10.3.0.1, 10.2.0.1]`).\n\nThe address (`10.3.0.1`) has only 10% probability of to be chosen. It occurs only 110x (cca 10%) on the zero position\nwhile 575x on the last position.\n\nThe index was calculated 1000 times. When you sum individual columns or rows, the result is always 1000x so everything\nis  mathematically OK. Let me add a few more examples.\n\n#### 100%\nLet's say we set `weight={0,0,1,0}`. The `PickVecor` function will always generate this indexes: `[2 1 0 3]`, \nso for our IP addresses they will always be sorted like this: `[10.2.0.1,10.1.0.1,10.0.0.1,10.3.0.1]`.  \nThis is the result matrix\n```\n    [10.0.0.1],[10.1.0.1],[10.2.0.1],[10.3.0.1]\n    [0 0 100 0]\n    -----------------\n 0. [0 0 100 0] \n 1. [0 100 0 0] \n 2. [100 0 0 0] \n 3. [0 0 0 100] \n```\n\n#### 50% / 50%\nthe last case is a bit redundant, although very explanatory. Let's say we have `weight={1,1}`.\nThe generated sample will look like following:\n```\n[0 1]\n[1 0]\n[0 1]\n[1 0]\n[0 1]\n[0 1]\n[1 0]\n[1 0]\n...\n\n    [10.0.0.1],[10.1.0.1]\n    [50 50]\n    -----------------\n 0. [511 489] \n 1. [489 511] \n```\nThe address `10.0.0.1` occurred 511 times in `1000` hits at index 0 , while 489 times at index 1.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fk8gb-io%2Fgo-weight-shuffling","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fk8gb-io%2Fgo-weight-shuffling","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fk8gb-io%2Fgo-weight-shuffling/lists"}