@@ -34,7 +34,6 @@ type allocator struct {
34
34
originalSizes map [string ]Range // unmodified after creation
35
35
buckets map [string ]Bucket // named buckets for allocation
36
36
warnings []string // warnings if allocation found issues
37
- failure error // error if allocation failed
38
37
}
39
38
40
39
func NewAllocator (sizes map [string ]Range , heuristics map [string ]float64 ) (* allocator , error ) {
@@ -57,21 +56,20 @@ const (
57
56
// Balance memory between buckets, adjusting stack units, observing
58
57
// constraints, and detecting memory wastage and default proximity.
59
58
func (a * allocator ) Balance (memLimit MemSize ) error {
60
- // Adjust stack bucket, if it exists
59
+ // adjust stack bucket, if it exists
61
60
stackBucket , estNumThreads := a .normaliseStack (memLimit )
62
61
63
- // balance buckets
64
- a .balance (memLimit )
62
+ // distribute memory among the buckets
63
+ if berr := a .balance (memLimit ); berr != nil {
64
+ return fmt .Errorf ("Memory allocation failed for configuration: %v, : %s" , getSizes (a .originalSizes ), berr )
65
+ }
65
66
66
- // Validate result and gather warnings
67
+ // validate result and gather warnings
67
68
a .validateAllocation (memLimit )
68
69
69
- // Re-adjust stack bucket, if it exists
70
+ // reset stack bucket, if it exists
70
71
a .unnormaliseStack (stackBucket , estNumThreads )
71
72
72
- if a .failure != nil {
73
- return fmt .Errorf ("Total memory exceeded by configuration: %v" , getSizes (a .originalSizes ))
74
- }
75
73
return nil
76
74
}
77
75
@@ -82,9 +80,6 @@ func (a *allocator) SetLowerBounds() {
82
80
}
83
81
84
82
func (a * allocator ) Switches (sfs switches.Funs ) []string {
85
- if a .failure != nil {
86
- return nil
87
- }
88
83
var strs = make ([]string , 0 , 10 )
89
84
for s , b := range a .buckets {
90
85
strs = append (strs , sfs .Apply (s , b .GetSize ().String ())... )
@@ -93,12 +88,10 @@ func (a *allocator) Switches(sfs switches.Funs) []string {
93
88
}
94
89
95
90
func (a * allocator ) GetWarnings () []string {
96
- if a .failure != nil {
97
- return nil
98
- }
99
91
return a .warnings
100
92
}
101
93
94
+ // getSizes returns a slice of memory type range strings
102
95
func getSizes (ss map [string ]Range ) []string {
103
96
result := []string {}
104
97
for n , s := range ss {
@@ -130,6 +123,7 @@ func totalWeight(bs map[string]Bucket) float64 {
130
123
return w
131
124
}
132
125
126
+ // Replace stack bucket to make it represent total memory for stacks temporarily
133
127
func (a * allocator ) normaliseStack (memLimit MemSize ) (originalStackBucket Bucket , estNumThreads float64 ) {
134
128
if sb , ok := a .buckets ["stack" ]; ok {
135
129
stackMem := weightedSize (totalWeight (a .buckets ), memLimit , sb )
@@ -146,6 +140,7 @@ func weightedSize(totWeight float64, memLimit MemSize, b Bucket) float64 {
146
140
return (float64 (memLimit ) * b .Weight ()) / totWeight
147
141
}
148
142
143
+ // Replace stack bucket, and set size per thread
149
144
func (a * allocator ) unnormaliseStack (sb Bucket , estNum float64 ) {
150
145
if sb == nil {
151
146
return
@@ -156,18 +151,26 @@ func (a *allocator) unnormaliseStack(sb Bucket, estNum float64) {
156
151
}
157
152
158
153
// Balance memory between buckets, observing constraints.
159
- func (a * allocator ) balance (memLimit MemSize ) {
154
+ func (a * allocator ) balance (memLimit MemSize ) error {
160
155
remaining := copyBucketMap (a .buckets )
161
156
removed := true
162
157
163
158
for removed && len (remaining ) != 0 {
164
159
var err error
165
160
memLimit , removed , err = balanceOrRemove (remaining , memLimit )
166
161
if err != nil {
167
- a .failure = err
168
- return
162
+ return err
169
163
}
170
164
}
165
+
166
+ // check for zero allocations
167
+ for n , b := range a .buckets {
168
+ if b .GetSize ().String () == "0" {
169
+ return fmt .Errorf ("Cannot allocate memory to '%n' type" , n )
170
+ }
171
+ }
172
+
173
+ return nil
171
174
}
172
175
173
176
func (a * allocator ) validateAllocation (memLimit MemSize ) {
@@ -179,16 +182,8 @@ func (a *allocator) validateAllocation(memLimit MemSize) {
179
182
180
183
func memoryWastageWarnings (bs map [string ]Bucket , memLimit MemSize ) []string {
181
184
warnings := []string {}
182
- if nativeBucket , ok := bs ["native" ]; ok && nativeBucket .Range ().Floor () == MEMSIZE_ZERO {
183
- totWeight := totalWeight (bs )
184
- floatSize := NATIVE_MEMORY_WARNING_FACTOR * weightedSize (totWeight , memLimit , nativeBucket )
185
- if MemSize (math .Floor (0.5 + floatSize )).LessThan (* nativeBucket .GetSize ()) {
186
- warnings = append (warnings ,
187
- fmt .Sprintf (
188
- "There is more than %g times more spare native memory than the default " +
189
- "so configured Java memory may be too small or available memory may be too large" ,
190
- NATIVE_MEMORY_WARNING_FACTOR ))
191
- }
185
+ if nb , ok := bs ["native" ]; ok {
186
+ warnings = append (warnings , nativeBucketWarning (nb , totalWeight (bs ), memLimit )... )
192
187
}
193
188
194
189
totalSize := MEMSIZE_ZERO
@@ -205,6 +200,19 @@ func memoryWastageWarnings(bs map[string]Bucket, memLimit MemSize) []string {
205
200
return warnings
206
201
}
207
202
203
+ func nativeBucketWarning (nativeBucket Bucket , totWeight float64 , memLimit MemSize ) []string {
204
+ if nativeBucket .Range ().Floor () == MEMSIZE_ZERO {
205
+ floatSize := NATIVE_MEMORY_WARNING_FACTOR * weightedSize (totWeight , memLimit , nativeBucket )
206
+ if MemSize (math .Floor (0.5 + floatSize )).LessThan (* nativeBucket .GetSize ()) {
207
+ return []string {fmt .Sprintf (
208
+ "There is more than %g times more spare native memory than the default " +
209
+ "so configured Java memory may be too small or available memory may be too large" ,
210
+ NATIVE_MEMORY_WARNING_FACTOR )}
211
+ }
212
+ }
213
+ return []string {}
214
+ }
215
+
208
216
func closeToDefaultWarnings (bs map [string ]Bucket , sizes map [string ]Range , memLimit MemSize ) []string {
209
217
totWeight := totalWeight (bs )
210
218
warnings := []string {}
0 commit comments