@@ -34,7 +34,6 @@ type allocator struct {
3434 originalSizes map [string ]Range // unmodified after creation
3535 buckets map [string ]Bucket // named buckets for allocation
3636 warnings []string // warnings if allocation found issues
37- failure error // error if allocation failed
3837}
3938
4039func NewAllocator (sizes map [string ]Range , heuristics map [string ]float64 ) (* allocator , error ) {
@@ -57,21 +56,20 @@ const (
5756// Balance memory between buckets, adjusting stack units, observing
5857// constraints, and detecting memory wastage and default proximity.
5958func (a * allocator ) Balance (memLimit MemSize ) error {
60- // Adjust stack bucket, if it exists
59+ // adjust stack bucket, if it exists
6160 stackBucket , estNumThreads := a .normaliseStack (memLimit )
6261
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+ }
6566
66- // Validate result and gather warnings
67+ // validate result and gather warnings
6768 a .validateAllocation (memLimit )
6869
69- // Re-adjust stack bucket, if it exists
70+ // reset stack bucket, if it exists
7071 a .unnormaliseStack (stackBucket , estNumThreads )
7172
72- if a .failure != nil {
73- return fmt .Errorf ("Total memory exceeded by configuration: %v" , getSizes (a .originalSizes ))
74- }
7573 return nil
7674}
7775
@@ -82,9 +80,6 @@ func (a *allocator) SetLowerBounds() {
8280}
8381
8482func (a * allocator ) Switches (sfs switches.Funs ) []string {
85- if a .failure != nil {
86- return nil
87- }
8883 var strs = make ([]string , 0 , 10 )
8984 for s , b := range a .buckets {
9085 strs = append (strs , sfs .Apply (s , b .GetSize ().String ())... )
@@ -93,12 +88,10 @@ func (a *allocator) Switches(sfs switches.Funs) []string {
9388}
9489
9590func (a * allocator ) GetWarnings () []string {
96- if a .failure != nil {
97- return nil
98- }
9991 return a .warnings
10092}
10193
94+ // getSizes returns a slice of memory type range strings
10295func getSizes (ss map [string ]Range ) []string {
10396 result := []string {}
10497 for n , s := range ss {
@@ -130,6 +123,7 @@ func totalWeight(bs map[string]Bucket) float64 {
130123 return w
131124}
132125
126+ // Replace stack bucket to make it represent total memory for stacks temporarily
133127func (a * allocator ) normaliseStack (memLimit MemSize ) (originalStackBucket Bucket , estNumThreads float64 ) {
134128 if sb , ok := a .buckets ["stack" ]; ok {
135129 stackMem := weightedSize (totalWeight (a .buckets ), memLimit , sb )
@@ -146,6 +140,7 @@ func weightedSize(totWeight float64, memLimit MemSize, b Bucket) float64 {
146140 return (float64 (memLimit ) * b .Weight ()) / totWeight
147141}
148142
143+ // Replace stack bucket, and set size per thread
149144func (a * allocator ) unnormaliseStack (sb Bucket , estNum float64 ) {
150145 if sb == nil {
151146 return
@@ -156,18 +151,26 @@ func (a *allocator) unnormaliseStack(sb Bucket, estNum float64) {
156151}
157152
158153// Balance memory between buckets, observing constraints.
159- func (a * allocator ) balance (memLimit MemSize ) {
154+ func (a * allocator ) balance (memLimit MemSize ) error {
160155 remaining := copyBucketMap (a .buckets )
161156 removed := true
162157
163158 for removed && len (remaining ) != 0 {
164159 var err error
165160 memLimit , removed , err = balanceOrRemove (remaining , memLimit )
166161 if err != nil {
167- a .failure = err
168- return
162+ return err
169163 }
170164 }
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
171174}
172175
173176func (a * allocator ) validateAllocation (memLimit MemSize ) {
@@ -179,16 +182,8 @@ func (a *allocator) validateAllocation(memLimit MemSize) {
179182
180183func memoryWastageWarnings (bs map [string ]Bucket , memLimit MemSize ) []string {
181184 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 )... )
192187 }
193188
194189 totalSize := MEMSIZE_ZERO
@@ -205,6 +200,19 @@ func memoryWastageWarnings(bs map[string]Bucket, memLimit MemSize) []string {
205200 return warnings
206201}
207202
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+
208216func closeToDefaultWarnings (bs map [string ]Bucket , sizes map [string ]Range , memLimit MemSize ) []string {
209217 totWeight := totalWeight (bs )
210218 warnings := []string {}
0 commit comments