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
Showing
1 changed file
with
21 additions
and
8 deletions
... | @@ -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 | } | ... | ... |
-
Please register or login to post a comment