Skip to content

Commit c782d65

Browse files
committed
Merge branch 'dev' into 'master'
update 更均匀的averagePlan See merge request !7
2 parents 8ad12dd + 6f8ab67 commit c782d65

File tree

2 files changed

+215
-26
lines changed

2 files changed

+215
-26
lines changed

scheduler/complex/cpu.go

+29-16
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,10 @@ func averagePlan(cpu float64, nodes map[string]types.CPUMap, need, maxShareCore,
234234
allocplan := allocPlan(nodeinfo, need)
235235

236236
for node, ncon := range allocplan {
237-
nodename = nodeinfo[node].Node
238-
result[nodename] = nodecontainer[nodename][:ncon]
237+
if ncon > 0 {
238+
nodename = nodeinfo[node].Node
239+
result[nodename] = nodecontainer[nodename][:ncon]
240+
}
239241
}
240242

241243
return result
@@ -244,24 +246,35 @@ func averagePlan(cpu float64, nodes map[string]types.CPUMap, need, maxShareCore,
244246
func allocPlan(info ByNCon, need int) map[int]int {
245247
result := make(map[int]int)
246248
NNode := info.Len()
247-
var vol int
248249

249-
r:
250+
var nodeToUse, more int
250251
for i := 0; i < NNode; i++ {
251-
vol = info[i].NCon * (NNode - i)
252-
if vol >= need {
253-
for j := i; j < NNode; j++ {
254-
if need <= info[i].NCon {
255-
result[j] = need
256-
break r
257-
}
258-
result[j] = info[i].NCon
259-
need -= info[i].NCon
252+
nodeToUse = NNode - i
253+
ave := need / nodeToUse
254+
if ave > info[i].NCon {
255+
ave = 1
256+
}
257+
for ; ave < info[i].NCon && ave*nodeToUse < need; ave++ {
258+
}
259+
more = ave*nodeToUse - need
260+
for j := i; nodeToUse != 0; nodeToUse-- {
261+
if _, ok := result[j]; !ok {
262+
result[j] = ave
263+
} else {
264+
result[j] += ave
260265
}
261-
} else {
262-
result[i] = info[i].NCon
263-
need -= info[i].NCon
266+
if more > 0 {
267+
more--
268+
result[j]--
269+
} else if more < 0 {
270+
info[j].NCon -= ave
271+
}
272+
j++
273+
}
274+
if more == 0 {
275+
break
264276
}
277+
need = -more
265278
}
266279
return result
267280
}

scheduler/complex/potassium_test.go

+186-10
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ func TestSelectNodes(t *testing.T) {
6161

6262
r, re, err := k.SelectNodes(nodes, 1, 2)
6363
assert.NoError(t, err)
64-
assert.Equal(t, 1, len(re))
64+
assert.Equal(t, 2, len(r))
65+
assert.Equal(t, 2, len(re))
6566

6667
for nodename, cpus := range r {
6768
assert.Contains(t, []string{"node1", "node2"}, nodename)
@@ -84,7 +85,7 @@ func TestSelectNodes(t *testing.T) {
8485
},
8586
}
8687

87-
r, re, err = k.SelectNodes(nodes, 1.3, 1)
88+
r, re, err = k.SelectNodes(nodes, 1.3, 2)
8889
assert.NoError(t, err)
8990

9091
for nodename, cpus := range r {
@@ -94,7 +95,6 @@ func TestSelectNodes(t *testing.T) {
9495
cpu := cpus[0]
9596
assert.Equal(t, cpu.Total(), 13)
9697
}
97-
9898
}
9999

100100
func checkAvgPlan(res map[string][]types.CPUMap, minCon int, maxCon int, name string) error {
@@ -112,6 +112,8 @@ func checkAvgPlan(res map[string][]types.CPUMap, minCon int, maxCon int, name st
112112
}
113113
if minC != minCon || maxC != maxCon {
114114
fmt.Println(name)
115+
fmt.Println("min: ", minC)
116+
fmt.Println("max: ", maxC)
115117
for k, v := range res {
116118
fmt.Println(k, ":", len(v))
117119
}
@@ -166,7 +168,6 @@ func TestComplexNodes(t *testing.T) {
166168
}
167169

168170
k, _ = New(coreCfg)
169-
170171
// test1
171172
res1, changed1, err := k.SelectNodes(nodes, 1.7, 7)
172173
if err != nil {
@@ -175,7 +176,7 @@ func TestComplexNodes(t *testing.T) {
175176
if check := checkAvgPlan(res1, 1, 2, "res1"); check != nil {
176177
t.Fatalf("something went wrong")
177178
}
178-
assert.Equal(t, len(changed1), 4)
179+
assert.Equal(t, len(changed1), len(res1))
179180

180181
// test2
181182
// SelectNodes 里有一些副作用, 粗暴地拿一个新的来测试吧
@@ -207,11 +208,14 @@ func TestComplexNodes(t *testing.T) {
207208
"4": 10, "5": 10, "6": 10, "7": 10,
208209
},
209210
}
210-
res2, rem2, err := k.SelectNodes(nodes, 1.7, 11)
211-
if check := checkAvgPlan(res2, 1, 4, "res2"); check != nil {
211+
res2, changed2, err := k.SelectNodes(nodes, 1.7, 11)
212+
if err != nil {
213+
t.Fatalf("something went wrong")
214+
}
215+
if check := checkAvgPlan(res2, 2, 3, "res2"); check != nil {
212216
t.Fatalf("something went wrong")
213217
}
214-
assert.Equal(t, len(rem2), 4)
218+
assert.Equal(t, len(changed2), len(res2))
215219

216220
// test3
217221
nodes = map[string]types.CPUMap{
@@ -241,11 +245,15 @@ func TestComplexNodes(t *testing.T) {
241245
"4": 10, "5": 10, "6": 10, "7": 10,
242246
},
243247
}
244-
res3, rem3, err := k.SelectNodes(nodes, 1.7, 23)
248+
res3, changed3, err := k.SelectNodes(nodes, 1.7, 23)
249+
if err != nil {
250+
fmt.Println("May be we dont have plan")
251+
fmt.Println(err)
252+
}
245253
if check := checkAvgPlan(res3, 2, 6, "res3"); check != nil {
246254
t.Fatalf("something went wrong")
247255
}
248-
assert.Equal(t, len(rem3), 5)
256+
assert.Equal(t, len(changed3), len(res3))
249257

250258
// test4
251259
nodes = map[string]types.CPUMap{
@@ -280,3 +288,171 @@ func TestComplexNodes(t *testing.T) {
280288
t.Fatalf("how to alloc 29 containers when you only have 28?")
281289
}
282290
}
291+
292+
func TestEvenPlan(t *testing.T) {
293+
coreCfg := types.Config{
294+
EtcdMachines: []string{"http://127.0.0.1:2379"},
295+
EtcdLockPrefix: "/eru-core/_lock",
296+
Scheduler: types.SchedConfig{
297+
LockKey: "/coretest",
298+
LockTTL: 1,
299+
Type: "complex",
300+
},
301+
}
302+
303+
k, merr := New(coreCfg)
304+
if merr != nil {
305+
t.Fatalf("cannot create Potassim instance.", merr)
306+
}
307+
308+
// nodes -- n1: 2, n2: 2
309+
pod1 := map[string]types.CPUMap{
310+
"n1": types.CPUMap{ // 2 containers
311+
"0": 10, "1": 10, "2": 10, "3": 10,
312+
},
313+
"n2": types.CPUMap{ // 2 containers
314+
"0": 10, "1": 10, "2": 10, "3": 10,
315+
},
316+
}
317+
318+
res1, rem1, err := k.SelectNodes(pod1, 1.3, 2)
319+
if err != nil {
320+
t.Fatalf("sth wrong")
321+
}
322+
if check := checkAvgPlan(res1, 1, 1, "res1"); check != nil {
323+
t.Fatalf("something went wrong")
324+
}
325+
assert.Equal(t, len(rem1), 2)
326+
327+
// nodes -- n1: 4, n2: 5, n3:6, n4: 5
328+
pod2 := map[string]types.CPUMap{
329+
"n1": types.CPUMap{ // 4 containers
330+
"0": 10, "1": 10, "2": 10, "3": 10,
331+
"4": 10, "5": 10, "6": 10, "7": 10,
332+
},
333+
"n2": types.CPUMap{ // 5 containers
334+
"0": 10, "1": 10, "2": 10, "3": 10,
335+
"4": 10, "5": 10, "6": 10, "7": 10,
336+
"8": 10, "9": 10,
337+
},
338+
"n3": types.CPUMap{ // 6 containers
339+
"0": 10, "1": 10, "2": 10, "3": 10,
340+
"4": 10, "5": 10, "6": 10, "7": 10,
341+
"8": 10, "9": 10, "10": 10, "11": 10,
342+
},
343+
"n4": types.CPUMap{ // 5 containers
344+
"0": 10, "1": 10, "2": 10, "3": 10,
345+
"4": 10, "5": 10, "6": 10, "7": 10,
346+
"8": 10, "9": 10,
347+
},
348+
}
349+
350+
res2, rem2, err := k.SelectNodes(pod2, 1.7, 3)
351+
if check := checkAvgPlan(res2, 1, 1, "res2"); check != nil {
352+
t.Fatalf("something went wront")
353+
}
354+
assert.Equal(t, len(rem2), 3)
355+
356+
pod3 := map[string]types.CPUMap{
357+
"n1": types.CPUMap{ // 4 containers
358+
"0": 10, "1": 10, "2": 10, "3": 10,
359+
"4": 10, "5": 10, "6": 10, "7": 10,
360+
},
361+
"n2": types.CPUMap{ // 5 containers
362+
"0": 10, "1": 10, "2": 10, "3": 10,
363+
"4": 10, "5": 10, "6": 10, "7": 10,
364+
"8": 10, "9": 10,
365+
},
366+
"n3": types.CPUMap{ // 6 containers
367+
"0": 10, "1": 10, "2": 10, "3": 10,
368+
"4": 10, "5": 10, "6": 10, "7": 10,
369+
"8": 10, "9": 10, "10": 10, "11": 10,
370+
},
371+
"n4": types.CPUMap{ // 5 containers
372+
"0": 10, "1": 10, "2": 10, "3": 10,
373+
"4": 10, "5": 10, "6": 10, "7": 10,
374+
"8": 10, "9": 10,
375+
},
376+
}
377+
res3, rem3, err := k.SelectNodes(pod3, 1.7, 8)
378+
if check := checkAvgPlan(res3, 2, 2, "res3"); check != nil {
379+
t.Fatalf("something went wront")
380+
}
381+
assert.Equal(t, len(rem3), 4)
382+
383+
pod4 := map[string]types.CPUMap{
384+
"n1": types.CPUMap{ // 4 containers
385+
"0": 10, "1": 10, "2": 10, "3": 10,
386+
"4": 10, "5": 10, "6": 10, "7": 10,
387+
},
388+
"n2": types.CPUMap{ // 5 containers
389+
"0": 10, "1": 10, "2": 10, "3": 10,
390+
"4": 10, "5": 10, "6": 10, "7": 10,
391+
"8": 10, "9": 10,
392+
},
393+
"n3": types.CPUMap{ // 6 containers
394+
"0": 10, "1": 10, "2": 10, "3": 10,
395+
"4": 10, "5": 10, "6": 10, "7": 10,
396+
"8": 10, "9": 10, "10": 10, "11": 10,
397+
},
398+
"n4": types.CPUMap{ // 5 containers
399+
"0": 10, "1": 10, "2": 10, "3": 10,
400+
"4": 10, "5": 10, "6": 10, "7": 10,
401+
"8": 10, "9": 10,
402+
},
403+
}
404+
405+
res4, rem4, err := k.SelectNodes(pod4, 1.7, 10)
406+
if check := checkAvgPlan(res4, 2, 3, "res4"); check != nil {
407+
t.Fatalf("something went wrong")
408+
}
409+
assert.Equal(t, len(rem4), 4)
410+
}
411+
412+
func TestSpecialCase(t *testing.T) {
413+
pod := map[string]types.CPUMap{
414+
"n1": types.CPUMap{ // 1 containers
415+
"0": 10, "1": 10,
416+
},
417+
"n2": types.CPUMap{ // 3 containers
418+
"0": 10, "1": 10, "2": 10, "3": 10,
419+
"4": 10, "5": 10,
420+
},
421+
"n3": types.CPUMap{ // 4 containers
422+
"0": 10, "1": 10, "2": 10, "3": 10,
423+
"4": 10, "5": 10, "6": 10, "7": 10,
424+
},
425+
}
426+
427+
coreCfg := types.Config{
428+
EtcdMachines: []string{"http://127.0.0.1:2379"},
429+
EtcdLockPrefix: "/eru-core/_lock",
430+
Scheduler: types.SchedConfig{
431+
LockKey: "/coretest",
432+
LockTTL: 1,
433+
Type: "complex",
434+
},
435+
}
436+
437+
k, _ := New(coreCfg)
438+
res1, _, err := k.SelectNodes(pod, 1.7, 7)
439+
if err != nil {
440+
t.Fatalf("something went wrong")
441+
}
442+
checkAvgPlan(res1, 1, 3, "new test 2")
443+
444+
newpod := map[string]types.CPUMap{
445+
"n1": types.CPUMap{ // 3 containers
446+
"0": 10, "1": 10, "2": 10, "3": 10,
447+
"4": 10, "5": 10,
448+
},
449+
"n2": types.CPUMap{ // 4 containers
450+
"0": 10, "1": 10, "2": 10, "3": 10,
451+
"4": 10, "5": 10, "6": 10, "7": 10,
452+
},
453+
}
454+
455+
res2, changed2, _ := k.SelectNodes(newpod, 1.7, 4)
456+
assert.Equal(t, len(res2), len(changed2))
457+
checkAvgPlan(res2, 2, 2, "new test 2")
458+
}

0 commit comments

Comments
 (0)