-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #758 from SiaFoundation/chris/parallelise-packed-u…
…ploads Start uploading next packed slab before previous one is finished
- Loading branch information
Showing
10 changed files
with
293 additions
and
94 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package worker | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"sync" | ||
|
||
"go.sia.tech/renterd/api" | ||
"go.uber.org/zap" | ||
) | ||
|
||
type ( | ||
// memoryManager helps regulate processes that use a lot of memory. Such as | ||
// uploads and downloads. | ||
memoryManager struct { | ||
totalAvailable uint64 | ||
logger *zap.SugaredLogger | ||
|
||
mu sync.Mutex | ||
sigNewMem sync.Cond | ||
available uint64 | ||
} | ||
|
||
acquiredMemory struct { | ||
mm *memoryManager | ||
|
||
mu sync.Mutex | ||
remaining uint64 | ||
} | ||
) | ||
|
||
func newMemoryManager(logger *zap.SugaredLogger, maxMemory uint64) (*memoryManager, error) { | ||
if maxMemory == 0 { | ||
return nil, fmt.Errorf("maxMemory cannot be 0") | ||
} | ||
mm := &memoryManager{ | ||
logger: logger, | ||
totalAvailable: maxMemory, | ||
} | ||
mm.available = mm.totalAvailable | ||
mm.sigNewMem = *sync.NewCond(&mm.mu) | ||
return mm, nil | ||
} | ||
|
||
func (mm *memoryManager) Status() api.MemoryStatus { | ||
mm.mu.Lock() | ||
defer mm.mu.Unlock() | ||
return api.MemoryStatus{ | ||
Available: mm.available, | ||
Total: mm.totalAvailable, | ||
} | ||
} | ||
|
||
func (mm *memoryManager) AcquireMemory(ctx context.Context, amt uint64) *acquiredMemory { | ||
if amt == 0 { | ||
mm.logger.Fatal("cannot acquire 0 memory") | ||
} else if mm.totalAvailable < amt { | ||
mm.logger.Errorf("cannot acquire %v memory with only %v available", amt, mm.totalAvailable) | ||
return nil | ||
} | ||
// block until enough memory is available | ||
mm.sigNewMem.L.Lock() | ||
for mm.available < amt { | ||
mm.sigNewMem.Wait() | ||
|
||
// check if the context was canceled in the meantime | ||
select { | ||
case <-ctx.Done(): | ||
mm.sigNewMem.L.Unlock() | ||
return nil | ||
default: | ||
} | ||
} | ||
mm.available -= amt | ||
mm.sigNewMem.L.Unlock() | ||
|
||
mm.sigNewMem.Signal() // wake next goroutine | ||
return &acquiredMemory{ | ||
mm: mm, | ||
remaining: amt, | ||
} | ||
} | ||
|
||
// release returns all the remaining memory to the memory manager. Should always | ||
// be called on every acquiredMemory when done using it. | ||
func (am *acquiredMemory) Release() { | ||
am.mm.sigNewMem.L.Lock() | ||
am.mm.available += am.remaining | ||
am.mm.sigNewMem.L.Unlock() | ||
|
||
am.mu.Lock() | ||
am.remaining = 0 | ||
am.mu.Unlock() | ||
|
||
am.mm.sigNewMem.Signal() // wake next goroutine | ||
} | ||
|
||
// ReleaseSome releases some of the remaining memory to the memory manager. | ||
// Panics if more memory is released than was acquired. | ||
func (am *acquiredMemory) ReleaseSome(amt uint64) { | ||
am.mm.sigNewMem.L.Lock() | ||
if amt > am.remaining { | ||
panic("releasing more memory than remaining") | ||
} | ||
am.mm.available += amt | ||
am.mm.sigNewMem.L.Unlock() | ||
|
||
am.mu.Lock() | ||
am.remaining -= amt | ||
am.mu.Unlock() | ||
|
||
am.mm.sigNewMem.Signal() // wake next goroutine | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.