Skip to content

Commit 25586a5

Browse files
committed
Multi-channel TCert pool making pool's communication with TCA parallel.
We think client_tcert_pool_mt.go can be further improved, by making communication with TCA parallel. The measurement with a prototype shows better performance,(0.8KTPS -> 1.4KTPS for authorizable counter, query) by utilizing CA-side concurrency. This change is enabled by security.multithreading.multichannel=true. Change-Id: I784efb19ae53eb2fccc2eeb6a9912f997cd5eadd Signed-off-by: Akihiko Tozawa <[email protected]>
1 parent 457635a commit 25586a5

File tree

4 files changed

+82
-23
lines changed

4 files changed

+82
-23
lines changed

core/crypto/client_tcert_pool_mt.go

+59-23
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,20 @@ type tCertPoolEntry struct {
3232
client *clientImpl
3333
}
3434

35+
const maxFillerThreads = 5
36+
3537
//NewTCertPoolEntry creates a new tcert pool entry
3638
func newTCertPoolEntry(client *clientImpl, attributes []string) *tCertPoolEntry {
37-
tCertChannel := make(chan *TCertBlock, client.conf.getTCertBatchSize()*2)
38-
tCertChannelFeedback := make(chan struct{}, client.conf.getTCertBatchSize()*2)
39+
var tCertChannel chan *TCertBlock
40+
var tCertChannelFeedback chan struct{}
41+
42+
if client.conf.IsMultiChannelEnabled() {
43+
tCertChannel = make(chan *TCertBlock, client.conf.getTCertBatchSize()*maxFillerThreads)
44+
tCertChannelFeedback = make(chan struct{}, maxFillerThreads)
45+
} else {
46+
tCertChannel = make(chan *TCertBlock, client.conf.getTCertBatchSize()*2)
47+
tCertChannelFeedback = make(chan struct{}, client.conf.getTCertBatchSize()*2)
48+
}
3949
done := make(chan struct{}, 1)
4050
return &tCertPoolEntry{attributes, tCertChannel, tCertChannelFeedback, done, client}
4151
}
@@ -90,9 +100,11 @@ func (tCertPoolEntry *tCertPoolEntry) GetNextTCert(attributes ...string) (tCertB
90100
tCertPoolEntry.client.Error("Failed getting a new TCert. Buffer is empty!")
91101
}
92102
if tCertBlock != nil {
93-
// Send feedback to the filler
94-
tCertPoolEntry.client.Debug("Send feedback")
95-
tCertPoolEntry.tCertChannelFeedback <- struct{}{}
103+
if !tCertPoolEntry.client.conf.IsMultiChannelEnabled() {
104+
// Send feedback to the filler
105+
tCertPoolEntry.client.Debug("Send feedback")
106+
tCertPoolEntry.tCertChannelFeedback <- struct{}{}
107+
}
96108
break
97109
}
98110
}
@@ -175,14 +187,24 @@ func (tCertPoolEntry *tCertPoolEntry) filler() {
175187
tCertPoolEntry.client.Debug("Load unused TCerts...done!")
176188

177189
if !stop {
178-
ticker := time.NewTicker(1 * time.Second)
190+
fillerThreads := 0
191+
var ticker *time.Ticker
192+
if tCertPoolEntry.client.conf.IsMultiChannelEnabled() {
193+
ticker = time.NewTicker(200 * time.Millisecond)
194+
} else {
195+
ticker = time.NewTicker(1 * time.Second)
196+
}
179197
for {
180198
select {
181199
case <-tCertPoolEntry.done:
182200
stop = true
183201
tCertPoolEntry.client.Debug("Done signal.")
184202
case <-tCertPoolEntry.tCertChannelFeedback:
185-
tCertPoolEntry.client.Debug("Feedback received. Time to check for tcerts")
203+
if tCertPoolEntry.client.conf.IsMultiChannelEnabled() {
204+
fillerThreads--
205+
} else {
206+
tCertPoolEntry.client.Debug("Feedback received. Time to check for tcerts")
207+
}
186208
case <-ticker.C:
187209
tCertPoolEntry.client.Debug("Time elapsed. Time to check for tcerts")
188210
}
@@ -192,25 +214,39 @@ func (tCertPoolEntry *tCertPoolEntry) filler() {
192214
break
193215
}
194216

195-
if len(tCertPoolEntry.tCertChannel) < tCertPoolEntry.client.conf.getTCertBatchSize() {
196-
tCertPoolEntry.client.Debugf("Refill TCert Pool. Current size [%d].",
197-
len(tCertPoolEntry.tCertChannel),
198-
)
217+
if tCertPoolEntry.client.conf.IsMultiChannelEnabled() {
199218

200-
var numTCerts = cap(tCertPoolEntry.tCertChannel) - len(tCertPoolEntry.tCertChannel)
201-
if len(tCertPoolEntry.tCertChannel) == 0 {
202-
numTCerts = cap(tCertPoolEntry.tCertChannel) / 10
203-
if numTCerts < 1 {
204-
numTCerts = 1
205-
}
206-
}
219+
for len(tCertPoolEntry.tCertChannel) <= tCertPoolEntry.client.conf.getTCertBatchSize()*(maxFillerThreads-fillerThreads-1) {
220+
tCertPoolEntry.client.Debugf("Refill TCert Pool. Current size [%d].", len(tCertPoolEntry.tCertChannel))
221+
numTCerts := tCertPoolEntry.client.conf.getTCertBatchSize()
207222

208-
tCertPoolEntry.client.Infof("Refilling [%d] TCerts.", numTCerts)
223+
tCertPoolEntry.client.Infof("Refilling [%d] TCerts.", numTCerts)
224+
fillerThreads++
209225

210-
err := tCertPoolEntry.client.getTCertsFromTCA(calculateAttributesHash(tCertPoolEntry.attributes), tCertPoolEntry.attributes, numTCerts)
211-
if err != nil {
212-
tCertPoolEntry.client.Errorf("Failed getting TCerts from the TCA: [%s]", err)
213-
break
226+
go func() {
227+
err := tCertPoolEntry.client.getTCertsFromTCA(calculateAttributesHash(tCertPoolEntry.attributes), tCertPoolEntry.attributes, numTCerts)
228+
if err != nil {
229+
tCertPoolEntry.client.Errorf("Failed getting TCerts from the TCA: [%s]", err)
230+
}
231+
tCertPoolEntry.tCertChannelFeedback <- struct{}{}
232+
}()
233+
}
234+
} else {
235+
if len(tCertPoolEntry.tCertChannel) < tCertPoolEntry.client.conf.getTCertBatchSize() {
236+
tCertPoolEntry.client.Debugf("Refill TCert Pool. Current size [%d].", len(tCertPoolEntry.tCertChannel))
237+
var numTCerts = cap(tCertPoolEntry.tCertChannel) - len(tCertPoolEntry.tCertChannel)
238+
if len(tCertPoolEntry.tCertChannel) == 0 {
239+
numTCerts = cap(tCertPoolEntry.tCertChannel) / 10
240+
if numTCerts < 1 {
241+
numTCerts = 1
242+
}
243+
}
244+
tCertPoolEntry.client.Infof("Refilling [%d] TCerts.", numTCerts)
245+
246+
err := tCertPoolEntry.client.getTCertsFromTCA(calculateAttributesHash(tCertPoolEntry.attributes), tCertPoolEntry.attributes, numTCerts)
247+
if err != nil {
248+
tCertPoolEntry.client.Errorf("Failed getting TCerts from the TCA: [%s]", err)
249+
}
214250
}
215251
}
216252
}

core/crypto/crypto_test.go

+7
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ func TestMain(m *testing.M) {
8888
if ret != 0 {
8989
os.Exit(ret)
9090
}
91+
92+
// Third scenario (repeat the above) now also with 'security.multithreading.multichannel' enabled.
93+
properties["security.multithreading.multichannel"] = "true"
94+
ret = runTestsOnScenario(m, properties, "Using multithread + multichannel enabled")
95+
if ret != 0 {
96+
os.Exit(ret)
97+
}
9198
properties["security.multithreading.enabled"] = "false"
9299

93100
//Fourth scenario with security level = 384

core/crypto/node_conf.go

+12
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ type configuration struct {
6262
tlsServerName string
6363

6464
multiThreading bool
65+
multiChannel bool
66+
6567
tCertBatchSize int
6668
}
6769

@@ -152,6 +154,12 @@ func (conf *configuration) init() error {
152154
conf.multiThreading = viper.GetBool("security.multithreading.enabled")
153155
}
154156

157+
// Set multichannel
158+
conf.multiChannel = false
159+
if viper.IsSet("security.multithreading.multichannel") {
160+
conf.multiChannel = viper.GetBool("security.multithreading.multichannel")
161+
}
162+
155163
return nil
156164
}
157165

@@ -255,6 +263,10 @@ func (conf *configuration) IsMultithreadingEnabled() bool {
255263
return conf.multiThreading
256264
}
257265

266+
func (conf *configuration) IsMultiChannelEnabled() bool {
267+
return conf.multiChannel
268+
}
269+
258270
func (conf *configuration) getTCAServerName() string {
259271
return conf.tlsServerName
260272
}

peer/core.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -411,8 +411,12 @@ security:
411411
# security to be enabled).
412412
attributes:
413413
enabled: false
414+
415+
# TCerts pool configuration. Multi-thread pool can also be configured
416+
# by multichannel option switching concurrency in communication with TCA.
414417
multithreading:
415418
enabled: false
419+
multichannel: false
416420

417421
# Confidentiality protocol versions supported: 1.2
418422
confidentialityProtocolVersion: 1.2

0 commit comments

Comments
 (0)