From 72c044e2eb553abf0e0fd7eb87043176f23400f0 Mon Sep 17 00:00:00 2001
From: Evgenii Stratonikov <evgeniy@nspcc.ru>
Date: Wed, 8 Jun 2022 14:03:29 +0300
Subject: [PATCH] [#1599] engine: Parallelize shard initialization

Shard is intended to be used as a separate failure domain,
which usually resides on a separate disk. Thus, sequential
initialization is bound by IO and this change speeds up thing a bit.

Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
---
 pkg/local_object_storage/engine/control.go | 40 +++++++++++++++++++---
 1 file changed, 36 insertions(+), 4 deletions(-)

diff --git a/pkg/local_object_storage/engine/control.go b/pkg/local_object_storage/engine/control.go
index f57536511..4fc39da8f 100644
--- a/pkg/local_object_storage/engine/control.go
+++ b/pkg/local_object_storage/engine/control.go
@@ -3,7 +3,9 @@ package engine
 import (
 	"errors"
 	"fmt"
+	"sync"
 
+	"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard"
 	"go.uber.org/zap"
 )
 
@@ -16,9 +18,24 @@ func (e *StorageEngine) open() error {
 	e.mtx.RLock()
 	defer e.mtx.RUnlock()
 
+	var wg sync.WaitGroup
+	var errCh = make(chan error, len(e.shards))
+
 	for id, sh := range e.shards {
-		if err := sh.Open(); err != nil {
-			return fmt.Errorf("could not open shard %s: %w", id, err)
+		wg.Add(1)
+		go func(id string, sh *shard.Shard) {
+			defer wg.Done()
+			if err := sh.Open(); err != nil {
+				errCh <- fmt.Errorf("could not open shard %s: %w", id, err)
+			}
+		}(id, sh.Shard)
+	}
+	wg.Wait()
+	close(errCh)
+
+	for err := range errCh {
+		if err != nil {
+			return err
 		}
 	}
 
@@ -30,9 +47,24 @@ func (e *StorageEngine) Init() error {
 	e.mtx.RLock()
 	defer e.mtx.RUnlock()
 
+	var wg sync.WaitGroup
+	var errCh = make(chan error, len(e.shards))
+
 	for id, sh := range e.shards {
-		if err := sh.Init(); err != nil {
-			return fmt.Errorf("could not initialize shard %s: %w", id, err)
+		wg.Add(1)
+		go func(id string, sh *shard.Shard) {
+			defer wg.Done()
+			if err := sh.Init(); err != nil {
+				errCh <- fmt.Errorf("could not initialize shard %s: %w", id, err)
+			}
+		}(id, sh.Shard)
+	}
+	wg.Wait()
+	close(errCh)
+
+	for err := range errCh {
+		if err != nil {
+			return err
 		}
 	}