Skip to content

Commit e65d346

Browse files
author
Steve Powell
committed
Merge branch '91088912-threads'
* 91088912-threads: Make number of threads explicit
2 parents bcd90fa + 6a7690b commit e65d346

File tree

5 files changed

+86
-15
lines changed

5 files changed

+86
-15
lines changed

flags/validate_flags.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
const (
3030
executableName = "java-buildpack-memory-calculator"
3131
totalFlag = "totMemory"
32+
threadsFlag = "stackThreads"
3233
weightsFlag = "memoryWeights"
3334
sizesFlag = "memorySizes"
3435
initialsFlag = "memoryInitials"
@@ -47,6 +48,9 @@ var (
4748
totMemory = flag.String(totalFlag, "",
4849
"total memory available to allocate, expressed as an integral "+
4950
"number of bytes, kilobytes, megabytes or gigabytes")
51+
stackThreads = flag.Int(threadsFlag, 0,
52+
"number of threads to use in stack allocation calculations, e.g. '50'; "+
53+
"the default value of 0 causes an estimate to be used")
5054
memoryWeights = flag.String(weightsFlag, "",
5155
"the weights given to each memory type, e.g. 'heap:15,permgen:5,stack:1,native:2'")
5256
memorySizes = flag.String(sizesFlag, "",
@@ -58,7 +62,7 @@ var (
5862
)
5963

6064
// Validate flags passed on command line; exit(1) if invalid; exit(2) if help printed
61-
func ValidateFlags() (memSize memory.MemSize, weights map[string]float64, sizes map[string]memory.Range, initials map[string]float64) {
65+
func ValidateFlags() (memSize memory.MemSize, numThreads int, weights map[string]float64, sizes map[string]memory.Range, initials map[string]float64) {
6266

6367
flag.Parse() // exit on error
6468

@@ -69,11 +73,12 @@ func ValidateFlags() (memSize memory.MemSize, weights map[string]float64, sizes
6973

7074
// validation routines will not return on error
7175
memSize = validateTotMemory(*totMemory)
76+
numThreads = validateNumThreads(*stackThreads)
7277
weights = validateWeights(*memoryWeights)
7378
sizes = validateSizes(*memorySizes)
7479
initials = validateInitials(*memoryInitials)
7580

76-
return memSize, weights, sizes, initials
81+
return memSize, numThreads, weights, sizes, initials
7782
}
7883

7984
func validateTotMemory(mem string) memory.MemSize {
@@ -178,6 +183,14 @@ func validateInitials(initials string) map[string]float64 {
178183
return is
179184
}
180185

186+
func validateNumThreads(stackThreads int) int {
187+
if stackThreads < 0 {
188+
fmt.Fprintf(os.Stderr, "Error in -%s flag; value must be positive", threadsFlag)
189+
os.Exit(1)
190+
}
191+
return stackThreads
192+
}
193+
181194
func noArgs(args []string) bool {
182195
return len(args) == 0
183196
}

integration/main_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,21 @@ var _ = Describe("java-buildpack-memory-calculator executable", func() {
133133
Ω(string(se)).Should(ContainSubstring("Initial value must be zero or more but no more than 100% in -memoryInitials flag; clause 'heap:-1%'"), "stderr incorrect for "+badFlags[0])
134134
})
135135

136+
It("executes with error when stackThreads is negative", func() {
137+
badFlags :=
138+
[]string{
139+
"-totMemory=2G",
140+
"-memoryWeights=heap:5,stack:1,permgen:3,native:1",
141+
"-memorySizes=stack:2m..,heap:30m..400m,permgen:10m..12m",
142+
"-stackThreads=-1",
143+
}
144+
so, se, err := runOutAndErr(badFlags...)
145+
Ω(err).Should(HaveOccurred(), badFlags[0])
146+
147+
Ω(string(so)).Should(BeEmpty(), "stdout not empty for "+badFlags[0])
148+
Ω(string(se)).Should(ContainSubstring("Error in -stackThreads flag; value must be positive"), "stderr incorrect for "+badFlags[0])
149+
})
150+
136151
Context("with valid parameters", func() {
137152
var (
138153
totMemFlag, weightsFlag, sizesFlag, initialsFlag string

main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,15 @@ const (
3333
func main() {
3434

3535
// validateFlags() will exit on error
36-
memSize, weights, sizes, initials := flags.ValidateFlags()
36+
memSize, numThreads, weights, sizes, initials := flags.ValidateFlags()
3737

3838
allocator, err := memory.NewAllocator(sizes, weights)
3939
if err != nil {
4040
fmt.Fprintf(os.Stderr, "Cannot allocate memory: %s", err)
4141
os.Exit(1)
4242
}
4343

44-
if err = allocator.Balance(memSize); err != nil {
44+
if err = allocator.Balance(memSize, numThreads); err != nil {
4545
fmt.Fprintf(os.Stderr, "Cannot balance memory: %s", err)
4646
os.Exit(1)
4747
}

memory/allocator.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ import (
2424
)
2525

2626
type Allocator interface {
27-
Balance(memLimit MemSize) error // Balance allocations to buckets within memory limit
28-
Switches(switches.Funs) []string // Get selected memory switches from current allocations
29-
GetWarnings() []string // Get warnings (if balancing succeeded)
30-
GenerateInitialAllocations(map[string]float64) // Generate initial buckets
27+
Balance(memLimit MemSize, numThreads int) error // Balance allocations to buckets within memory limit
28+
Switches(switches.Funs) []string // Get selected memory switches from current allocations
29+
GetWarnings() []string // Get warnings (if balancing succeeded)
30+
GenerateInitialAllocations(map[string]float64) // Generate initial buckets
3131
}
3232

3333
type allocator struct {
@@ -63,13 +63,13 @@ var initialMinimums = map[string]MemSize{
6363

6464
// Balance memory between buckets, adjusting stack units, observing
6565
// constraints, and detecting memory wastage and default proximity.
66-
func (a *allocator) Balance(memLimit MemSize) error {
66+
func (a *allocator) Balance(memLimit MemSize, numThreads int) error {
6767
if memLimit.LessThan(MemSize(kILO)) {
6868
return fmt.Errorf("Too little memory to allocate: %s", memLimit)
6969
}
7070

7171
// adjust stack bucket, if it exists
72-
stackBucket, estNumThreads := a.normaliseStack(memLimit)
72+
stackBucket, estNumThreads := a.normaliseStack(memLimit, numThreads)
7373

7474
// distribute memory among the buckets
7575
if berr := a.balance(memLimit); berr != nil {
@@ -160,10 +160,14 @@ func totalWeight(bs map[string]Bucket) float64 {
160160
}
161161

162162
// Replace stack bucket to make it represent total memory for stacks temporarily
163-
func (a *allocator) normaliseStack(memLimit MemSize) (originalStackBucket Bucket, estNumThreads float64) {
163+
func (a *allocator) normaliseStack(memLimit MemSize, numThreads int) (originalStackBucket Bucket, estNumThreads float64) {
164164
if sb, ok := a.buckets["stack"]; ok {
165165
stackMem := weightedSize(totalWeight(a.buckets), memLimit, sb)
166-
estNumThreads = math.Max(1.0, stackMem/float64(sb.DefaultSize()))
166+
if numThreads == 0 {
167+
estNumThreads = math.Max(1.0, stackMem/float64(sb.DefaultSize()))
168+
} else {
169+
estNumThreads = float64(numThreads)
170+
}
167171
nsb, _ := NewBucket("normalised stack", sb.Weight(), sb.Range().Scale(estNumThreads))
168172

169173
a.buckets["stack"] = nsb

memory/allocator_test.go

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,18 @@ var _ = Describe("Allocator", func() {
9090

9191
Context("balancing", func() {
9292
var (
93-
memLimit = memory.MEMSIZE_ZERO
94-
aerr error
93+
memLimit = memory.MEMSIZE_ZERO
94+
aerr error
95+
numThreads = 0
9596
)
9697

98+
BeforeEach(func() {
99+
numThreads = 0
100+
})
101+
97102
JustBeforeEach(func() {
98103
a = shouldWork(memory.NewAllocator(convertToRanges(sizes), weights))
99-
aerr = a.Balance(memLimit)
104+
aerr = a.Balance(memLimit, numThreads)
100105
})
101106

102107
Context("badly", func() {
@@ -348,6 +353,40 @@ var _ = Describe("Allocator", func() {
348353
})
349354
})
350355

356+
Context("when number of threads is specified", func() {
357+
358+
BeforeEach(func() {
359+
sizes = strmap{}
360+
weights = floatmap{"heap": 5.0, "permgen": 3.0, "stack": 1.0, "native": 1.0}
361+
memLimit = memory.NewMemSize(4 * gIGA)
362+
numThreads = 100
363+
})
364+
365+
It("balances the stack according to number of threads", func() {
366+
bucks := memory.GetBuckets(a)
367+
Ω(bucks).Should(ContainElement(
368+
"Bucket{name: stack, size: 4194K, range: 0.., weight: 1}",
369+
))
370+
})
371+
})
372+
373+
Context("when number of threads is specified and stack size is fixed", func() {
374+
375+
BeforeEach(func() {
376+
sizes = strmap{"stack": "2M"}
377+
weights = floatmap{"heap": 5.0, "permgen": 3.0, "stack": 1.0, "native": 1.0}
378+
memLimit = memory.NewMemSize(4 * gIGA)
379+
numThreads = 100
380+
})
381+
382+
It("balances the stack ignoring the number of threads", func() {
383+
bucks := memory.GetBuckets(a)
384+
Ω(bucks).Should(ContainElement(
385+
"Bucket{name: stack, size: 2M, range: 2M..2M, weight: 1}",
386+
))
387+
})
388+
})
389+
351390
Context("when thread stack size is specified", func() {
352391

353392
BeforeEach(func() {

0 commit comments

Comments
 (0)