Skip to content

Instantly share code, notes, and snippets.

@spddl
Last active January 5, 2021 12:30
Show Gist options
  • Save spddl/36466ba3279e34243125051812b170df to your computer and use it in GitHub Desktop.
Save spddl/36466ba3279e34243125051812b170df to your computer and use it in GitHub Desktop.
I have X different intervals that should all run in parallel with the largest possible time interval between them.

I have X different intervals that should all run in parallel with the largest possible time interval between them.

Input:

1m, 1m

Output:

1m started now, next: 1m0s, 2m0s, 3m0s, 4m0s

1m started at 30s, next: 1m30s, 2m30s, 3m30s, 4m30s


Input:

5m, 5m, 10m

Output:

5m started now, next: 5m0s, 10m0s, 15m0s, 20m0s

5m started at 1m40s, next: 6m40s, 11m40s, 16m40s, 21m40s

10m started at 3m20s, next: 13m20s, 23m20s, 33m20s, 43m20s

import threading
import time
StartTime = time.time()
def func(msg="", interval=0.0):
t = threading.Timer(interval, func, kwargs={'msg': msg, 'interval': interval})
t.start()
print(msg+' -> time : {:.1f}s'.format(time.time()-StartTime))
intervals = [5, 5] # <- Input
intervals = sorted(intervals)
sumInterval = 0
for item in intervals:
sumInterval += item
lenIntervals = len(intervals)
for i in range(lenIntervals):
if i == 0:
threading.Timer(0, func, kwargs={'msg': "Hello from "+str(i), 'interval': intervals[i]}).start()
else:
if lenIntervals == sumInterval/intervals[i]:
delay = intervals[i]/lenIntervals*i
else:
delay = sumInterval/lenIntervals*i
while delay > intervals[i]:
delay -= intervals[i]
threading.Timer(delay, func, kwargs={'msg': "Hello from "+str(i), 'interval': intervals[i]}).start()
# Hello from 0 -> time : 0.0s
# Hello from 1 -> time : 2.5s
# Hello from 0 -> time : 5.0s
# Hello from 1 -> time : 7.5s
# Hello from 0 -> time : 10.0s
# Hello from 1 -> time : 12.5s
# Hello from 0 -> time : 15.0s
# Hello from 1 -> time : 17.5s
# Hello from 0 -> time : 20.0s
# Hello from 1 -> time : 22.5s
# Hello from 0 -> time : 25.0s
# Hello from 1 -> time : 27.5s
# Hello from 0 -> time : 30.0s
package main
import (
"fmt"
"log"
"os"
"sort"
"time"
)
func main() {
// setInverals([]string{"1m", "1m"})
// 1m0s started now, next: 1m0s, 2m0s, 3m0s, 4m0s
// 1m0s started at 30s, next: 1m30s, 2m30s, 3m30s, 4m30s
// setInverals([]string{"5m", "5m"})
// 5m0s started now, next: 5m0s, 10m0s, 15m0s, 20m0s
// 5m0s started at 2m30s, next: 7m30s, 12m30s, 17m30s, 22m30s
// setInverals([]string{"20m", "30m"})
// 20m0s started now, next: 20m0s, 40m0s, 1h0m0s, 1h20m0s
// 30m0s started at 25m0s, next: 55m0s, 1h25m0s, 1h55m0s, 2h25m0s
// setInverals([]string{"5m", "5m", "5m"})
// 5m0s started now, next: 5m0s, 10m0s, 15m0s, 20m0s
// 5m0s started at 1m40s, next: 6m40s, 11m40s, 16m40s, 21m40s
// 5m0s started at 3m20s, next: 8m20s, 13m20s, 18m20s, 23m20s
// setInverals([]string{"5m", "5m", "10m"})
// 5m0s started now, next: 5m0s, 10m0s, 15m0s, 20m0s
// 5m0s started at 1m40s, next: 6m40s, 11m40s, 16m40s, 21m40s
// 10m0s started at 3m20s, next: 13m20s, 23m20s, 33m20s, 43m20s
// setInverals([]string{"5m", "5m", "15m"})
// 5m0s started now, next: 5m0s, 10m0s, 15m0s, 20m0s
// 5m0s started at 3m20s, next: 8m20s, 13m20s, 18m20s, 23m20s
// 15m0s started at 1m40s, next: 16m40s, 31m40s, 46m40s, 1h1m40s
// setInverals([]string{"5m", "5m", "30m"})
// 5m0s started now, next: 5m0s, 10m0s, 15m0s, 20m0s
// 5m0s started at 3m20s, next: 8m20s, 13m20s, 18m20s, 23m20s
// 30m0s started at 26m40s, next: 56m40s, 1h26m40s, 1h56m40s, 2h26m40s
setInverals([]string{"1h", "30m", "15m"})
// 15m0s started now, next: 15m0s, 30m0s, 45m0s, 1h0m0s
// 30m0s started at 5m0s, next: 35m0s, 1h5m0s, 1h35m0s, 2h5m0s
// 1h0m0s started at 10m0s, next: 1h10m0s, 2h10m0s, 3h10m0s, 4h10m0s
select {} // blocking this thread
}
func setInverals(intervalsString []string) {
var intervalsInt []int
var sumInterval int
for _, v := range intervalsString {
duration, err := time.ParseDuration(v)
if err != nil {
fmt.Println(err)
}
durationNanoseconds := int(duration.Nanoseconds())
sumInterval += durationNanoseconds
intervalsInt = append(intervalsInt, durationNanoseconds)
}
sort.Ints(intervalsInt)
var lenIntervals = len(intervalsInt)
for i, value := range intervalsInt {
go func(i, value int) {
if i == 0 {
log.Printf("i: %d, starts now and next time at %dns\n", i, value)
} else {
var delay int
if lenIntervals == sumInterval/intervalsInt[i] && sumInterval%intervalsInt[i] == 0 {
delay = intervalsInt[i] / lenIntervals * i
} else {
delay = sumInterval / lenIntervals * i
}
for delay > intervalsInt[i] {
delay -= intervalsInt[i]
}
fmt.Printf("(%dns start at %dns)\n", value, delay)
time.Sleep(time.Duration(delay) * time.Nanosecond)
}
ticker := time.NewTicker(time.Duration(value) * time.Nanosecond)
for {
<-ticker.C
log.Printf("i: %d, value: %dns\n", i, value)
os.Exit(1)
}
}(i, value)
}
}
const startDate = Date.now()
function test (msg) {
console.log(msg + ' -> time :', ((Date.now() - startDate) / 1000) + 's')
}
let intervals = [5 * 1000, 5 * 1000] // 5s, 5s
intervals = intervals.sort((a, b) => a - b)
let sumInterval = 0
intervals.forEach(ival => {
sumInterval += ival
})
const lenIntervals = intervals.length
for (let i = 0; i < lenIntervals; i++) {
if (i === 0) {
test('Hello from ' + i)
setInterval(test, intervals[i], 'Hello from ' + i)
} else {
let delay
if (lenIntervals === sumInterval / intervals[i]) {
delay = intervals[i] / lenIntervals * i
} else {
delay = sumInterval / lenIntervals * i
}
while (delay > intervals[i]) {
delay -= intervals[i]
}
setTimeout(() => {
test('Hello from ' + i)
setInterval(test, intervals[i], 'Hello from ' + i)
}, delay)
}
}
/*
Hello from 0 -> time : 0s
Hello from 1 -> time : 2.505s
Hello from 0 -> time : 5.004s
Hello from 1 -> time : 7.506s
Hello from 0 -> time : 10.006s
Hello from 1 -> time : 12.506s
Hello from 0 -> time : 15.005s
Hello from 1 -> time : 17.506s
Hello from 0 -> time : 20.006s
Hello from 1 -> time : 22.506s
Hello from 0 -> time : 25.006s
Hello from 1 -> time : 27.507s
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment