All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.eBus.config.ThreadAffinity Maven / Gradle / Ivy

//
// Copyright 2021 Charles W. Rapp
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package net.sf.eBus.config;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import net.openhft.affinity.AffinityLock;
import net.openhft.affinity.AffinityStrategies;
import net.sf.eBus.config.ThreadAffinityConfigure.AffinityType;

/**
 * Provides interface to
 * OpenHFT Thread Affinity Library
 * based on a given {@link ThreadAffinityConfigure}. The idea is
 * that by binding a thread to a core thread performance is
 * improved. But this improvement can only be realized if the
 * core is isolated from operating system use. Otherwise the
 * thread still faces losing its core to the OS, having to wait
 * to gain the core again with its cache wrecked by the OS
 * thread.
 * 

* Please see {@link ThreadAffinityConfigure} for a detailed * discussion on how to configure thread affinity. *

*

* This class is designed for use with * {@code net.sf.eBus.net.SelectorThread} and * {@code net.sf.eBus.net.client.EClient.RQThread} both of which * may be bound to a core. This would normally be done when the * thread is configured as spinning. *

* * @see ThreadAffinityConfigure * * @author Charles W. Rapp */ public final class ThreadAffinity { //--------------------------------------------------------------- // Member data. // //----------------------------------------------------------- // Statics. // /** * Locks CPU affinity lock process to prevent concurrent * acquisition which will cause failures. */ private static final Lock sAcquisitionLock = new ReentrantLock(); //--------------------------------------------------------------- // Member methods. // //----------------------------------------------------------- // Constructors. // /** * Private constructor to prevent instantiation. */ private ThreadAffinity() {} // // end of Constructors. //----------------------------------------------------------- /** * Returns an OpenHFT thread affinity lock. * @param config * @return thread affinity lock. This lock should be * {@link AffinityLock#release() released} when the thread * stops. * @throws IllegalStateException * if {@code config.affinityType} is * {@code AffinityType.CPU_STRATEGIES} which requires an * existing {@code AffinityLock} to work. * * @see #acquireLock(AffinityLock, ThreadAffinityConfigure) */ public static AffinityLock acquireLock(final ThreadAffinityConfigure config) { final AffinityType type = config.affinityType(); final AffinityLock retval; if (type == AffinityType.CPU_STRATEGIES) { throw ( new IllegalStateException( "affinity lock acquisition using strategies requires an existing lock")); } sAcquisitionLock.lock(); try { switch (type) { case ANY_CORE: retval = AffinityLock.acquireCore(); break; case ANY_CPU: retval = AffinityLock.acquireLock(); break; case CPU_ID: retval = AffinityLock.acquireLock(config.cpuId()); break; default: retval = AffinityLock.acquireLockLastMinus( config.cpuOffset()); } if (config.bindFlag()) { retval.bind(config.wholeCoreFlag()); } } finally { sAcquisitionLock.unlock(); } return (retval); } // end of acquireLock(ThreadAffinityConfigure) /** * Returns an OpenHFT thread affinity lock based on an * existing lock and CPU strategy configuration. The idea * is OpenHFT will select a CPU based on the existing lock's * CPU and the CPU selection strategies. Please not that the * final strategy is {@link AffinityStrategies#ANY} allowing * any CPU to be chosen if no available CPU matches the * previous strategies. * @param lock existing affinity lock. * @param config CPU selection strategy. * @return thread affinity lock. This lock should be * {@link AffinityLock#release() released} when the thread * stops. * @throws NullPointerException * if {@code lock} or {@code config} is {@code null}. * @throws IllegalArgumentException * if {@code config} affinity type is not * {@code AffinityType.CPU_STRATEGIES}. * * @see #acquireLock(ThreadAffinityConfigure) */ public static AffinityLock acquireLock(final AffinityLock lock, final ThreadAffinityConfigure config) { final AffinityType type = config.affinityType(); final AffinityLock retval; Objects.requireNonNull(lock, "lock is null"); if (type != AffinityType.CPU_STRATEGIES) { throw ( new IllegalArgumentException( String.format( "invalid affinity type %s, must be %s", type, AffinityType.CPU_STRATEGIES))); } sAcquisitionLock.lock(); try { final List strategies = config.strategies(); retval = lock.acquireLock( strategies.toArray( new AffinityStrategies[strategies.size()])); if (config.bindFlag()) { retval.bind(config.wholeCoreFlag()); } } finally { sAcquisitionLock.unlock(); } return (retval); } // end of acquireLock(AffinityLock,ThreadAffinityConfigure) } // end of class ThreadAffinity




© 2015 - 2025 Weber Informatics LLC | Privacy Policy