kircaali
Committed by Gerrit Code Review

Fix for ONOS-3183

Stream processes by Lambda queries in collection objects has a known performance bottleneck. For each create and update link data operations, this  kind of queries are frequently used and this causes inefficient topology discovery operation. For to solve that problem i analize thread dump during discovery process and i saw that especially getAllProviders method uses high cpu. than i change the provider search operation with additional map data which holds linkkey and its providers. by this way provider search operation not only gets faster but also uses minimum resource. Before that change, i can discover only 4XX number of switches at one controller, but later number grows to 15XX switches

Change-Id: I65ed71b7f295917c818b2f9227d0fc070aa4a29b
...@@ -71,6 +71,7 @@ import org.slf4j.Logger; ...@@ -71,6 +71,7 @@ import org.slf4j.Logger;
71 71
72 import com.google.common.collect.Iterables; 72 import com.google.common.collect.Iterables;
73 import com.google.common.collect.Maps; 73 import com.google.common.collect.Maps;
74 +import com.google.common.collect.Sets;
74 import com.google.common.util.concurrent.Futures; 75 import com.google.common.util.concurrent.Futures;
75 76
76 import static com.google.common.base.Preconditions.checkNotNull; 77 import static com.google.common.base.Preconditions.checkNotNull;
...@@ -117,8 +118,10 @@ public class ECLinkStore ...@@ -117,8 +118,10 @@ public class ECLinkStore
117 private final Logger log = getLogger(getClass()); 118 private final Logger log = getLogger(getClass());
118 119
119 private final Map<LinkKey, Link> links = Maps.newConcurrentMap(); 120 private final Map<LinkKey, Link> links = Maps.newConcurrentMap();
121 + private final Map<LinkKey, Set<ProviderId>> linkProviders = Maps.newConcurrentMap();
120 private EventuallyConsistentMap<Provided<LinkKey>, LinkDescription> linkDescriptions; 122 private EventuallyConsistentMap<Provided<LinkKey>, LinkDescription> linkDescriptions;
121 123
124 +
122 private ApplicationId appId; 125 private ApplicationId appId;
123 126
124 private static final MessageSubject LINK_INJECT_MESSAGE = new MessageSubject("inject-link-request"); 127 private static final MessageSubject LINK_INJECT_MESSAGE = new MessageSubject("inject-link-request");
...@@ -202,6 +205,7 @@ public class ECLinkStore ...@@ -202,6 +205,7 @@ public class ECLinkStore
202 public void deactivate() { 205 public void deactivate() {
203 linkDescriptions.removeListener(linkTracker); 206 linkDescriptions.removeListener(linkTracker);
204 linkDescriptions.destroy(); 207 linkDescriptions.destroy();
208 + linkProviders.clear();
205 links.clear(); 209 links.clear();
206 clusterCommunicator.removeSubscriber(LINK_INJECT_MESSAGE); 210 clusterCommunicator.removeSubscriber(LINK_INJECT_MESSAGE);
207 netCfgService.removeListener(cfgListener); 211 netCfgService.removeListener(cfgListener);
...@@ -305,6 +309,14 @@ public class ECLinkStore ...@@ -305,6 +309,14 @@ public class ECLinkStore
305 return updated; 309 return updated;
306 } 310 }
307 311
312 + private Set<ProviderId> createOrUpdateLinkProviders(Set<ProviderId> current, ProviderId providerId) {
313 + if (current == null) {
314 + current = Sets.newConcurrentHashSet();
315 + }
316 + current.add(providerId);
317 + return current;
318 + }
319 +
308 private LinkEvent refreshLinkCache(LinkKey linkKey) { 320 private LinkEvent refreshLinkCache(LinkKey linkKey) {
309 AtomicReference<LinkEvent.Type> eventType = new AtomicReference<>(); 321 AtomicReference<LinkEvent.Type> eventType = new AtomicReference<>();
310 Link link = links.compute(linkKey, (key, existingLink) -> { 322 Link link = links.compute(linkKey, (key, existingLink) -> {
...@@ -326,11 +338,7 @@ public class ECLinkStore ...@@ -326,11 +338,7 @@ public class ECLinkStore
326 } 338 }
327 339
328 private Set<ProviderId> getAllProviders(LinkKey linkKey) { 340 private Set<ProviderId> getAllProviders(LinkKey linkKey) {
329 - return linkDescriptions.keySet() 341 + return linkProviders.getOrDefault(linkKey, Sets.newConcurrentHashSet());
330 - .stream()
331 - .filter(key -> key.key().equals(linkKey))
332 - .map(key -> key.providerId())
333 - .collect(Collectors.toSet());
334 } 342 }
335 343
336 private ProviderId getBaseProviderId(LinkKey linkKey) { 344 private ProviderId getBaseProviderId(LinkKey linkKey) {
...@@ -358,8 +366,11 @@ public class ECLinkStore ...@@ -358,8 +366,11 @@ public class ECLinkStore
358 getAllProviders(linkKey).stream() 366 getAllProviders(linkKey).stream()
359 .map(p -> new Provided<>(linkKey, p)) 367 .map(p -> new Provided<>(linkKey, p))
360 .forEach(key -> { 368 .forEach(key -> {
369 + LinkDescription linkDescription = linkDescriptions.get(key);
370 + if (linkDescription != null) {
361 annotations.set(merge(annotations.get(), 371 annotations.set(merge(annotations.get(),
362 - linkDescriptions.get(key).annotations())); 372 + linkDescription.annotations()));
373 + }
363 }); 374 });
364 375
365 Link.State initialLinkState; 376 Link.State initialLinkState;
...@@ -375,8 +386,6 @@ public class ECLinkStore ...@@ -375,8 +386,6 @@ public class ECLinkStore
375 } 386 }
376 387
377 388
378 -
379 -
380 return DefaultLink.builder() 389 return DefaultLink.builder()
381 .providerId(baseProviderId) 390 .providerId(baseProviderId)
382 .src(src) 391 .src(src)
...@@ -447,6 +456,7 @@ public class ECLinkStore ...@@ -447,6 +456,7 @@ public class ECLinkStore
447 Link removedLink = links.remove(linkKey); 456 Link removedLink = links.remove(linkKey);
448 if (removedLink != null) { 457 if (removedLink != null) {
449 getAllProviders(linkKey).forEach(p -> linkDescriptions.remove(new Provided<>(linkKey, p))); 458 getAllProviders(linkKey).forEach(p -> linkDescriptions.remove(new Provided<>(linkKey, p)));
459 + linkProviders.remove(linkKey);
450 return new LinkEvent(LINK_REMOVED, removedLink); 460 return new LinkEvent(LINK_REMOVED, removedLink);
451 } 461 }
452 return null; 462 return null;
...@@ -475,9 +485,12 @@ public class ECLinkStore ...@@ -475,9 +485,12 @@ public class ECLinkStore
475 @Override 485 @Override
476 public void event(EventuallyConsistentMapEvent<Provided<LinkKey>, LinkDescription> event) { 486 public void event(EventuallyConsistentMapEvent<Provided<LinkKey>, LinkDescription> event) {
477 if (event.type() == PUT) { 487 if (event.type() == PUT) {
488 + linkProviders.compute(event.key().key(), (k, v) ->
489 + createOrUpdateLinkProviders(v, event.key().providerId()));
478 notifyDelegate(refreshLinkCache(event.key().key())); 490 notifyDelegate(refreshLinkCache(event.key().key()));
479 } else if (event.type() == REMOVE) { 491 } else if (event.type() == REMOVE) {
480 notifyDelegate(purgeLinkCache(event.key().key())); 492 notifyDelegate(purgeLinkCache(event.key().key()));
493 + linkProviders.remove(event.key().key());
481 } 494 }
482 } 495 }
483 } 496 }
......