├── .gitignore ├── LICENSE ├── README.adoc ├── affinity-test ├── pom.xml └── src │ ├── main │ └── java │ │ └── net │ │ └── openhft │ │ └── affinity │ │ └── osgi │ │ └── OSGiPlaceholder.java │ └── test │ └── java │ └── net │ └── openhft │ └── affinity │ └── osgi │ ├── OSGiBundleTest.java │ └── OSGiTestBase.java ├── affinity ├── pom.xml └── src │ ├── main │ ├── c │ │ ├── Makefile │ │ ├── net_openhft_ticker_impl_JNIClock.cpp │ │ ├── software_chronicle_enterprise_internals_impl_NativeAffinity.cpp │ │ └── software_chronicle_enterprise_internals_impl_NativeAffinity_MacOSX.c │ └── java │ │ ├── net │ │ └── openhft │ │ │ ├── affinity │ │ │ ├── Affinity.java │ │ │ ├── AffinityLock.java │ │ │ ├── AffinityStrategies.java │ │ │ ├── AffinityStrategy.java │ │ │ ├── AffinityThreadFactory.java │ │ │ ├── BootClassPath.java │ │ │ ├── CpuLayout.java │ │ │ ├── IAffinity.java │ │ │ ├── LockCheck.java │ │ │ ├── LockInventory.java │ │ │ ├── MicroJitterSampler.java │ │ │ ├── impl │ │ │ │ ├── LinuxHelper.java │ │ │ │ ├── LinuxJNAAffinity.java │ │ │ │ ├── NoCpuLayout.java │ │ │ │ ├── NullAffinity.java │ │ │ │ ├── OSXJNAAffinity.java │ │ │ │ ├── PosixJNAAffinity.java │ │ │ │ ├── SolarisJNAAffinity.java │ │ │ │ ├── Utilities.java │ │ │ │ ├── VanillaCpuLayout.java │ │ │ │ ├── VersionHelper.java │ │ │ │ └── WindowsJNAAffinity.java │ │ │ ├── lockchecker │ │ │ │ ├── FileLockBasedLockChecker.java │ │ │ │ ├── LockChecker.java │ │ │ │ └── LockReference.java │ │ │ └── main │ │ │ │ └── AffinityTestMain.java │ │ │ └── ticker │ │ │ ├── ITicker.java │ │ │ ├── Ticker.java │ │ │ └── impl │ │ │ ├── JNIClock.java │ │ │ └── SystemClock.java │ │ └── software │ │ └── chronicle │ │ └── enterprise │ │ └── internals │ │ └── impl │ │ └── NativeAffinity.java │ └── test │ ├── java │ ├── net │ │ └── openhft │ │ │ ├── affinity │ │ │ ├── AffinityLockBindMain.java │ │ │ ├── AffinityLockMain.java │ │ │ ├── AffinityLockTest.java │ │ │ ├── AffinitySupportMain.java │ │ │ ├── AffinityThreadFactoryMain.java │ │ │ ├── BaseAffinityTest.java │ │ │ ├── BootClassPathTest.java │ │ │ ├── FileLockLockCheckTest.java │ │ │ ├── InterrupedThread.java │ │ │ ├── LockCheckTest.java │ │ │ ├── MultiProcessAffinityTest.java │ │ │ ├── impl │ │ │ │ ├── AbstractAffinityImplTest.java │ │ │ │ ├── LinuxJNAAffinityTest.java │ │ │ │ ├── NativeAffinityImpTest.java │ │ │ │ ├── PosixJNAAffinityTest.java │ │ │ │ ├── VanillaCpuLayoutTest.java │ │ │ │ └── VersionHelperTest.java │ │ │ └── testimpl │ │ │ │ └── TestFileLockBasedLockChecker.java │ │ │ └── ticker │ │ │ └── impl │ │ │ └── JNIClockTest.java │ └── software │ │ └── chronicle │ │ └── enterprise │ │ └── internals │ │ ├── JnaAffinityTest.java │ │ └── NativeAffinityTest.java │ └── resources │ ├── amd64.dual.core.cpuinfo │ ├── amd64.quad.core.cpuinfo │ ├── core.duo.cpuinfo │ ├── dual.E5405.cpuinfo │ ├── dual.xeon.cpuinfo │ ├── i3.cpuinfo │ ├── i7.cpuinfo │ ├── i7.properties │ ├── q6600.noht.cpuinfo │ └── q6600.vm.cpuinfo ├── docs └── images │ └── Thread-Affinity_line.png └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | ### How to update 2 | # This is copied from OpenHFT/.gitignore 3 | # update the original and run OpenHFT/update_gitignore.sh 4 | 5 | ### Compiled class file 6 | *.class 7 | 8 | ### Package Files 9 | *.jar 10 | *.war 11 | *.ear 12 | 13 | ### Log file 14 | *.log 15 | 16 | ### IntelliJ 17 | *.iml 18 | *.ipr 19 | *.iws 20 | .idea 21 | compat_reports 22 | .attach_pid* 23 | 24 | ### Virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 25 | hs_err_pid* 26 | 27 | ### Maven template 28 | target/ 29 | pom.xml.tag 30 | pom.xml.releaseBackup 31 | pom.xml.versionsBackup 32 | pom.xml.next 33 | release.properties 34 | 35 | ### Eclipse template 36 | *.pydevproject 37 | .metadata 38 | .gradle 39 | bin/ 40 | tmp/ 41 | *.tmp 42 | *.bak 43 | *.swp 44 | *~.nib 45 | local.properties 46 | .classpath 47 | .project 48 | .settings/ 49 | .loadpath 50 | 51 | ### Queue files 52 | *.cq4t 53 | *.cq4 54 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = Thread Affinity 2 | 3 | image::docs/images/Thread-Affinity_line.png[width=20%] 4 | 5 | == Version 6 | 7 | [#image-maven] 8 | [caption="", link=https://maven-badges.herokuapp.com/maven-central/net.openhft/affinity] 9 | image::https://maven-badges.herokuapp.com/maven-central/net.openhft/affinity/badge.svg[] 10 | image:https://javadoc.io/badge2/net.openhft/affinity/javadoc.svg[link="https://www.javadoc.io/doc/net.openhft/affinity/latest/index.html"] 11 | 12 | == Overview 13 | Lets you bind a thread to a given core, this can improve performance (this library works best on linux). 14 | 15 | OpenHFT Java Thread Affinity library 16 | 17 | See https://github.com/OpenHFT/Java-Thread-Affinity/tree/master/affinity/src/test/java[affinity/src/test/java] 18 | for working examples of how to use this library. 19 | 20 | === Changes 21 | 22 | * V3.2.0 - Add support for text configuration 23 | * V3.1.1 - Upgraded JNA dependency to 4.4.0 24 | * V2.0.1 - Added getThreadId for the process if of the thread. 25 | 26 | === Dependencies 27 | 28 | Java-Thread-Affinity will try to use https://github.com/java-native-access/jna[JNA] 29 | to provide access to native thread-handling functions. JNA should be installed on 30 | your system to get the most from this library. 31 | 32 | === JNA version 33 | 34 | Java-Thread-Affinity currently depends on JNA version 4.4.0, which in turn 35 | depends on a version of GLIBC >= 2.14. If your operating system is an old one, 36 | with a version of GLIBC released before 2011, this library will not be able to 37 | invoke native functions. 38 | 39 | To work around this problem, fork the repository, and override the `` tag 40 | for the artifacts `jna` and `jna-platform` in the project's `pom` file. 41 | 42 | === Installing JNA on Ubuntu 43 | 44 | sudo apt-get install libjna-java 45 | 46 | === Installing JNA on CentOS 47 | 48 | sudo yum install jna 49 | 50 | === How does CPU allocation work? 51 | The library will read your `/proc/cpuinfo` if you have one or provide one and it will determine your CPU layout. If you don't have one it will assume every CPU is on one CPU socket. 52 | 53 | The library looks for isolated CPUs determined by looking at the CPUs you are not running on by default. 54 | i.e. if you have 16 CPUs but 8 of them are not available for general use (as determined by the affinity of the process on startup) it will start assigning to those CPUs. 55 | 56 | Note: if you have more than one process using this library you need to specify which CPUs the process can use otherwise it will assign the same CPUs to both processes. 57 | To control which CPUs a process can use, add -Daffinity.reserved={cpu-mask-in-hex} to the command line of the process. 58 | 59 | Note: the CPU 0 is reserved for the Operating System, it has to run somewhere. 60 | 61 | === References 62 | 63 | https://github.com/peter-lawrey/Java-Thread-Affinity/wiki/Getting-started 64 | 65 | https://github.com/peter-lawrey/Java-Thread-Affinity/wiki/How-it-works 66 | 67 | http://vanillajava.blogspot.co.uk/2013/07/micro-jitter-busy-waiting-and-binding.html 68 | 69 | === isolcpus 70 | 71 | Java-Thread-Affinity requires that you first isolate some CPU's. 72 | 73 | Once a CPU core is isolated, the Linux scheduler will not use the CPU core to run any user-space processes. The isolated CPUs will not participate in load balancing, and will not have tasks running on them unless explicitly assigned. 74 | 75 | To isolate the 1st and 3rd CPU cores (CPU numbers start from 0) on your system, add the following to the kernel command line during boot: 76 | 77 | isolcpus=1,3 78 | 79 | == Using AffinityLock 80 | 81 | === Acquiring a CPU lock for a thread 82 | You can acquire a lock for a CPU in the following way: 83 | 84 | In Java 6 85 | [source, java] 86 | ---- 87 | AffinityLock al = AffinityLock.acquireLock(); 88 | try { 89 | // do some work locked to a CPU. 90 | } finally { 91 | al.release(); 92 | } 93 | ---- 94 | 95 | In Java 7 or 8 96 | [source, java] 97 | ---- 98 | try (AffinityLock al = AffinityLock.acquireLock()) { 99 | // do some work while locked to a CPU. 100 | } 101 | ---- 102 | You have further options such as 103 | 104 | === Acquiring a CORE lock for a thread 105 | You can reserve a whole core. If you have hyper-threading enabled, this will use one CPU and leave it's twin CPU unused. 106 | [source, java] 107 | ---- 108 | try (AffinityLock al = AffinityLock.acquireCore()) { 109 | // do some work while locked to a CPU. 110 | } 111 | ---- 112 | === Controlling layout 113 | You can chose a layout relative to an existing lock. 114 | [source, java] 115 | ---- 116 | try (final AffinityLock al = AffinityLock.acquireLock()) { 117 | System.out.println("Main locked"); 118 | Thread t = new Thread(new Runnable() { 119 | @Override 120 | public void run() { 121 | try (AffinityLock al2 = al.acquireLock(AffinityStrategies.SAME_SOCKET, 122 | AffinityStrategies.ANY)) { 123 | System.out.println("Thread-0 locked"); 124 | } 125 | } 126 | }); 127 | t.start(); 128 | } 129 | ---- 130 | In this example, the library will prefer a free CPU on the same Socket as the first thread, otherwise it will pick any free CPU. 131 | 132 | === Getting the thread id 133 | You can get the current thread id using 134 | [source, java] 135 | ---- 136 | 137 | int threadId = AffinitySupport.getThreadId(); 138 | ---- 139 | === Determining which CPU you are running on 140 | You can get the current CPU being used by 141 | [source, java] 142 | ---- 143 | 144 | int cpuId = AffinitySupport.getCpu(); 145 | ---- 146 | === Controlling the affinity more directly 147 | The affinity of the process on start up is 148 | [source, java] 149 | ---- 150 | 151 | long baseAffinity = AffinityLock.BASE_AFFINITY; 152 | ---- 153 | The available CPU for reservation is 154 | [source, java] 155 | ---- 156 | long reservedAffinity = AffinityLock.RESERVED_AFFINITY; 157 | ---- 158 | If you want to get/set the affinity directly you can do 159 | [source, java] 160 | ---- 161 | long currentAffinity = AffinitySupport.getAffinity(); 162 | AffinitySupport.setAffinity(1L << 5); // lock to CPU 5. 163 | ---- 164 | 165 | === Debugging affinity state 166 | 167 | For a detailed of view of the current affinity state (as seen by the library), 168 | execute the following script on Linux systems: 169 | 170 | [source] 171 | ---- 172 | # change to the affinity lock-file directory (defaults to system property java.io.tmpdir) 173 | $ cd /tmp 174 | 175 | # dump affinity state 176 | $ for i in "$(ls cpu-*)"; 177 | do PID="$(cat $i | head -n1)"; TIMESTAMP="$(cat $i | tail -n1)"; 178 | echo "pid $PID locked at $TIMESTAMP in $i"; taskset -cp $PID; 179 | cat "/proc/$PID/cmdline"; echo; echo 180 | done 181 | 182 | pid 14584 locked at 2017.10.30 at 10:33:24 GMT in cpu-3.lock 183 | pid 14584's current affinity list: 3 184 | /opt/jdk1.8.0_141/bin/java ... 185 | 186 | ---- 187 | 188 | == Support Material 189 | 190 | https://groups.google.com/forum/?hl=en-GB#!forum/java-thread-affinity[Java Thread Affinity support group] 191 | 192 | For an article on how much difference affinity can make and how to use it http://vanillajava.blogspot.com/2013/07/micro-jitter-busy-waiting-and-binding.html 193 | 194 | == Questions and Answers 195 | 196 | === Question: How to lock a specific cpuId 197 | I am currently working on a project related to deadlock detection in multithreaded programs in java. We are trying to run threads on different processors and thus came across your github posts regarding the same. https://github.com/peter-lawrey/Java-Thread-Affinity/wiki/Getting-started 198 | Being a beginner, I have little knowledge and thus need your assistance. We need to know how to run threads on specified cpu number and then switch threads when one is waiting. 199 | 200 | === Answer 201 | 202 | [source, java] 203 | ---- 204 | // lock a cpuId 205 | try (AffinityLock lock = AffinityLock.acquireLock(n)) { 206 | 207 | } 208 | ---- 209 | 210 | where n is the cpu you want to run the thread on. 211 | 212 | OR 213 | 214 | [source,java] 215 | ---- 216 | // lock one of the last CPUs 217 | try (AffinityLock lock = AffinityLock.acquireLockLastMinus(n)) { 218 | 219 | } 220 | ---- 221 | 222 | === Question: how to use a configuration file to set the cpuId 223 | 224 | I have the cpuId in a configuration file, how can I set it using a string? 225 | 226 | === Answer: use one of the following 227 | 228 | [source,java] 229 | ---- 230 | try (AffinityLock lock = AffinityLock.acquireLock("last")) { 231 | assertEquals(PROCESSORS - 1, Affinity.getCpu()); 232 | } 233 | try (AffinityLock lock = AffinityLock.acquireLock("last-1")) { 234 | assertEquals(PROCESSORS - 2, Affinity.getCpu()); 235 | } 236 | try (AffinityLock lock = AffinityLock.acquireLock("1")) { 237 | assertEquals(1, Affinity.getCpu()); 238 | } 239 | try (AffinityLock lock = AffinityLock.acquireLock("any")) { 240 | assertTrue(lock.bound); 241 | } 242 | try (AffinityLock lock = AffinityLock.acquireLock("none")) { 243 | assertFalse(lock.bound); 244 | } 245 | try (AffinityLock lock = AffinityLock.acquireLock((String) null)) { 246 | assertFalse(lock.bound); 247 | } 248 | try (AffinityLock lock = AffinityLock.acquireLock("0")) { // prints a warning 249 | assertFalse(lock.bound); 250 | } 251 | ---- 252 | -------------------------------------------------------------------------------- /affinity-test/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 4.0.0 20 | 21 | 22 | net.openhft 23 | java-parent-pom 24 | 1.27ea0 25 | 26 | 27 | 28 | affinity-test 29 | 3.27ea1-SNAPSHOT 30 | bundle 31 | 32 | OpenHFT/Java-Thread-Affinity/affinity-test 33 | Java Thread Affinity library 34 | 35 | 36 | UTF-8 37 | 38 | 39 | 40 | 41 | 42 | net.openhft 43 | third-party-bom 44 | 3.27ea0 45 | pom 46 | import 47 | 48 | 49 | net.openhft 50 | affinity 51 | ${project.version} 52 | 53 | 54 | 55 | 56 | 57 | 58 | net.openhft 59 | affinity 60 | 61 | 62 | javax.inject 63 | javax.inject 64 | test 65 | 66 | 67 | org.osgi 68 | org.osgi.core 69 | test 70 | 71 | 72 | org.osgi 73 | org.osgi.compendium 74 | test 75 | 76 | 77 | org.ops4j.pax.exam 78 | pax-exam-container-native 79 | test 80 | 81 | 82 | 83 | org.ops4j.pax.exam 84 | pax-exam-junit4 85 | test 86 | 87 | 88 | org.ops4j.pax.exam 89 | pax-exam-link-mvn 90 | test 91 | 92 | 93 | org.ops4j.pax.url 94 | pax-url-aether 95 | test 96 | 97 | 98 | org.ops4j.pax.url 99 | pax-url-reference 100 | test 101 | 102 | 103 | org.apache.felix 104 | org.apache.felix.framework 105 | test 106 | 107 | 108 | org.slf4j 109 | slf4j-api 110 | test 111 | 112 | 113 | org.slf4j 114 | slf4j-simple 115 | test 116 | 117 | 118 | 119 | 120 | 121 | 122 | org.apache.maven.plugins 123 | maven-compiler-plugin 124 | 125 | -Xlint:deprecation 126 | 1.8 127 | 1.8 128 | UTF-8 129 | 130 | 131 | 139 | 140 | org.apache.servicemix.tooling 141 | depends-maven-plugin 142 | 143 | 144 | generate-depends-file 145 | 146 | generate-depends-file 147 | 148 | 149 | 150 | 151 | 152 | 153 | org.apache.felix 154 | maven-bundle-plugin 155 | true 156 | 157 | 158 | ${project.groupId}.${project.artifactId} 159 | 160 | ${project.artifactId} 161 | 162 | net.openhft.affinity.osgi 163 | 164 | 165 | * 166 | 167 | 168 | 169 | 170 | 174 | 175 | 176 | manifest 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | pre-java9 187 | 188 | 189 | com.sun 190 | tools 191 | 1.8.0 192 | system 193 | ${java.home}/../lib/tools.jar 194 | 195 | 196 | 197 | 198 | ${java.home}/../lib/tools.jar 199 | 200 | 201 | 202 | 203 | 204 | 205 | scm:git:git@github.com:OpenHFT/Java-Thread-Affinity.git 206 | ea 207 | scm:git:git@github.com:OpenHFT/Java-Thread-Affinity.git 208 | scm:git:git@github.com:OpenHFT/Java-Thread-Affinity.git 209 | 210 | 211 | 212 | 213 | -------------------------------------------------------------------------------- /affinity-test/src/main/java/net/openhft/affinity/osgi/OSGiPlaceholder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity.osgi; 19 | 20 | /** 21 | * A placeholder to have some plugin works 22 | */ 23 | public class OSGiPlaceholder { 24 | } 25 | -------------------------------------------------------------------------------- /affinity-test/src/test/java/net/openhft/affinity/osgi/OSGiBundleTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity.osgi; 19 | 20 | import org.junit.Ignore; 21 | import org.junit.Test; 22 | import org.junit.runner.RunWith; 23 | import org.ops4j.pax.exam.Configuration; 24 | import org.ops4j.pax.exam.Option; 25 | import org.ops4j.pax.exam.junit.PaxExam; 26 | import org.osgi.framework.Bundle; 27 | import org.osgi.framework.BundleContext; 28 | 29 | import javax.inject.Inject; 30 | 31 | import static org.junit.Assert.*; 32 | import static org.ops4j.pax.exam.CoreOptions.*; 33 | 34 | @Ignore("TODO FIX") 35 | @RunWith(PaxExam.class) 36 | public class OSGiBundleTest extends net.openhft.affinity.osgi.OSGiTestBase { 37 | @Inject 38 | BundleContext context; 39 | 40 | @Configuration 41 | public Option[] config() { 42 | return options( 43 | systemProperty("org.osgi.framework.storage.clean").value("true"), 44 | systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("WARN"), 45 | mavenBundleAsInProject("org.slf4j", "slf4j-api"), 46 | mavenBundleAsInProject("org.slf4j", "slf4j-simple").noStart(), 47 | mavenBundleAsInProject("net.openhft", "affinity"), 48 | workspaceBundle("affinity-test"), 49 | junitBundles(), 50 | systemPackage("sun.misc"), 51 | systemPackage("sun.nio.ch"), 52 | systemPackage("com.sun.jna"), 53 | systemPackage("com.sun.jna.ptr"), 54 | cleanCaches() 55 | ); 56 | } 57 | 58 | @Test 59 | public void checkInject() { 60 | assertNotNull(context); 61 | } 62 | 63 | @Test 64 | public void checkBundleState() { 65 | final Bundle bundle = findBundle(context, "net.openhft.affinity"); 66 | assertNotNull(bundle); 67 | assertEquals(bundle.getState(), Bundle.ACTIVE); 68 | } 69 | 70 | @Test 71 | public void checkBundleExports() { 72 | final Bundle bundle = findBundle(context, "net.openhft.affinity"); 73 | assertNotNull(bundle); 74 | 75 | final String exports = bundle.getHeaders().get("Export-Package"); 76 | final String[] packages = exports.split(","); 77 | 78 | assertTrue(packages.length >= 2); 79 | assertTrue(packages[0].startsWith("net.openhft.affinity;") 80 | || packages[0].startsWith("net.openhft.affinity.impl;")); 81 | assertTrue(packages[1].startsWith("net.openhft.affinity;") 82 | || packages[1].startsWith("net.openhft.affinity.impl;")); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /affinity-test/src/test/java/net/openhft/affinity/osgi/OSGiTestBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity.osgi; 19 | 20 | import org.ops4j.pax.exam.CoreOptions; 21 | import org.ops4j.pax.exam.Option; 22 | import org.ops4j.pax.exam.options.MavenArtifactProvisionOption; 23 | import org.osgi.framework.Bundle; 24 | import org.osgi.framework.BundleContext; 25 | 26 | import java.io.File; 27 | 28 | public class OSGiTestBase { 29 | 30 | public static Option workspaceBundle(String projectName) { 31 | String baseDir = System.getProperty("main.basedir"); 32 | String bundleDir = null; 33 | 34 | bundleDir = String.format("%s/%s/target/classes", baseDir, projectName); 35 | if (new File(bundleDir).exists()) { 36 | return CoreOptions.bundle(String.format("reference:file:%s", bundleDir)); 37 | } 38 | 39 | bundleDir = String.format("%s/../%s/target/classes", baseDir, projectName); 40 | if (new File(bundleDir).exists()) { 41 | return CoreOptions.bundle(String.format("reference:file:%s", bundleDir)); 42 | } 43 | 44 | return null; 45 | } 46 | 47 | public static MavenArtifactProvisionOption mavenBundleAsInProject(final String groupId, final String artifactId) { 48 | return CoreOptions.mavenBundle().groupId(groupId).artifactId(artifactId).versionAsInProject(); 49 | } 50 | 51 | public static Bundle findBundle(BundleContext context, String symbolicName) { 52 | Bundle[] bundles = context.getBundles(); 53 | for (Bundle bundle : bundles) { 54 | if (bundle != null) { 55 | if (bundle.getSymbolicName().equals(symbolicName)) { 56 | return bundle; 57 | } 58 | } 59 | } 60 | 61 | return null; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /affinity/src/main/c/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for C code 3 | # 4 | 5 | # C sources to compile 6 | 7 | TARGET_DIR := ../../../target/classes 8 | TARGET := $(TARGET_DIR)/libCEInternals.so 9 | 10 | WORKING_DIR := $(TARGET_DIR)/../jni 11 | 12 | JNI_OS := win32 13 | UNAME_S:= $(shell uname -s) 14 | ifeq ($(UNAME_S), Linux) 15 | JNI_OS := linux 16 | LRT := -lrt 17 | endif 18 | ifeq ($(UNAME_S), Darwin) 19 | JNI_OS := darwin 20 | endif 21 | 22 | JAVA_CLASSES = software.chronicle.enterprise.internals.impl.NativeAffinity net.openhft.ticker.impl.JNIClock 23 | 24 | JNI_STUBS := $(subst .,_,$(JAVA_CLASSES)) 25 | JNI_SOURCES := $(patsubst %,%.cpp,$(JNI_STUBS)) 26 | 27 | JAVA_BUILD_DIR := $(TARGET_DIR) 28 | 29 | JAVA_HOME ?= /usr/java/default 30 | JAVA_LIB := $(JAVA_HOME)/jre/lib 31 | JVM_SHARED_LIBS := -L"$(JAVA_LIB)/amd64/server" -L"$(JAVA_LIB)/i386/server" -L"$(JAVA_LIB)/amd64/jrockit" -L"$(JAVA_LIB)/i386/jrockit" -L"$(JAVA_LIB)/ppc64le/server" -L"$(JAVA_LIB)/ppc64le/jrockit" -L"$(JAVA_HOME)/lib/server" 32 | 33 | CXX=g++ 34 | INCLUDES := -I"$(JAVA_HOME)/include" -I"$(JAVA_HOME)/include/$(JNI_OS)" -I"$(WORKING_DIR)" 35 | 36 | # classpath for javah 37 | ifdef CLASSPATH 38 | JAVAH_CLASSPATH = $(JAVA_BUILD_DIR):$(CLASSPATH) 39 | else 40 | JAVAH_CLASSPATH = $(JAVA_BUILD_DIR) 41 | endif 42 | 43 | .PHONY : clean 44 | 45 | all: $(TARGET) 46 | 47 | $(TARGET): $(JNI_SOURCES) 48 | $(CXX) -O3 -Wall -shared -fPIC $(JVM_SHARED_LIBS) $(LRT) $(INCLUDES) $(JNI_SOURCES) -o $(TARGET) 49 | 50 | clean: 51 | rm $(TARGET) 52 | -------------------------------------------------------------------------------- /affinity/src/main/c/net_openhft_ticker_impl_JNIClock.cpp: -------------------------------------------------------------------------------- 1 | /* vim: syntax=cpp 2 | * Copyright 2015-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _GNU_SOURCE 18 | #define _GNU_SOURCE 19 | #endif 20 | 21 | #include 22 | #include "net_openhft_ticker_impl_JNIClock.h" 23 | 24 | #if defined(__i386__) 25 | static __inline__ unsigned long long rdtsc(void) { 26 | unsigned long long int x; 27 | __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x)); 28 | return x; 29 | } 30 | 31 | #elif defined(__x86_64__) 32 | static __inline__ unsigned long long rdtsc(void) { 33 | unsigned hi, lo; 34 | __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); 35 | return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 ); 36 | } 37 | 38 | #elif defined(__MIPS_32__) 39 | #define rdtsc(dest) \ 40 | _ _asm_ _ _ _volatile_ _("mfc0 %0,$9; nop" : "=r" (dest)) 41 | 42 | #elif defined(__MIPS_SGI__) 43 | #include 44 | 45 | static __inline__ unsigned long long rdtsc (void) { 46 | struct timespec tp; 47 | clock_gettime (CLOCK_SGI_CYCLE, &tp); 48 | return (unsigned long long)(tp.tv_sec * (unsigned long long)1000000000) + (unsigned long long)tp.tv_nsec; 49 | } 50 | #elif defined(__PPC64__) 51 | unsigned long long rdtsc(){ 52 | unsigned long long rval; 53 | __asm__ __volatile__("mfspr %%r3, 268": "=r" (rval)); 54 | return rval; 55 | } 56 | #elif defined(__aarch64__) // ARMv8-A (AArch64) 57 | #include 58 | inline uint64_t rdtsc() { 59 | uint64_t virtual_timer_value; 60 | asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value)); 61 | return virtual_timer_value; 62 | } 63 | #elif defined(__ARM_ARCH) && (__ARM_ARCH >= 7) // ARMv7-A (32-bit) 64 | #include 65 | inline uint64_t rdtsc() { 66 | struct timespec ts; 67 | clock_gettime(CLOCK_MONOTONIC, &ts); 68 | return (uint64_t)ts.tv_sec * 1000000000ULL + (uint64_t)ts.tv_nsec; 69 | } 70 | #elif defined(__APPLE__) 71 | #include 72 | inline uint64_t rdtsc() { 73 | return mach_absolute_time(); 74 | } 75 | #elif defined(_MSC_VER) 76 | #include 77 | inline uint64_t rdtsc() { 78 | return __rdtsc(); 79 | } 80 | #endif 81 | 82 | /* 83 | * Class: net_openhft_clock_impl_JNIClock 84 | * Method: rdtsc0 85 | * Signature: ()J 86 | */ 87 | JNIEXPORT jlong JNICALL Java_net_openhft_ticker_impl_JNIClock_rdtsc0 88 | (JNIEnv *env, jclass c) { 89 | return (jlong) rdtsc(); 90 | } 91 | -------------------------------------------------------------------------------- /affinity/src/main/c/software_chronicle_enterprise_internals_impl_NativeAffinity.cpp: -------------------------------------------------------------------------------- 1 | /* vim: syntax=cpp 2 | * Copyright 2011-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _GNU_SOURCE 18 | #define _GNU_SOURCE 19 | #endif 20 | 21 | #include 22 | #ifdef __linux__ 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #endif 29 | #include 30 | #include "software_chronicle_enterprise_internals_impl_NativeAffinity.h" 31 | 32 | /* 33 | * Class: software_chronicle_enterprise_internals_impl_NativeAffinity 34 | * Method: getAffinity0 35 | * Signature: ()J 36 | */ 37 | JNIEXPORT jbyteArray JNICALL Java_software_chronicle_enterprise_internals_impl_NativeAffinity_getAffinity0 38 | (JNIEnv *env, jclass c) 39 | { 40 | #ifdef __linux__ 41 | // The default size of the structure supports 1024 CPUs, should be enough 42 | // for now In the future we can use dynamic sets, which can support more 43 | // CPUs, given OS can handle them as well 44 | cpu_set_t mask; 45 | const size_t size = sizeof(mask); 46 | 47 | int res = sched_getaffinity(0, size, &mask); 48 | if (res < 0) 49 | { 50 | return NULL; 51 | } 52 | 53 | jbyteArray ret = env->NewByteArray(size); 54 | jbyte* bytes = env->GetByteArrayElements(ret, 0); 55 | memcpy(bytes, &mask, size); 56 | env->SetByteArrayRegion(ret, 0, size, bytes); 57 | 58 | return ret; 59 | #else 60 | throw std::runtime_error("Not supported"); 61 | #endif 62 | } 63 | 64 | /* 65 | * Class: software_chronicle_enterprise_internals_NativeAffinity 66 | * Method: setAffinity0 67 | * Signature: (J)V 68 | */ 69 | JNIEXPORT void JNICALL Java_software_chronicle_enterprise_internals_impl_NativeAffinity_setAffinity0 70 | (JNIEnv *env, jclass c, jbyteArray affinity) 71 | { 72 | #ifdef __linux__ 73 | cpu_set_t mask; 74 | const size_t size = sizeof(mask); 75 | CPU_ZERO(&mask); 76 | 77 | jbyte* bytes = env->GetByteArrayElements(affinity, 0); 78 | memcpy(&mask, bytes, size); 79 | 80 | sched_setaffinity(0, size, &mask); 81 | #else 82 | throw std::runtime_error("Not supported"); 83 | #endif 84 | } 85 | 86 | /* 87 | * Class: software_chronicle_enterprise_internals_impl_NativeAffinity 88 | * Method: getProcessId0 89 | * Signature: ()I 90 | */ 91 | JNIEXPORT jint JNICALL Java_software_chronicle_enterprise_internals_impl_NativeAffinity_getProcessId0 92 | (JNIEnv *env, jclass c) { 93 | #ifndef __linux__ 94 | throw std::runtime_error("Not supported"); 95 | #else 96 | 97 | return (jint) getpid(); 98 | #endif 99 | } 100 | 101 | /* 102 | * Class: software_chronicle_enterprise_internals_impl_NativeAffinity 103 | * Method: getThreadId0 104 | * Signature: ()I 105 | */ 106 | JNIEXPORT jint JNICALL Java_software_chronicle_enterprise_internals_impl_NativeAffinity_getThreadId0 107 | (JNIEnv *env, jclass c) { 108 | #ifndef __linux__ 109 | throw std::runtime_error("Not supported"); 110 | #else 111 | 112 | return (jint) (pid_t) syscall (SYS_gettid); 113 | #endif 114 | } 115 | 116 | /* 117 | * Class: software_chronicle_enterprise_internals_impl_NativeAffinity 118 | * Method: getCpu0 119 | * Signature: ()I 120 | */ 121 | JNIEXPORT jint JNICALL Java_software_chronicle_enterprise_internals_impl_NativeAffinity_getCpu0 122 | (JNIEnv *env, jclass c) { 123 | #ifndef __linux__ 124 | throw std::runtime_error("Not supported"); 125 | #else 126 | 127 | return (jint) sched_getcpu(); 128 | #endif 129 | } 130 | 131 | -------------------------------------------------------------------------------- /affinity/src/main/c/software_chronicle_enterprise_internals_impl_NativeAffinity_MacOSX.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include "software_chronicle_enterprise_internals_impl_NativeAffinity.h" 21 | 22 | /* 23 | * Class: software_chronicle_enterprise_internals_impl_NativeAffinity 24 | * Method: getAffinity0 25 | * Signature: ()J 26 | */ 27 | JNIEXPORT jlong JNICALL Java_software_chronicle_enterprise_internals_impl_NativeAffinity_getAffinity0 28 | (JNIEnv *env, jclass c) { 29 | 30 | thread_port_t threadport = pthread_mach_thread_np(pthread_self()); 31 | 32 | struct thread_enterprise_internals_policy policy; 33 | policy.affinity_tag = 0; 34 | mach_msg_type_number_t count = THREAD_AFFINITY_POLICY_COUNT; 35 | boolean_t get_default = FALSE; 36 | 37 | if ((thread_policy_get(threadport, 38 | THREAD_AFFINITY_POLICY, (thread_policy_t)&policy, 39 | &count, &get_default)) != KERN_SUCCESS) { 40 | return ~0LL; 41 | } 42 | 43 | return (jlong) policy.affinity_tag; 44 | } 45 | 46 | /* 47 | * Class: software_chronicle_enterprise_internals_NativeAffinity 48 | * Method: setAffinity0 49 | * Signature: (J)V 50 | */ 51 | JNIEXPORT void JNICALL Java_software_chronicle_enterprise_internals_impl_NativeAffinity_setAffinity0 52 | (JNIEnv *env, jclass c, jlong affinity) { 53 | 54 | thread_port_t threadport = pthread_mach_thread_np(pthread_self()); 55 | 56 | struct thread_enterprise_internals_policy policy; 57 | policy.affinity_tag = affinity; 58 | 59 | int rc = thread_policy_set(threadport, 60 | THREAD_AFFINITY_POLICY, (thread_policy_t)&policy, 61 | THREAD_AFFINITY_POLICY_COUNT); 62 | if (rc != KERN_SUCCESS) { 63 | jclass ex = (*env)->FindClass(env, "java/lang/RuntimeException"); 64 | char msg[100]; 65 | sprintf(msg, "Bad return value from thread_policy_set: %d", rc); 66 | (*env)->ThrowNew(env, ex, msg); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/Affinity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity; 19 | 20 | import com.sun.jna.Native; 21 | import net.openhft.affinity.impl.*; 22 | import org.jetbrains.annotations.NotNull; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | 26 | import java.io.PrintWriter; 27 | import java.io.StringWriter; 28 | import java.lang.reflect.Field; 29 | import java.util.BitSet; 30 | 31 | /** 32 | * Library to wrap low level JNI or JNA calls. Can be called without needing to know the actual 33 | * implementation used. 34 | * 35 | * @author peter.lawrey 36 | */ 37 | public enum Affinity { 38 | ; // none 39 | static final Logger LOGGER = LoggerFactory.getLogger(Affinity.class); 40 | @NotNull 41 | private static final IAffinity AFFINITY_IMPL; 42 | private static Boolean JNAAvailable; 43 | 44 | static { 45 | String osName = System.getProperty("os.name"); 46 | if (osName.contains("Win") && isWindowsJNAAffinityUsable()) { 47 | LOGGER.trace("Using Windows JNA-based affinity control implementation"); 48 | AFFINITY_IMPL = WindowsJNAAffinity.INSTANCE; 49 | 50 | } else if (osName.contains("x")) { 51 | /*if (osName.startsWith("Linux") && NativeAffinity.LOADED) { 52 | LOGGER.trace("Using Linux JNI-based affinity control implementation"); 53 | AFFINITY_IMPL = NativeAffinity.INSTANCE; 54 | } else*/ 55 | if (osName.startsWith("Linux") && isLinuxJNAAffinityUsable()) { 56 | LOGGER.trace("Using Linux JNA-based affinity control implementation"); 57 | AFFINITY_IMPL = LinuxJNAAffinity.INSTANCE; 58 | 59 | } else if (isPosixJNAAffinityUsable()) { 60 | LOGGER.trace("Using Posix JNA-based affinity control implementation"); 61 | AFFINITY_IMPL = PosixJNAAffinity.INSTANCE; 62 | 63 | } else { 64 | LOGGER.info("Using dummy affinity control implementation"); 65 | AFFINITY_IMPL = NullAffinity.INSTANCE; 66 | } 67 | } else if (osName.contains("Mac") && isMacJNAAffinityUsable()) { 68 | LOGGER.trace("Using MAC OSX JNA-based thread id implementation"); 69 | AFFINITY_IMPL = OSXJNAAffinity.INSTANCE; 70 | 71 | } else if (osName.contains("SunOS") && isSolarisJNAAffinityUsable()) { 72 | LOGGER.trace("Using Solaris JNA-based thread id implementation"); 73 | AFFINITY_IMPL = SolarisJNAAffinity.INSTANCE; 74 | 75 | } else { 76 | LOGGER.info("Using dummy affinity control implementation"); 77 | AFFINITY_IMPL = NullAffinity.INSTANCE; 78 | } 79 | } 80 | 81 | public static IAffinity getAffinityImpl() { 82 | return AFFINITY_IMPL; 83 | } 84 | 85 | private static boolean isWindowsJNAAffinityUsable() { 86 | if (isJNAAvailable()) { 87 | try { 88 | return WindowsJNAAffinity.LOADED; 89 | } catch (Throwable t) { 90 | logThrowable(t, "Windows JNA-based affinity not usable because it failed to load!"); 91 | return false; 92 | } 93 | } else { 94 | LOGGER.warn("Windows JNA-based affinity not usable due to JNA not being available!"); 95 | return false; 96 | } 97 | } 98 | 99 | private static boolean isPosixJNAAffinityUsable() { 100 | if (isJNAAvailable()) { 101 | try { 102 | return PosixJNAAffinity.LOADED; 103 | } catch (Throwable t) { 104 | logThrowable(t, "Posix JNA-based affinity not usable because it failed to load!"); 105 | return false; 106 | } 107 | } else { 108 | LOGGER.warn("Posix JNA-based affinity not usable due to JNA not being available!"); 109 | return false; 110 | } 111 | } 112 | 113 | private static boolean isLinuxJNAAffinityUsable() { 114 | if (isJNAAvailable()) { 115 | try { 116 | return LinuxJNAAffinity.LOADED; 117 | } catch (Throwable t) { 118 | logThrowable(t, "Linux JNA-based affinity not usable because it failed to load!"); 119 | return false; 120 | } 121 | } else { 122 | LOGGER.warn("Linux JNA-based affinity not usable due to JNA not being available!"); 123 | return false; 124 | } 125 | } 126 | 127 | private static boolean isMacJNAAffinityUsable() { 128 | if (isJNAAvailable()) { 129 | return true; 130 | 131 | } else { 132 | LOGGER.warn("MAC OSX JNA-based affinity not usable due to JNA not being available!"); 133 | return false; 134 | } 135 | } 136 | 137 | private static boolean isSolarisJNAAffinityUsable() { 138 | if (isJNAAvailable()) { 139 | return true; 140 | 141 | } else { 142 | LOGGER.warn("Solaris JNA-based affinity not usable due to JNA not being available!"); 143 | return false; 144 | } 145 | } 146 | 147 | private static void logThrowable(Throwable t, String description) { 148 | StringWriter sw = new StringWriter(); 149 | sw.append(description); 150 | sw.append(" Reason: "); 151 | t.printStackTrace(new PrintWriter(sw)); 152 | LOGGER.warn(sw.toString()); 153 | } 154 | 155 | public static BitSet getAffinity() { 156 | return AFFINITY_IMPL.getAffinity(); 157 | } 158 | 159 | public static void setAffinity(final BitSet affinity) { 160 | AFFINITY_IMPL.setAffinity(affinity); 161 | } 162 | 163 | public static void setAffinity(int cpu) { 164 | BitSet affinity = new BitSet(Runtime.getRuntime().availableProcessors()); 165 | affinity.set(cpu); 166 | setAffinity(affinity); 167 | } 168 | 169 | public static int getCpu() { 170 | return AFFINITY_IMPL.getCpu(); 171 | } 172 | 173 | public static int getThreadId() { 174 | return AFFINITY_IMPL.getThreadId(); 175 | } 176 | 177 | public static void setThreadId() { 178 | try { 179 | int threadId = Affinity.getThreadId(); 180 | final Field tid = Thread.class.getDeclaredField("tid"); 181 | tid.setAccessible(true); 182 | final Thread thread = Thread.currentThread(); 183 | tid.setLong(thread, threadId); 184 | Affinity.LOGGER.info("Set {} to thread id {}", thread.getName(), threadId); 185 | } catch (Exception e) { 186 | throw new IllegalStateException(e); 187 | } 188 | } 189 | 190 | public static boolean isJNAAvailable() { 191 | if (JNAAvailable == null) { 192 | int majorVersion = Integer.parseInt(Native.VERSION.split("\\.")[0]); 193 | if(majorVersion < 5) { 194 | LOGGER.warn("Affinity library requires JNA version >= 5"); 195 | JNAAvailable = false; 196 | } 197 | else { 198 | try { 199 | Class.forName("com.sun.jna.Platform"); 200 | JNAAvailable = true; 201 | } catch (ClassNotFoundException ignored) { 202 | JNAAvailable = false; 203 | } 204 | } 205 | } 206 | return JNAAvailable; 207 | } 208 | 209 | public static AffinityLock acquireLock() { 210 | return AffinityLock.acquireLock(); 211 | } 212 | 213 | public static AffinityLock acquireCore() { 214 | return AffinityLock.acquireCore(); 215 | } 216 | 217 | public static AffinityLock acquireLock(boolean bind) { 218 | return AffinityLock.acquireLock(bind); 219 | } 220 | 221 | public static AffinityLock acquireCore(boolean bind) { 222 | return AffinityLock.acquireCore(bind); 223 | } 224 | 225 | public static void resetToBaseAffinity() { 226 | Affinity.setAffinity(AffinityLock.BASE_AFFINITY); 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/AffinityStrategies.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity; 19 | 20 | /** 21 | * Pre-defined strategies for determining which thread to pick next. 22 | * 23 | * @author peter.lawrey 24 | */ 25 | public enum AffinityStrategies implements AffinityStrategy { 26 | 27 | /** 28 | * Any free cpu. 29 | */ 30 | ANY { 31 | @Override 32 | public boolean matches(int cpuId, int cpuId2) { 33 | return true; 34 | } 35 | }, 36 | /** 37 | * Must be a cpu on the same core. 38 | */ 39 | SAME_CORE { 40 | @Override 41 | public boolean matches(int cpuId, int cpuId2) { 42 | CpuLayout cpuLayout = AffinityLock.cpuLayout(); 43 | return cpuLayout.socketId(cpuId) == cpuLayout.socketId(cpuId2) && 44 | cpuLayout.coreId(cpuId) == cpuLayout.coreId(cpuId2); 45 | } 46 | }, 47 | /** 48 | * Must be a cpu on the same socket/chip but different core. 49 | */ 50 | SAME_SOCKET { 51 | @Override 52 | public boolean matches(int cpuId, int cpuId2) { 53 | CpuLayout cpuLayout = AffinityLock.cpuLayout(); 54 | return cpuLayout.socketId(cpuId) == cpuLayout.socketId(cpuId2) && 55 | cpuLayout.coreId(cpuId) != cpuLayout.coreId(cpuId2); 56 | } 57 | }, 58 | /** 59 | * Must be a cpu on any other core (or socket) 60 | */ 61 | DIFFERENT_CORE { 62 | @Override 63 | public boolean matches(int cpuId, int cpuId2) { 64 | CpuLayout cpuLayout = AffinityLock.cpuLayout(); 65 | return cpuLayout.socketId(cpuId) != cpuLayout.socketId(cpuId2) || 66 | cpuLayout.coreId(cpuId) != cpuLayout.coreId(cpuId2); 67 | } 68 | }, 69 | /** 70 | * Must be a cpu on any other socket. 71 | */ 72 | DIFFERENT_SOCKET { 73 | @Override 74 | public boolean matches(int cpuId, int cpuId2) { 75 | CpuLayout cpuLayout = AffinityLock.cpuLayout(); 76 | return cpuLayout.socketId(cpuId) != cpuLayout.socketId(cpuId2); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/AffinityStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity; 19 | 20 | /** 21 | * Allow you define a strategy for find the a cpu relative to another select cpu. 22 | * 23 | * @author peter.lawrey 24 | */ 25 | public interface AffinityStrategy { 26 | /** 27 | * @param cpuId to cpuId to compare 28 | * @param cpuId2 with a second cpuId 29 | * @return true if it matches the criteria. 30 | */ 31 | boolean matches(int cpuId, int cpuId2); 32 | } 33 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/AffinityThreadFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity; 19 | 20 | import org.jetbrains.annotations.NotNull; 21 | import org.jetbrains.annotations.Nullable; 22 | 23 | import java.util.concurrent.ThreadFactory; 24 | 25 | /** 26 | * This is a ThreadFactory which assigns threads based the strategies provided. 27 | *

28 | * If no strategies are provided AffinityStrategies.ANY is used. 29 | * 30 | * @author peter.lawrey 31 | */ 32 | public class AffinityThreadFactory implements ThreadFactory { 33 | private final String name; 34 | private final boolean daemon; 35 | @NotNull 36 | private final AffinityStrategy[] strategies; 37 | @Nullable 38 | private AffinityLock lastAffinityLock = null; 39 | private int id = 1; 40 | 41 | public AffinityThreadFactory(String name, AffinityStrategy... strategies) { 42 | this(name, true, strategies); 43 | } 44 | 45 | public AffinityThreadFactory(String name, boolean daemon, @NotNull AffinityStrategy... strategies) { 46 | this.name = name; 47 | this.daemon = daemon; 48 | this.strategies = strategies.length == 0 ? new AffinityStrategy[]{AffinityStrategies.ANY} : strategies; 49 | } 50 | 51 | @NotNull 52 | @Override 53 | public synchronized Thread newThread(@NotNull final Runnable r) { 54 | String name2 = id <= 1 ? name : (name + '-' + id); 55 | id++; 56 | Thread t = new Thread(new Runnable() { 57 | @Override 58 | public void run() { 59 | try (AffinityLock ignored = acquireLockBasedOnLast()) { 60 | assert ignored != null; 61 | r.run(); 62 | } 63 | } 64 | }, name2); 65 | t.setDaemon(daemon); 66 | return t; 67 | } 68 | 69 | private synchronized AffinityLock acquireLockBasedOnLast() { 70 | AffinityLock al = lastAffinityLock == null ? AffinityLock.acquireLock(false) : lastAffinityLock.acquireLock(strategies); 71 | al.bind(); 72 | if (al.cpuId() >= 0) 73 | lastAffinityLock = al; 74 | return al; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/BootClassPath.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity; 19 | 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | 23 | import java.io.IOException; 24 | import java.nio.file.*; 25 | import java.nio.file.attribute.BasicFileAttributes; 26 | import java.util.Collections; 27 | import java.util.Enumeration; 28 | import java.util.HashSet; 29 | import java.util.Set; 30 | import java.util.jar.JarEntry; 31 | import java.util.jar.JarFile; 32 | 33 | enum BootClassPath { 34 | INSTANCE; 35 | 36 | private final Set bootClassPathResources = Collections.unmodifiableSet(getResourcesOnBootClasspath()); 37 | 38 | private static Set getResourcesOnBootClasspath() { 39 | final Logger logger = LoggerFactory.getLogger(BootClassPath.class); 40 | final Set resources = new HashSet<>(); 41 | final String bootClassPath = System.getProperty("sun.boot.class.path", ""); 42 | logger.trace("Boot class-path is: {}", bootClassPath); 43 | 44 | final String pathSeparator = System.getProperty("path.separator"); 45 | logger.trace("Path separator is: '{}'", pathSeparator); 46 | 47 | final String[] pathElements = bootClassPath.split(pathSeparator); 48 | 49 | for (final String pathElement : pathElements) { 50 | resources.addAll(findResources(Paths.get(pathElement), logger)); 51 | } 52 | 53 | return resources; 54 | } 55 | 56 | private static Set findResources(final Path path, final Logger logger) { 57 | if (!Files.exists(path)) { 58 | return Collections.emptySet(); 59 | } 60 | 61 | if (Files.isDirectory(path)) { 62 | return findResourcesInDirectory(path, logger); 63 | } 64 | 65 | return findResourcesInJar(path, logger); 66 | } 67 | 68 | private static Set findResourcesInJar(final Path path, final Logger logger) { 69 | final Set jarResources = new HashSet<>(); 70 | try (final JarFile jarFile = new JarFile(path.toFile())) { 71 | final Enumeration entries = jarFile.entries(); 72 | while (entries.hasMoreElements()) { 73 | final JarEntry jarEntry = entries.nextElement(); 74 | if (jarEntry.getName().endsWith(".class")) { 75 | jarResources.add(jarEntry.getName()); 76 | } 77 | } 78 | } catch (IOException e) { 79 | logger.warn("Not a jar file: {}", path); 80 | } 81 | 82 | return jarResources; 83 | } 84 | 85 | private static Set findResourcesInDirectory(final Path path, final Logger logger) { 86 | final Set dirResources = new HashSet<>(); 87 | try { 88 | Files.walkFileTree(path, new SimpleFileVisitor() { 89 | @Override 90 | public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException { 91 | if (file.getFileName().toString().endsWith(".class")) { 92 | dirResources.add(path.relativize(file).toString()); 93 | } 94 | return super.visitFile(file, attrs); 95 | } 96 | }); 97 | } catch (IOException e) { 98 | logger.warn("Error walking dir: " + path, e); 99 | } 100 | 101 | return dirResources; 102 | } 103 | 104 | public final boolean has(String binaryClassName) { 105 | final String resourceClassName = binaryClassName.replace('.', '/').concat(".class"); 106 | return bootClassPathResources.contains(resourceClassName); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/CpuLayout.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity; 19 | 20 | /** 21 | * @author peter.lawrey 22 | */ 23 | public interface CpuLayout { 24 | /** 25 | * @return the number of cpus. 26 | */ 27 | int cpus(); 28 | 29 | int sockets(); 30 | 31 | int coresPerSocket(); 32 | 33 | int threadsPerCore(); 34 | 35 | /** 36 | * @param cpuId the logical processor number 37 | * @return which socket id this cpu is on. 38 | */ 39 | int socketId(int cpuId); 40 | 41 | /** 42 | * @param cpuId the logical processor number 43 | * @return which core on a socket this cpu is on. 44 | */ 45 | int coreId(int cpuId); 46 | 47 | /** 48 | * @param cpuId the logical processor number 49 | * @return which thread on a core this cpu is on. 50 | */ 51 | int threadId(int cpuId); 52 | } 53 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/IAffinity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity; 19 | 20 | import java.util.BitSet; 21 | 22 | /** 23 | * Implementation interface 24 | * 25 | * @author cheremin 26 | * @since 29.12.11, 20:14 27 | */ 28 | public interface IAffinity { 29 | /** 30 | * @return returns affinity mask for current thread, or null if unknown 31 | */ 32 | BitSet getAffinity(); 33 | 34 | /** 35 | * @param affinity sets affinity mask of current thread to specified value 36 | */ 37 | void setAffinity(final BitSet affinity); 38 | 39 | /** 40 | * @return the current cpu id, or -1 if unknown. 41 | */ 42 | int getCpu(); 43 | 44 | /** 45 | * @return the process id of the current process. 46 | */ 47 | int getProcessId(); 48 | 49 | /** 50 | * @return the thread id of the current thread or -1 is not available. 51 | */ 52 | int getThreadId(); 53 | } 54 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/LockCheck.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity; 19 | 20 | import net.openhft.affinity.lockchecker.FileLockBasedLockChecker; 21 | import net.openhft.affinity.lockchecker.LockChecker; 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | 25 | import java.io.File; 26 | import java.io.IOException; 27 | 28 | /** 29 | * @author Rob Austin. 30 | */ 31 | public enum LockCheck { 32 | ; // none 33 | 34 | private static final Logger LOGGER = LoggerFactory.getLogger(LockCheck.class); 35 | private static final String OS = System.getProperty("os.name").toLowerCase(); 36 | static final boolean IS_LINUX = OS.startsWith("linux"); 37 | private static final int EMPTY_PID = Integer.MIN_VALUE; 38 | 39 | private static final LockChecker lockChecker = FileLockBasedLockChecker.getInstance(); 40 | 41 | public static long getPID() { 42 | String processName = 43 | java.lang.management.ManagementFactory.getRuntimeMXBean().getName(); 44 | return Long.parseLong(processName.split("@")[0]); 45 | } 46 | 47 | static boolean canOSSupportOperation() { 48 | return IS_LINUX; 49 | } 50 | 51 | public static boolean isCpuFree(int cpu) { 52 | if (!canOSSupportOperation()) 53 | return true; 54 | 55 | return isLockFree(cpu); 56 | } 57 | 58 | static boolean replacePid(int cpu, long processID) throws IOException { 59 | return storePid(processID, cpu); 60 | } 61 | 62 | public static boolean isProcessRunning(long pid) { 63 | if (canOSSupportOperation()) 64 | return new File("/proc/" + pid).exists(); 65 | else 66 | throw new UnsupportedOperationException("this is only supported on LINUX"); 67 | } 68 | 69 | /** 70 | * stores the pid in a file, named by the core, the pid is written to the file with the date 71 | * below 72 | */ 73 | private synchronized static boolean storePid(long processID, int cpu) throws IOException { 74 | return lockChecker.obtainLock(cpu, Long.toString(processID)); 75 | } 76 | 77 | private synchronized static boolean isLockFree(int id) { 78 | return lockChecker.isLockFree(id); 79 | } 80 | 81 | public static int getProcessForCpu(int core) throws IOException { 82 | String meta = lockChecker.getMetaInfo(core); 83 | 84 | if (meta != null && !meta.isEmpty()) { 85 | try { 86 | return Integer.parseInt(meta); 87 | } catch (NumberFormatException e) { 88 | //nothing 89 | } 90 | } 91 | return EMPTY_PID; 92 | } 93 | 94 | static boolean updateCpu(int cpu) throws IOException { 95 | if (!canOSSupportOperation()) 96 | return true; 97 | return replacePid(cpu, getPID()); 98 | } 99 | 100 | public static void releaseLock(int cpu) { 101 | lockChecker.releaseLock(cpu); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/MicroJitterSampler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.openhft.affinity; 18 | 19 | import java.io.PrintStream; 20 | 21 | /** 22 | * User: peter.lawrey Date: 30/06/13 Time: 13:13 23 | */ 24 | public class MicroJitterSampler { 25 | 26 | private static final long[] DELAY = { 27 | 2 * 1000, 3 * 1000, 4 * 1000, 6 * 1000, 8 * 1000, 10 * 1000, 14 * 1000, 28 | 20 * 1000, 30 * 1000, 40 * 1000, 60 * 1000, 80 * 1000, 100 * 1000, 140 * 1000, 29 | 200 * 1000, 300 * 1000, 400 * 1000, 600 * 1000, 800 * 1000, 1000 * 1000, 30 | 2 * 1000 * 1000, 5 * 1000 * 1000, 10 * 1000 * 1000, 31 | 20 * 1000 * 1000, 50 * 1000 * 1000, 100 * 1000 * 1000 32 | }; 33 | private static final double UTIL = Double.parseDouble(System.getProperty("util", "50")); 34 | private static final boolean BUSYWAIT = Boolean.parseBoolean(System.getProperty("busywait", "false")); 35 | private static final String CPU = System.getProperty("cpu", "none"); 36 | 37 | private final int[] count = new int[DELAY.length]; 38 | private long totalTime = 0; 39 | 40 | private static void pause() throws InterruptedException { 41 | if (BUSYWAIT) { 42 | long now = System.nanoTime(); 43 | while (System.nanoTime() - now < 1_000_000) ; 44 | } else { 45 | Thread.sleep(1); 46 | } 47 | } 48 | 49 | public static void main(String... ignored) throws InterruptedException { 50 | MicroJitterSampler sampler = new MicroJitterSampler(); 51 | 52 | Thread t = new Thread(sampler::run); 53 | t.start(); 54 | t.join(); 55 | } 56 | 57 | private void once() throws InterruptedException { 58 | if (UTIL >= 100) { 59 | sample(30L * 1000 * 1000 * 1000); 60 | } else { 61 | long sampleLength = (long) ((1 / (1 - UTIL / 100) - 1) * 1000 * 1000); 62 | for (int i = 0; i < 30 * 1000; i += 2) { 63 | sample(sampleLength); 64 | //noinspection BusyWait 65 | pause(); 66 | } 67 | } 68 | } 69 | 70 | public void run() { 71 | try (final AffinityLock lock = AffinityLock.acquireLock(CPU)) { 72 | assert lock != null; 73 | boolean first = true; 74 | System.out.println("Warming up..."); 75 | while (!Thread.currentThread().isInterrupted()) { 76 | once(); 77 | 78 | if (first) { 79 | reset(); 80 | first = false; 81 | System.out.println("Warmup complete. Running jitter tests..."); 82 | continue; 83 | } 84 | 85 | print(System.out); 86 | } 87 | } catch (InterruptedException e) { 88 | Thread.currentThread().interrupt(); 89 | } 90 | } 91 | 92 | private static String asString(long timeNS) { 93 | return timeNS < 1000 ? timeNS + "ns" : 94 | timeNS < 1000000 ? timeNS / 1000 + "us" : 95 | timeNS < 1000000000 ? timeNS / 1000000 + "ms" : 96 | timeNS / 1000000000 + "sec"; 97 | } 98 | 99 | void reset() { 100 | for (int i = 0; i < DELAY.length; ++i) 101 | count[i] = 0; 102 | totalTime = 0; 103 | } 104 | 105 | void sample(long intervalNS) { 106 | long prev = System.nanoTime(); 107 | long end = prev + intervalNS; 108 | long now; 109 | do { 110 | now = System.nanoTime(); 111 | long time = now - prev; 112 | if (time >= DELAY[0]) { 113 | int i; 114 | for (i = 1; i < DELAY.length; i++) 115 | if (time < DELAY[i]) 116 | break; 117 | count[i - 1]++; 118 | } 119 | prev = now; 120 | } while (now < end); 121 | totalTime += intervalNS; 122 | } 123 | 124 | void print(PrintStream ps) { 125 | ps.println("After " + totalTime / 1000000000 + " seconds, the average per hour was"); 126 | for (int i = 0; i < DELAY.length; i++) { 127 | if (count[i] < 1) continue; 128 | long countPerHour = (long) Math.ceil(count[i] * 3600e9 / totalTime); 129 | ps.println(asString(DELAY[i]) + '\t' + countPerHour); 130 | } 131 | ps.println(); 132 | } 133 | } 134 | /* e.g. 135 | Ubuntu 20.04, Ryzen 5950X with an isolated CPU. (init 3) sudo cpupower -c {cpu} -g performance, run from command line 136 | After 3600 seconds, the average per hour was 137 | 2us 2571 138 | 3us 2304 139 | 4us 376 140 | 6us 1 141 | 10us 1 142 | 20us 1 143 | 30us 1 144 | 40us 2 145 | 60us 1 146 | 147 | Ubuntu 20.04, Ryzen 5950X with an isolated CPU. (init 5) sudo cpupower -c {cpu} -g performance, run from command line 148 | After 3600 seconds, the average per hour was 149 | 2us 2157 150 | 3us 3444 151 | 4us 3654 152 | 6us 135 153 | 8us 4 154 | 14us 1 155 | 20us 1 156 | 40us 2 157 | 60us 1 158 | 159 | Ubuntu 20.04, Ryzen 5950X with an isolated CPU. (init 5) sudo cpupower -c {cpu} -g performance, run from IntelliJ CE 160 | After 7200 seconds, the average per hour was 161 | 2us 2189 162 | 3us 3341 163 | 4us 2335 164 | 6us 191 165 | 8us 4 166 | 14us 1 167 | 20us 1 168 | 169 | Windows 10 i7-4770 laptop 170 | After 1845 seconds, the average per hour was 171 | 2us 2435969 172 | 3us 548812 173 | 4us 508041 174 | 6us 60320 175 | 8us 25374 176 | 10us 1832324 177 | 14us 2089216 178 | 20us 391901 179 | 30us 16063 180 | 40us 6440 181 | 60us 2617 182 | 80us 1487 183 | 100us 1241 184 | 140us 826 185 | 200us 2108 186 | 300us 601 187 | 400us 159 188 | 600us 129 189 | 800us 215 190 | 1ms 155 191 | 2ms 229 192 | 5ms 24 193 | 10ms 38 194 | 20ms 32 195 | 196 | On an Centos 7 machine with an isolated CPU. 197 | After 2145 seconds, the average per hour was 198 | 2us 781271 199 | 3us 1212123 200 | 4us 13504 201 | 6us 489 202 | 8us 2 203 | 10us 3032577 204 | 14us 17475 205 | 20us 628 206 | 30us 645 207 | 40us 1301 208 | 60us 1217 209 | 80us 1306 210 | 100us 1526 211 | 140us 22 212 | 213 | */ 214 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/impl/LinuxJNAAffinity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity.impl; 19 | 20 | import com.sun.jna.NativeLong; 21 | import com.sun.jna.Platform; 22 | import net.openhft.affinity.IAffinity; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | 26 | import java.util.BitSet; 27 | 28 | public enum LinuxJNAAffinity implements IAffinity { 29 | INSTANCE; 30 | public static final boolean LOADED; 31 | private static final Logger LOGGER = LoggerFactory.getLogger(LinuxJNAAffinity.class); 32 | private static final int PROCESS_ID; 33 | private static final int SYS_gettid = Platform.isPPC() ? 207 : Platform.is64Bit() ? 186 : 224; 34 | private static final Object[] NO_ARGS = {}; 35 | 36 | private static final String OS = System.getProperty("os.name").toLowerCase(); 37 | private static final boolean IS_LINUX = OS.startsWith("linux"); 38 | 39 | static { 40 | int pid = -1; 41 | try { 42 | pid = LinuxHelper.getpid(); 43 | } catch (NoClassDefFoundError | Exception ignored) { 44 | } 45 | PROCESS_ID = pid; 46 | } 47 | 48 | static { 49 | boolean loaded = false; 50 | try { 51 | INSTANCE.getAffinity(); 52 | loaded = true; 53 | } catch (NoClassDefFoundError | UnsatisfiedLinkError e) { 54 | if (IS_LINUX) 55 | LOGGER.warn("Unable to load jna library {}", e); 56 | } 57 | LOADED = loaded; 58 | } 59 | 60 | private final ThreadLocal THREAD_ID = new ThreadLocal<>(); 61 | 62 | @Override 63 | public BitSet getAffinity() { 64 | final LinuxHelper.cpu_set_t cpuset = LinuxHelper.sched_getaffinity(); 65 | 66 | BitSet ret = new BitSet(LinuxHelper.cpu_set_t.__CPU_SETSIZE); 67 | int i = 0; 68 | for (NativeLong nl : cpuset.__bits) { 69 | for (int j = 0; j < Long.SIZE; j++) 70 | ret.set(i++, ((nl.longValue() >>> j) & 1) != 0); 71 | } 72 | return ret; 73 | } 74 | 75 | @Override 76 | public void setAffinity(final BitSet affinity) { 77 | LinuxHelper.sched_setaffinity(affinity); 78 | } 79 | 80 | @Override 81 | public int getCpu() { 82 | return LinuxHelper.sched_getcpu(); 83 | } 84 | 85 | @Override 86 | public int getProcessId() { 87 | return PROCESS_ID; 88 | } 89 | 90 | @Override 91 | public int getThreadId() { 92 | Integer tid = THREAD_ID.get(); 93 | if (tid == null) 94 | THREAD_ID.set(tid = LinuxHelper.syscall(SYS_gettid, NO_ARGS)); 95 | return tid; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/impl/NoCpuLayout.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity.impl; 19 | 20 | import net.openhft.affinity.CpuLayout; 21 | 22 | /** 23 | * This assumes there is one socket with every cpu on a different core. 24 | * 25 | * @author peter.lawrey 26 | */ 27 | public class NoCpuLayout implements CpuLayout { 28 | private final int cpus; 29 | 30 | public NoCpuLayout(int cpus) { 31 | this.cpus = cpus; 32 | } 33 | 34 | @Override 35 | public int sockets() { 36 | return 1; 37 | } 38 | 39 | @Override 40 | public int coresPerSocket() { 41 | return cpus; 42 | } 43 | 44 | @Override 45 | public int threadsPerCore() { 46 | return 1; 47 | } 48 | 49 | public int cpus() { 50 | return cpus; 51 | } 52 | 53 | @Override 54 | public int socketId(int cpuId) { 55 | return 0; 56 | } 57 | 58 | @Override 59 | public int coreId(int cpuId) { 60 | return cpuId; 61 | } 62 | 63 | @Override 64 | public int threadId(int cpuId) { 65 | return 0; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/impl/NullAffinity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity.impl; 19 | 20 | import net.openhft.affinity.IAffinity; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | import java.lang.management.ManagementFactory; 25 | import java.util.BitSet; 26 | 27 | /** 28 | * @author peter.lawrey 29 | */ 30 | public enum NullAffinity implements IAffinity { 31 | INSTANCE; 32 | private static final Logger LOGGER = LoggerFactory.getLogger(NullAffinity.class); 33 | 34 | @Override 35 | public BitSet getAffinity() { 36 | return new BitSet(); 37 | } 38 | 39 | @Override 40 | public void setAffinity(final BitSet affinity) { 41 | LOGGER.trace("unable to set mask to {} as the JNIa nd JNA libraries and not loaded", Utilities.toHexString(affinity)); 42 | } 43 | 44 | @Override 45 | public int getCpu() { 46 | return -1; 47 | } 48 | 49 | @Override 50 | public int getProcessId() { 51 | final String name = ManagementFactory.getRuntimeMXBean().getName(); 52 | return Integer.parseInt(name.split("@")[0]); 53 | } 54 | 55 | @Override 56 | public int getThreadId() { 57 | throw new UnsupportedOperationException(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/impl/OSXJNAAffinity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity.impl; 19 | 20 | import com.sun.jna.LastErrorException; 21 | import com.sun.jna.Library; 22 | import com.sun.jna.Native; 23 | import net.openhft.affinity.IAffinity; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | 27 | import java.lang.management.ManagementFactory; 28 | import java.util.BitSet; 29 | 30 | /** 31 | * This is essentially the same as the NullAffinity implementation but with concrete 32 | * support for getThreadId(). 33 | * 34 | * @author daniel.shaya 35 | */ 36 | public enum OSXJNAAffinity implements IAffinity { 37 | INSTANCE; 38 | private static final Logger LOGGER = LoggerFactory.getLogger(OSXJNAAffinity.class); 39 | private final ThreadLocal THREAD_ID = new ThreadLocal<>(); 40 | 41 | @Override 42 | public BitSet getAffinity() { 43 | return new BitSet(); 44 | } 45 | 46 | @Override 47 | public void setAffinity(final BitSet affinity) { 48 | LOGGER.trace("unable to set mask to {} as the JNIa nd JNA libraries and not loaded", Utilities.toHexString(affinity)); 49 | } 50 | 51 | @Override 52 | public int getCpu() { 53 | return -1; 54 | } 55 | 56 | @Override 57 | public int getProcessId() { 58 | final String name = ManagementFactory.getRuntimeMXBean().getName(); 59 | return Integer.parseInt(name.split("@")[0]); 60 | } 61 | 62 | @Override 63 | public int getThreadId() { 64 | Integer tid = THREAD_ID.get(); 65 | if (tid == null) { 66 | tid = CLibrary.INSTANCE.pthread_self(); 67 | //The tid assumed to be an unsigned 24 bit, see net.openhft.lang.Jvm.getMaxPid() 68 | tid = tid & 0xFFFFFF; 69 | THREAD_ID.set(tid); 70 | } 71 | return tid; 72 | } 73 | 74 | interface CLibrary extends Library { 75 | CLibrary INSTANCE = Native.load("libpthread.dylib", CLibrary.class); 76 | 77 | int pthread_self() throws LastErrorException; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/impl/PosixJNAAffinity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity.impl; 19 | 20 | import com.sun.jna.*; 21 | import com.sun.jna.ptr.IntByReference; 22 | import com.sun.jna.ptr.PointerByReference; 23 | import net.openhft.affinity.IAffinity; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | 27 | import java.nio.ByteBuffer; 28 | import java.util.Arrays; 29 | import java.util.BitSet; 30 | 31 | /** 32 | * Implementation of {@link IAffinity} based on JNA call of 33 | * sched_setaffinity(3)/sched_getaffinity(3) from 'c' library. Applicable for most 34 | * linux/unix platforms 35 | *

36 | * TODO Support assignment to core 64 and above 37 | * 38 | * @author peter.lawrey 39 | * @author BegemoT 40 | */ 41 | public enum PosixJNAAffinity implements IAffinity { 42 | INSTANCE; 43 | public static final boolean LOADED; 44 | private static final Logger LOGGER = LoggerFactory.getLogger(PosixJNAAffinity.class); 45 | private static final String LIBRARY_NAME = Platform.isWindows() ? "msvcrt" : "c"; 46 | private static final int PROCESS_ID; 47 | private static final int SYS_gettid = Utilities.is64Bit() ? 186 : 224; 48 | private static final Object[] NO_ARGS = {}; 49 | 50 | static { 51 | int processId; 52 | try { 53 | processId = CLibrary.INSTANCE.getpid(); 54 | } catch (Exception ignored) { 55 | processId = -1; 56 | } 57 | PROCESS_ID = processId; 58 | } 59 | 60 | static { 61 | boolean loaded = false; 62 | try { 63 | INSTANCE.getAffinity(); 64 | loaded = true; 65 | } catch (UnsatisfiedLinkError e) { 66 | LOGGER.warn("Unable to load jna library {}", e); 67 | } 68 | LOADED = loaded; 69 | } 70 | 71 | private final ThreadLocal THREAD_ID = new ThreadLocal<>(); 72 | 73 | @Override 74 | public BitSet getAffinity() { 75 | final CLibrary lib = CLibrary.INSTANCE; 76 | final int procs = Runtime.getRuntime().availableProcessors(); 77 | 78 | final int cpuSetSizeInLongs = (procs + 63) / 64; 79 | final int cpuSetSizeInBytes = cpuSetSizeInLongs * 8; 80 | final Memory cpusetArray = new Memory(cpuSetSizeInBytes); 81 | final PointerByReference cpuset = new PointerByReference(cpusetArray); 82 | try { 83 | final int ret = lib.sched_getaffinity(0, cpuSetSizeInBytes, cpuset); 84 | if (ret < 0) { 85 | throw new IllegalStateException("sched_getaffinity((" + cpuSetSizeInBytes + ") , &(" + cpusetArray + ") ) return " + ret); 86 | } 87 | ByteBuffer buff = cpusetArray.getByteBuffer(0, cpuSetSizeInBytes); 88 | return BitSet.valueOf(buff.array()); 89 | } catch (LastErrorException e) { 90 | if (e.getErrorCode() != 22) { 91 | throw new IllegalStateException("sched_getaffinity((" + cpuSetSizeInBytes + ") , &(" + cpusetArray + ") ) errorNo=" + e.getErrorCode(), e); 92 | } 93 | } 94 | 95 | // fall back to the old method 96 | final IntByReference cpuset32 = new IntByReference(0); 97 | try { 98 | final int ret = lib.sched_getaffinity(0, Integer.SIZE / 8, cpuset32); 99 | if (ret < 0) { 100 | throw new IllegalStateException("sched_getaffinity((" + Integer.SIZE / 8 + ") , &(" + cpuset32 + ") ) return " + ret); 101 | } 102 | long[] longs = new long[1]; 103 | longs[0] = cpuset32.getValue() & 0xFFFFFFFFL; 104 | return BitSet.valueOf(longs); 105 | } catch (LastErrorException e) { 106 | throw new IllegalStateException("sched_getaffinity((" + Integer.SIZE / 8 + ") , &(" + cpuset32 + ") ) errorNo=" + e.getErrorCode(), e); 107 | } 108 | } 109 | 110 | @Override 111 | public void setAffinity(final BitSet affinity) { 112 | int procs = Runtime.getRuntime().availableProcessors(); 113 | if (affinity.isEmpty()) { 114 | throw new IllegalArgumentException("Cannot set zero affinity"); 115 | } 116 | 117 | final CLibrary lib = CLibrary.INSTANCE; 118 | byte[] buff = affinity.toByteArray(); 119 | final int cpuSetSizeInBytes = buff.length; 120 | final Memory cpusetArray = new Memory(cpuSetSizeInBytes); 121 | try { 122 | cpusetArray.write(0, buff, 0, buff.length); 123 | final int ret = lib.sched_setaffinity(0, cpuSetSizeInBytes, new PointerByReference(cpusetArray)); 124 | if (ret < 0) { 125 | throw new IllegalStateException("sched_setaffinity((" + cpuSetSizeInBytes + ") , &(" + affinity + ") ) return " + ret); 126 | } 127 | } catch (LastErrorException e) { 128 | if (e.getErrorCode() != 22 || !Arrays.equals(buff, cpusetArray.getByteArray(0, cpuSetSizeInBytes))) { 129 | throw new IllegalStateException("sched_setaffinity((" + cpuSetSizeInBytes + ") , &(" + affinity + ") ) errorNo=" + e.getErrorCode(), e); 130 | } 131 | } 132 | 133 | final int value = (int) affinity.toLongArray()[0]; 134 | if (value == 0) { 135 | throw new IllegalArgumentException("Cannot set zero affinity"); 136 | } 137 | final IntByReference cpuset32 = new IntByReference(0); 138 | cpuset32.setValue(value); 139 | try { 140 | final int ret = lib.sched_setaffinity(0, Integer.SIZE / 8, cpuset32); 141 | if (ret < 0) 142 | throw new IllegalStateException("sched_setaffinity((" + Integer.SIZE / 8 + ") , &(" + Integer.toHexString(cpuset32.getValue()) + ") ) return " + ret); 143 | } catch (LastErrorException e) { 144 | throw new IllegalStateException("sched_setaffinity((" + Integer.SIZE / 8 + ") , &(" + Integer.toHexString(cpuset32.getValue()) + ") ) errorNo=" + e.getErrorCode(), e); 145 | } 146 | } 147 | 148 | @Override 149 | public int getCpu() { 150 | final CLibrary lib = CLibrary.INSTANCE; 151 | try { 152 | final int ret = lib.sched_getcpu(); 153 | if (ret < 0) 154 | throw new IllegalStateException("sched_getcpu( ) return " + ret); 155 | return ret; 156 | } catch (LastErrorException e) { 157 | throw new IllegalStateException("sched_getcpu( ) errorNo=" + e.getErrorCode(), e); 158 | } catch (UnsatisfiedLinkError ule) { 159 | try { 160 | final IntByReference cpu = new IntByReference(); 161 | final IntByReference node = new IntByReference(); 162 | final int ret = lib.syscall(318, cpu, node, null); 163 | if (ret != 0) { 164 | throw new IllegalStateException("getcpu( ) return " + ret); 165 | } 166 | 167 | return cpu.getValue(); 168 | } catch (LastErrorException lee) { 169 | throw new IllegalStateException("getcpu( ) errorNo=" + lee.getErrorCode(), lee); 170 | } 171 | } 172 | } 173 | 174 | @Override 175 | public int getProcessId() { 176 | return PROCESS_ID; 177 | } 178 | 179 | @Override 180 | public int getThreadId() { 181 | if (Utilities.ISLINUX) { 182 | Integer tid = THREAD_ID.get(); 183 | if (tid == null) 184 | THREAD_ID.set(tid = CLibrary.INSTANCE.syscall(SYS_gettid, NO_ARGS)); 185 | return tid; 186 | } 187 | return -1; 188 | } 189 | 190 | /** 191 | * @author BegemoT 192 | */ 193 | interface CLibrary extends Library { 194 | CLibrary INSTANCE = Native.load(LIBRARY_NAME, CLibrary.class); 195 | 196 | int sched_setaffinity(final int pid, 197 | final int cpusetsize, 198 | final PointerType cpuset) throws LastErrorException; 199 | 200 | int sched_getaffinity(final int pid, 201 | final int cpusetsize, 202 | final PointerType cpuset) throws LastErrorException; 203 | 204 | int sched_getcpu() throws LastErrorException; 205 | 206 | int getcpu(final IntByReference cpu, 207 | final IntByReference node, 208 | final PointerType tcache) throws LastErrorException; 209 | 210 | int getpid() throws LastErrorException; 211 | 212 | int syscall(int number, Object... args) throws LastErrorException; 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/impl/SolarisJNAAffinity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity.impl; 19 | 20 | import com.sun.jna.LastErrorException; 21 | import com.sun.jna.Library; 22 | import com.sun.jna.Native; 23 | import net.openhft.affinity.IAffinity; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | 27 | import java.lang.management.ManagementFactory; 28 | import java.util.BitSet; 29 | 30 | /** 31 | * This is essentially the same as the NullAffinity implementation but with concrete 32 | * support for getThreadId(). 33 | * 34 | * @author daniel.shaya 35 | */ 36 | public enum SolarisJNAAffinity implements IAffinity { 37 | INSTANCE; 38 | private static final Logger LOGGER = LoggerFactory.getLogger(SolarisJNAAffinity.class); 39 | private final ThreadLocal THREAD_ID = new ThreadLocal<>(); 40 | 41 | @Override 42 | public BitSet getAffinity() { 43 | return new BitSet(); 44 | } 45 | 46 | @Override 47 | public void setAffinity(final BitSet affinity) { 48 | LOGGER.trace("unable to set mask to {} as the JNIa nd JNA libraries and not loaded", Utilities.toHexString(affinity)); 49 | } 50 | 51 | @Override 52 | public int getCpu() { 53 | return -1; 54 | } 55 | 56 | @Override 57 | public int getProcessId() { 58 | final String name = ManagementFactory.getRuntimeMXBean().getName(); 59 | return Integer.parseInt(name.split("@")[0]); 60 | } 61 | 62 | @Override 63 | public int getThreadId() { 64 | Integer tid = THREAD_ID.get(); 65 | if (tid == null) { 66 | tid = CLibrary.INSTANCE.pthread_self(); 67 | //The tid assumed to be an unsigned 24 bit, see net.openhft.lang.Jvm.getMaxPid() 68 | tid = tid & 0xFFFFFF; 69 | THREAD_ID.set(tid); 70 | } 71 | return tid; 72 | } 73 | 74 | interface CLibrary extends Library { 75 | CLibrary INSTANCE = Native.load("c", CLibrary.class); 76 | 77 | int pthread_self() throws LastErrorException; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/impl/Utilities.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity.impl; 19 | 20 | import java.io.ByteArrayOutputStream; 21 | import java.io.PrintWriter; 22 | import java.util.BitSet; 23 | 24 | /* 25 | * Created by andre on 20/06/15. 26 | */ 27 | public final class Utilities { 28 | public static final boolean ISLINUX = "Linux".equals(System.getProperty("os.name")); 29 | static final boolean IS64BIT = is64Bit0(); 30 | 31 | private Utilities() { 32 | throw new InstantiationError("Must not instantiate this class"); 33 | } 34 | 35 | /** 36 | * Creates a hexademical representation of the bit set 37 | * 38 | * @param set the bit set to convert 39 | * @return the hexademical string representation 40 | */ 41 | public static String toHexString(final BitSet set) { 42 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 43 | PrintWriter writer = new PrintWriter(out); 44 | final long[] longs = set.toLongArray(); 45 | for (long aLong : longs) { 46 | writer.write(Long.toHexString(aLong)); 47 | } 48 | writer.flush(); 49 | 50 | return new String(out.toByteArray(), java.nio.charset.StandardCharsets.UTF_8); 51 | } 52 | 53 | public static String toBinaryString(BitSet set) { 54 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 55 | PrintWriter writer = new PrintWriter(out); 56 | final long[] longs = set.toLongArray(); 57 | for (long aLong : longs) { 58 | writer.write(Long.toBinaryString(aLong)); 59 | } 60 | writer.flush(); 61 | 62 | return new String(out.toByteArray(), java.nio.charset.StandardCharsets.UTF_8); 63 | } 64 | 65 | public static boolean is64Bit() { 66 | return IS64BIT; 67 | } 68 | 69 | private static boolean is64Bit0() { 70 | String systemProp; 71 | systemProp = System.getProperty("com.ibm.vm.bitmode"); 72 | if (systemProp != null) { 73 | return "64".equals(systemProp); 74 | } 75 | systemProp = System.getProperty("sun.arch.data.model"); 76 | if (systemProp != null) { 77 | return "64".equals(systemProp); 78 | } 79 | systemProp = System.getProperty("java.vm.version"); 80 | return systemProp != null && systemProp.contains("_64"); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/impl/VanillaCpuLayout.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity.impl; 19 | 20 | import net.openhft.affinity.CpuLayout; 21 | import org.jetbrains.annotations.NotNull; 22 | import org.jetbrains.annotations.Nullable; 23 | import org.slf4j.LoggerFactory; 24 | 25 | import java.io.*; 26 | import java.util.*; 27 | 28 | import static java.lang.Integer.parseInt; 29 | 30 | /** 31 | * @author peter.lawrey 32 | */ 33 | public class VanillaCpuLayout implements CpuLayout { 34 | public static final int MAX_CPUS_SUPPORTED = 256; 35 | 36 | @NotNull 37 | private final List cpuDetails; 38 | private final int sockets; 39 | private final int coresPerSocket; 40 | private final int threadsPerCore; 41 | 42 | VanillaCpuLayout(@NotNull List cpuDetails) { 43 | this.cpuDetails = cpuDetails; 44 | SortedSet sockets = new TreeSet<>(), 45 | cores = new TreeSet<>(), 46 | threads = new TreeSet<>(); 47 | for (CpuInfo cpuDetail : cpuDetails) { 48 | sockets.add(cpuDetail.socketId); 49 | cores.add((cpuDetail.socketId << 16) + cpuDetail.coreId); 50 | threads.add(cpuDetail.threadId); 51 | } 52 | this.sockets = sockets.size(); 53 | this.coresPerSocket = cores.size() / sockets.size(); 54 | this.threadsPerCore = threads.size(); 55 | if (cpuDetails.size() != sockets() * coresPerSocket() * threadsPerCore()) { 56 | StringBuilder error = new StringBuilder(); 57 | error.append("cpuDetails.size= ").append(cpuDetails.size()) 58 | .append(" != sockets: ").append(sockets()) 59 | .append(" * coresPerSocket: ").append(coresPerSocket()) 60 | .append(" * threadsPerCore: ").append(threadsPerCore()).append('\n'); 61 | for (CpuInfo detail : cpuDetails) { 62 | error.append(detail).append('\n'); 63 | } 64 | LoggerFactory.getLogger(VanillaCpuLayout.class).warn(error.toString()); 65 | } 66 | } 67 | 68 | @NotNull 69 | public static VanillaCpuLayout fromProperties(String fileName) throws IOException { 70 | return fromProperties(openFile(fileName)); 71 | } 72 | 73 | @NotNull 74 | public static VanillaCpuLayout fromProperties(InputStream is) throws IOException { 75 | Properties prop = new Properties(); 76 | prop.load(is); 77 | return fromProperties(prop); 78 | } 79 | 80 | @NotNull 81 | public static VanillaCpuLayout fromProperties(@NotNull Properties prop) { 82 | List cpuDetails = new ArrayList<>(); 83 | for (int i = 0; i < MAX_CPUS_SUPPORTED; i++) { 84 | String line = prop.getProperty("" + i); 85 | if (line == null) break; 86 | String[] word = line.trim().split(" *, *"); 87 | CpuInfo details = new CpuInfo(parseInt(word[0]), 88 | parseInt(word[1]), parseInt(word[2])); 89 | cpuDetails.add(details); 90 | } 91 | return new VanillaCpuLayout(cpuDetails); 92 | } 93 | 94 | @NotNull 95 | public static VanillaCpuLayout fromCpuInfo() throws IOException { 96 | return fromCpuInfo("/proc/cpuinfo"); 97 | } 98 | 99 | @NotNull 100 | public static VanillaCpuLayout fromCpuInfo(String filename) throws IOException { 101 | return fromCpuInfo(openFile(filename)); 102 | } 103 | 104 | private static InputStream openFile(String filename) throws FileNotFoundException { 105 | try { 106 | return new FileInputStream(filename); 107 | } catch (FileNotFoundException e) { 108 | InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(filename); 109 | if (is == null) 110 | throw e; 111 | return is; 112 | } 113 | } 114 | 115 | @NotNull 116 | public static VanillaCpuLayout fromCpuInfo(InputStream is) throws IOException { 117 | BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8")); 118 | String line; 119 | List cpuDetails = new ArrayList<>(); 120 | CpuInfo details = new CpuInfo(); 121 | Map threadCount = new LinkedHashMap<>(); 122 | 123 | while ((line = br.readLine()) != null) { 124 | if (line.trim().isEmpty()) { 125 | String key = details.socketId + "," + details.coreId; 126 | Integer count = threadCount.get(key); 127 | if (count == null) 128 | threadCount.put(key, count = 1); 129 | else 130 | threadCount.put(key, count += 1); 131 | details.threadId = count - 1; 132 | cpuDetails.add(details); 133 | details = new CpuInfo(); 134 | details.coreId = cpuDetails.size(); 135 | continue; 136 | } 137 | String[] words = line.split("\\s*:\\s*", 2); 138 | if (words[0].equals("physical id")) 139 | details.socketId = parseInt(words[1]); 140 | else if (words[0].equals("core id")) 141 | details.coreId = parseInt(words[1]); 142 | } 143 | return new VanillaCpuLayout(cpuDetails); 144 | } 145 | 146 | @Override 147 | public int cpus() { 148 | return cpuDetails.size(); 149 | } 150 | 151 | public int sockets() { 152 | return sockets; 153 | } 154 | 155 | public int coresPerSocket() { 156 | return coresPerSocket; 157 | } 158 | 159 | @Override 160 | public int threadsPerCore() { 161 | return threadsPerCore; 162 | } 163 | 164 | @Override 165 | public int socketId(int cpuId) { 166 | return cpuDetails.get(cpuId).socketId; 167 | } 168 | 169 | @Override 170 | public int coreId(int cpuId) { 171 | return cpuDetails.get(cpuId).coreId; 172 | } 173 | 174 | @Override 175 | public int threadId(int cpuId) { 176 | return cpuDetails.get(cpuId).threadId; 177 | } 178 | 179 | @NotNull 180 | @Override 181 | public String toString() { 182 | StringBuilder sb = new StringBuilder(); 183 | for (int i = 0, cpuDetailsSize = cpuDetails.size(); i < cpuDetailsSize; i++) { 184 | CpuInfo cpuDetail = cpuDetails.get(i); 185 | sb.append(i).append(": ").append(cpuDetail).append('\n'); 186 | } 187 | return sb.toString(); 188 | } 189 | 190 | @Override 191 | public boolean equals(@Nullable Object o) { 192 | if (this == o) return true; 193 | if (o == null || getClass() != o.getClass()) return false; 194 | 195 | VanillaCpuLayout that = (VanillaCpuLayout) o; 196 | 197 | if (coresPerSocket != that.coresPerSocket) return false; 198 | if (sockets != that.sockets) return false; 199 | if (threadsPerCore != that.threadsPerCore) return false; 200 | return cpuDetails.equals(that.cpuDetails); 201 | 202 | } 203 | 204 | @Override 205 | public int hashCode() { 206 | int result = cpuDetails.hashCode(); 207 | result = 31 * result + sockets; 208 | result = 31 * result + coresPerSocket; 209 | result = 31 * result + threadsPerCore; 210 | return result; 211 | } 212 | 213 | static class CpuInfo { 214 | int socketId, coreId, threadId; 215 | 216 | CpuInfo() { 217 | } 218 | 219 | CpuInfo(int socketId, int coreId, int threadId) { 220 | this.socketId = socketId; 221 | this.coreId = coreId; 222 | this.threadId = threadId; 223 | } 224 | 225 | @NotNull 226 | @Override 227 | public String toString() { 228 | return "CpuInfo{" + 229 | "socketId=" + socketId + 230 | ", coreId=" + coreId + 231 | ", threadId=" + threadId + 232 | '}'; 233 | } 234 | 235 | @Override 236 | public boolean equals(@Nullable Object o) { 237 | if (this == o) return true; 238 | if (o == null || getClass() != o.getClass()) return false; 239 | 240 | CpuInfo cpuInfo = (CpuInfo) o; 241 | 242 | if (coreId != cpuInfo.coreId) return false; 243 | if (socketId != cpuInfo.socketId) return false; 244 | return threadId == cpuInfo.threadId; 245 | 246 | } 247 | 248 | @Override 249 | public int hashCode() { 250 | int result = socketId; 251 | result = 31 * result + coreId; 252 | result = 31 * result + threadId; 253 | return result; 254 | } 255 | } 256 | } 257 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/impl/VersionHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity.impl; 19 | 20 | public class VersionHelper { 21 | private static final String DELIM = "."; 22 | private final int major; 23 | private final int minor; 24 | private final int release; 25 | 26 | public VersionHelper(int major_, int minor_, int release_) { 27 | major = major_; 28 | minor = minor_; 29 | release = release_; 30 | } 31 | 32 | public VersionHelper(String ver) { 33 | if (ver != null && (ver = ver.trim()).length() > 0) { 34 | final String[] parts = ver.split("\\."); 35 | major = parts.length > 0 ? Integer.parseInt(parts[0]) : 0; 36 | minor = parts.length > 1 ? Integer.parseInt(parts[1]) : 0; 37 | release = parts.length > 2 ? Integer.parseInt(parts[2]) : 0; 38 | 39 | } else { 40 | major = minor = release = 0; 41 | } 42 | } 43 | 44 | public String toString() { 45 | return major + DELIM + minor + DELIM + release; 46 | } 47 | 48 | public boolean equals(Object o) { 49 | if (o != null && (o instanceof VersionHelper)) { 50 | VersionHelper ver = (VersionHelper) o; 51 | return this.major == ver.major 52 | && this.minor == ver.minor 53 | && this.release == ver.release; 54 | 55 | } else { 56 | return false; 57 | } 58 | } 59 | 60 | public int hashCode() { 61 | return (major << 16) | (minor << 8) | release; 62 | } 63 | 64 | @SuppressWarnings("unused") 65 | public boolean majorMinorEquals(final VersionHelper ver) { 66 | return ver != null 67 | && this.major == ver.major 68 | && this.minor == ver.minor; 69 | } 70 | 71 | public boolean isSameOrNewer(final VersionHelper ver) { 72 | return ver != null 73 | && (this.major > ver.major 74 | || this.major == ver.major 75 | && (this.minor > ver.minor 76 | || this.minor == ver.minor 77 | && this.release >= ver.release)); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/impl/WindowsJNAAffinity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity.impl; 19 | 20 | import com.sun.jna.*; 21 | import com.sun.jna.platform.win32.Kernel32; 22 | import com.sun.jna.platform.win32.WinDef; 23 | import com.sun.jna.platform.win32.WinNT; 24 | import com.sun.jna.ptr.LongByReference; 25 | import net.openhft.affinity.IAffinity; 26 | import org.jetbrains.annotations.Nullable; 27 | import org.slf4j.Logger; 28 | import org.slf4j.LoggerFactory; 29 | 30 | import java.util.BitSet; 31 | 32 | /** 33 | * Implementation of {@link net.openhft.affinity.IAffinity} based on JNA call of 34 | * sched_SetThreadAffinityMask/GetProcessAffinityMask from Windows 'kernel32' library. Applicable for 35 | * most windows platforms 36 | *

* 37 | * 38 | * @author andre.monteiro 39 | */ 40 | public enum WindowsJNAAffinity implements IAffinity { 41 | INSTANCE; 42 | public static final boolean LOADED; 43 | private static final Logger LOGGER = LoggerFactory.getLogger(WindowsJNAAffinity.class); 44 | private static final ThreadLocal currentAffinity = new ThreadLocal<>(); 45 | 46 | static { 47 | boolean loaded = false; 48 | try { 49 | INSTANCE.getAffinity(); 50 | loaded = true; 51 | } catch (UnsatisfiedLinkError e) { 52 | LOGGER.warn("Unable to load jna library", e); 53 | } 54 | LOADED = loaded; 55 | } 56 | 57 | private final ThreadLocal THREAD_ID = new ThreadLocal<>(); 58 | 59 | @Override 60 | public BitSet getAffinity() { 61 | BitSet bitSet = currentAffinity.get(); 62 | if (bitSet != null) 63 | return bitSet; 64 | BitSet longs = getAffinity0(); 65 | return longs != null ? longs : new BitSet(); 66 | } 67 | 68 | @Override 69 | public void setAffinity(final BitSet affinity) { 70 | final CLibrary lib = CLibrary.INSTANCE; 71 | 72 | WinDef.DWORD aff; 73 | long[] longs = affinity.toLongArray(); 74 | switch (longs.length) { 75 | case 0: 76 | aff = new WinDef.DWORD(0); 77 | break; 78 | case 1: 79 | aff = new WinDef.DWORD(longs[0]); 80 | break; 81 | default: 82 | throw new IllegalArgumentException("Windows API does not support more than 64 CPUs for thread affinity"); 83 | } 84 | 85 | int pid = getTid(); 86 | try { 87 | lib.SetThreadAffinityMask(handle(pid), aff); 88 | } catch (LastErrorException e) { 89 | throw new IllegalStateException("SetThreadAffinityMask((" + pid + ") , &(" + affinity + ") ) errorNo=" + e.getErrorCode(), e); 90 | } 91 | BitSet affinity2 = getAffinity0(); 92 | if (!affinity2.equals(affinity)) { 93 | LoggerFactory.getLogger(WindowsJNAAffinity.class).warn("Tried to set affinity to " + affinity + " but was " + affinity2 + " you may have insufficient access rights"); 94 | } 95 | currentAffinity.set((BitSet) affinity.clone()); 96 | } 97 | 98 | @Nullable 99 | private BitSet getAffinity0() { 100 | final CLibrary lib = CLibrary.INSTANCE; 101 | final LongByReference cpuset1 = new LongByReference(0); 102 | final LongByReference cpuset2 = new LongByReference(0); 103 | try { 104 | 105 | final int ret = lib.GetProcessAffinityMask(handle(-1), cpuset1, cpuset2); 106 | // Successful result is positive, according to the docs 107 | // https://msdn.microsoft.com/en-us/library/windows/desktop/ms683213%28v=vs.85%29.aspx 108 | if (ret <= 0) { 109 | throw new IllegalStateException("GetProcessAffinityMask(( -1 ), &(" + cpuset1 + "), &(" + cpuset2 + ") ) return " + ret); 110 | } 111 | 112 | long[] longs = new long[1]; 113 | longs[0] = cpuset1.getValue(); 114 | return BitSet.valueOf(longs); 115 | } catch (Exception e) { 116 | LOGGER.error(e.getMessage(), e); 117 | } 118 | return null; 119 | } 120 | 121 | private WinNT.HANDLE handle(int pid) { 122 | return new WinNT.HANDLE(new Pointer(pid)); 123 | } 124 | 125 | public int getTid() { 126 | final CLibrary lib = CLibrary.INSTANCE; 127 | 128 | try { 129 | return lib.GetCurrentThread(); 130 | } catch (LastErrorException e) { 131 | throw new IllegalStateException("GetCurrentThread( ) errorNo=" + e.getErrorCode(), e); 132 | } 133 | } 134 | 135 | @Override 136 | public int getCpu() { 137 | return -1; 138 | } 139 | 140 | @Override 141 | public int getProcessId() { 142 | return Kernel32.INSTANCE.GetCurrentProcessId(); 143 | } 144 | 145 | @Override 146 | public int getThreadId() { 147 | Integer tid = THREAD_ID.get(); 148 | if (tid == null) 149 | THREAD_ID.set(tid = Kernel32.INSTANCE.GetCurrentThreadId()); 150 | return tid; 151 | } 152 | 153 | /** 154 | * @author BegemoT 155 | */ 156 | private interface CLibrary extends Library { 157 | CLibrary INSTANCE = Native.load("kernel32", CLibrary.class); 158 | 159 | int GetProcessAffinityMask(final WinNT.HANDLE pid, final PointerType lpProcessAffinityMask, final PointerType lpSystemAffinityMask) throws LastErrorException; 160 | 161 | void SetThreadAffinityMask(final WinNT.HANDLE pid, final WinDef.DWORD lpProcessAffinityMask) throws LastErrorException; 162 | 163 | int GetCurrentThread() throws LastErrorException; 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/lockchecker/FileLockBasedLockChecker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.openhft.affinity.lockchecker; 18 | 19 | import org.jetbrains.annotations.NotNull; 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | 23 | import java.io.File; 24 | import java.io.IOException; 25 | import java.nio.ByteBuffer; 26 | import java.nio.channels.FileChannel; 27 | import java.nio.channels.FileLock; 28 | import java.nio.channels.OverlappingFileLockException; 29 | import java.nio.file.NoSuchFileException; 30 | import java.nio.file.OpenOption; 31 | import java.nio.file.attribute.FileAttribute; 32 | import java.nio.file.attribute.PosixFilePermission; 33 | import java.nio.file.attribute.PosixFilePermissions; 34 | import java.text.SimpleDateFormat; 35 | import java.util.Arrays; 36 | import java.util.Date; 37 | import java.util.HashSet; 38 | import java.util.Set; 39 | 40 | import static java.nio.file.StandardOpenOption.*; 41 | import static net.openhft.affinity.impl.VanillaCpuLayout.MAX_CPUS_SUPPORTED; 42 | 43 | public class FileLockBasedLockChecker implements LockChecker { 44 | 45 | private static final int MAX_LOCK_RETRIES = 5; 46 | private static final ThreadLocal dfTL = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy.MM" + ".dd 'at' HH:mm:ss z")); 47 | private static final FileAttribute> LOCK_FILE_ATTRIBUTES = PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rw-rw-rw-")); 48 | private static final Set LOCK_FILE_OPEN_OPTIONS = new HashSet<>(Arrays.asList(READ, WRITE, CREATE, SYNC)); 49 | private static final Logger LOGGER = LoggerFactory.getLogger(FileLockBasedLockChecker.class); 50 | private static final FileLockBasedLockChecker instance = new FileLockBasedLockChecker(); 51 | private final LockReference[] locks = new LockReference[MAX_CPUS_SUPPORTED]; 52 | 53 | protected FileLockBasedLockChecker() { 54 | //nothing 55 | } 56 | 57 | public static LockChecker getInstance() { 58 | return instance; 59 | } 60 | 61 | @Override 62 | public synchronized boolean isLockFree(int id) { 63 | // check if this process already has the lock 64 | if (locks[id] != null) { 65 | return false; 66 | } 67 | 68 | // check if another process has the lock 69 | File lockFile = toFile(id); 70 | try (final FileChannel channel = FileChannel.open(lockFile.toPath(), READ)) { 71 | // if we can acquire a shared lock, nobody has an exclusive lock 72 | try (final FileLock fileLock = channel.tryLock(0, Long.MAX_VALUE, true)) { 73 | if (fileLock != null && fileLock.isValid()) { 74 | if (!lockFile.delete()) { // try and clean up the orphaned lock file 75 | LOGGER.debug("Couldn't delete orphaned lock file " + lockFile); 76 | } 77 | return true; 78 | } else { 79 | // another process has an exclusive lock 80 | return false; 81 | } 82 | } catch (OverlappingFileLockException e) { 83 | // someone else (in the same JVM) has an exclusive lock 84 | /* 85 | * This shouldn't happen under normal circumstances, we have the singleton 86 | * {@link #locks} array to prevent overlapping locks from the same JVM, but 87 | * it can occur when there are multiple classloaders in the JVM 88 | */ 89 | return false; 90 | } 91 | } catch (NoSuchFileException e) { 92 | // no lock file exists, nobody has the lock 93 | return true; 94 | } catch (IOException e) { 95 | LOGGER.warn("An unexpected error occurred checking if the lock was free, assuming it's not", e); 96 | return false; 97 | } 98 | } 99 | 100 | @Override 101 | public synchronized boolean obtainLock(int id, String metaInfo) throws IOException { 102 | int attempt = 0; 103 | while (attempt < MAX_LOCK_RETRIES) { 104 | try { 105 | LockReference lockReference = tryAcquireLockOnFile(id, metaInfo); 106 | if (lockReference != null) { 107 | locks[id] = lockReference; 108 | return true; 109 | } 110 | return false; 111 | } catch (ConcurrentLockFileDeletionException e) { 112 | attempt++; 113 | } 114 | } 115 | LOGGER.warn("Exceeded maximum retries for locking CPU " + id + ", failing acquire"); 116 | return false; 117 | } 118 | 119 | /** 120 | * Attempts to acquire an exclusive lock on the core lock file. 121 | *

122 | * It will fail if another process already has an exclusive lock on the file. 123 | * 124 | * @param id The CPU ID to acquire 125 | * @param metaInfo The meta-info to write to the file upon successful acquisition 126 | * @return The {@link LockReference} if the lock was successfully acquired, null otherwise 127 | * @throws IOException If an IOException occurs creating or writing to the file 128 | * @throws ConcurrentLockFileDeletionException If another process deleted the file between us opening it and locking it 129 | */ 130 | private LockReference tryAcquireLockOnFile(int id, String metaInfo) throws IOException, ConcurrentLockFileDeletionException { 131 | final File lockFile = toFile(id); 132 | final FileChannel fileChannel = FileChannel.open(lockFile.toPath(), LOCK_FILE_OPEN_OPTIONS, LOCK_FILE_ATTRIBUTES); // NOSONAR 133 | try { 134 | final FileLock fileLock = fileChannel.tryLock(0, Long.MAX_VALUE, false); 135 | if (fileLock == null) { 136 | // someone else has a lock (exclusive or shared), fail to acquire 137 | closeQuietly(fileChannel); 138 | return null; 139 | } else { 140 | if (!lockFile.exists()) { 141 | // someone deleted the file between us opening it and acquiring the lock, signal to retry 142 | closeQuietly(fileLock, fileChannel); 143 | throw new ConcurrentLockFileDeletionException(); 144 | } else { 145 | // we have the lock, the file exists. That's success. 146 | writeMetaInfoToFile(fileChannel, metaInfo); 147 | return new LockReference(fileChannel, fileLock); 148 | } 149 | } 150 | } catch (OverlappingFileLockException e) { 151 | // someone else (in the same JVM) has a lock, fail to acquire 152 | /* 153 | * This shouldn't happen under normal circumstances, we have the singleton 154 | * {@link #locks} array to prevent overlapping locks from the same JVM, but 155 | * it can occur when there are multiple classloaders in the JVM 156 | */ 157 | closeQuietly(fileChannel); 158 | return null; 159 | } 160 | } 161 | 162 | private void writeMetaInfoToFile(FileChannel fc, String metaInfo) throws IOException { 163 | byte[] content = String.format("%s%n%s", metaInfo, dfTL.get().format(new Date())).getBytes(); 164 | ByteBuffer buffer = ByteBuffer.wrap(content); 165 | while (buffer.hasRemaining()) { 166 | fc.write(buffer); 167 | } 168 | } 169 | 170 | @Override 171 | public synchronized boolean releaseLock(int id) { 172 | if (locks[id] != null) { 173 | final File lockFile = toFile(id); 174 | if (!lockFile.delete()) { 175 | LOGGER.warn("Couldn't delete lock file on release: " + lockFile); 176 | } 177 | closeQuietly(locks[id].lock, locks[id].channel); 178 | locks[id] = null; 179 | return true; 180 | } 181 | return false; 182 | } 183 | 184 | private void closeQuietly(AutoCloseable... closeables) { 185 | for (AutoCloseable closeable : closeables) { 186 | try { 187 | if (closeable != null) { 188 | closeable.close(); 189 | } 190 | } catch (Exception e) { 191 | LOGGER.warn("Error closing " + closeable.getClass().getName(), e); 192 | } 193 | } 194 | } 195 | 196 | @Override 197 | public String getMetaInfo(int id) throws IOException { 198 | final File file = toFile(id); 199 | 200 | LockReference lr = locks[id]; 201 | if (lr != null) { 202 | return readMetaInfoFromLockFileChannel(file, lr.channel); 203 | } else { 204 | try (FileChannel fc = FileChannel.open(file.toPath(), READ)) { 205 | return readMetaInfoFromLockFileChannel(file, fc); 206 | } catch (NoSuchFileException e) { 207 | return null; 208 | } 209 | } 210 | } 211 | 212 | private String readMetaInfoFromLockFileChannel(File lockFile, FileChannel lockFileChannel) throws IOException { 213 | ByteBuffer buffer = ByteBuffer.allocate(64); 214 | int len = lockFileChannel.read(buffer, 0); 215 | String content = len < 1 ? "" : new String(buffer.array(), 0, len); 216 | if (content.isEmpty()) { 217 | LOGGER.warn("Empty lock file {}", lockFile.getAbsolutePath()); 218 | return null; 219 | } 220 | return content.substring(0, content.indexOf("\n")); 221 | } 222 | 223 | @NotNull 224 | protected File toFile(int id) { 225 | assert id >= 0; 226 | return new File(tmpDir(), "cpu-" + id + ".lock"); 227 | } 228 | 229 | private File tmpDir() { 230 | final File tempDir = new File(System.getProperty("java.io.tmpdir")); 231 | 232 | if (!tempDir.exists()) 233 | tempDir.mkdirs(); 234 | 235 | return tempDir; 236 | } 237 | 238 | /** 239 | * Thrown when another process deleted the lock file between us opening the file and acquiring the lock 240 | */ 241 | class ConcurrentLockFileDeletionException extends Exception { 242 | private static final long serialVersionUID = 0L; 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/lockchecker/LockChecker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.openhft.affinity.lockchecker; 18 | 19 | import java.io.IOException; 20 | 21 | /** 22 | * @author Tom Shercliff 23 | */ 24 | 25 | public interface LockChecker { 26 | 27 | boolean isLockFree(int id); 28 | 29 | boolean obtainLock(int id, String metaInfo) throws IOException; 30 | 31 | boolean releaseLock(int id); 32 | 33 | String getMetaInfo(int id) throws IOException; 34 | } 35 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/lockchecker/LockReference.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.openhft.affinity.lockchecker; 18 | 19 | import java.nio.channels.FileChannel; 20 | import java.nio.channels.FileLock; 21 | 22 | /** 23 | * @author Tom Shercliff 24 | */ 25 | 26 | public class LockReference { 27 | protected final FileChannel channel; 28 | protected final FileLock lock; 29 | 30 | public LockReference(final FileChannel channel, final FileLock lock) { 31 | this.channel = channel; 32 | this.lock = lock; 33 | } 34 | 35 | public FileChannel getChannel() { 36 | return channel; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/affinity/main/AffinityTestMain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.openhft.affinity.main; 18 | 19 | import net.openhft.affinity.Affinity; 20 | import net.openhft.affinity.AffinityLock; 21 | 22 | import java.text.SimpleDateFormat; 23 | import java.util.Date; 24 | 25 | /** 26 | * @author Tom Shercliff 27 | */ 28 | public class AffinityTestMain { 29 | 30 | public static void main(String[] args) { 31 | 32 | int cpus = 1; 33 | if (args.length == 0) { 34 | cpus = AffinityLock.cpuLayout().cpus() / 12; 35 | } else { 36 | cpus = Integer.valueOf(args[0]); 37 | } 38 | 39 | for (int i = 0; i < cpus; i++) { 40 | acquireAndDoWork(); 41 | } 42 | } 43 | 44 | private static void acquireAndDoWork() { 45 | 46 | Thread t = new Thread(() -> { 47 | final SimpleDateFormat df = new SimpleDateFormat("yyyy.MM" + ".dd 'at' HH:mm:ss z"); 48 | try (AffinityLock al = Affinity.acquireLock()) { 49 | String threadName = Thread.currentThread().getName(); 50 | System.out.println("Thread (" + threadName + ") locked onto cpu " + al.cpuId()); 51 | 52 | while (true) { 53 | System.out.println(df.format(new Date()) + " - Thread (" + threadName + ") doing work on cpu " + al.cpuId() + ". IsAllocated = " + al.isAllocated() + ", isBound = " + al.isBound() + ". " + al.toString()); 54 | 55 | try { 56 | Thread.sleep(10000L); 57 | } catch (InterruptedException e) { 58 | //nothing 59 | } 60 | } 61 | } 62 | }); 63 | t.start(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/ticker/ITicker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.ticker; 19 | 20 | /* 21 | * Created by Peter Lawrey on 13/07/15. 22 | */ 23 | public interface ITicker { 24 | long nanoTime(); 25 | 26 | long ticks(); 27 | 28 | long toNanos(long ticks); 29 | 30 | double toMicros(double ticks); 31 | } 32 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/ticker/Ticker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.ticker; 19 | 20 | import net.openhft.ticker.impl.JNIClock; 21 | import net.openhft.ticker.impl.SystemClock; 22 | 23 | /** 24 | * Static factory for available {@link ITicker} interface implementation 25 | * 26 | * @author Peter.Lawrey 27 | */ 28 | public final class Ticker { 29 | public static final ITicker INSTANCE; 30 | 31 | static { 32 | if (JNIClock.LOADED) { 33 | INSTANCE = JNIClock.INSTANCE; 34 | } else { 35 | INSTANCE = SystemClock.INSTANCE; 36 | } 37 | } 38 | 39 | private Ticker() { 40 | throw new InstantiationError("Must not instantiate this class"); 41 | } 42 | 43 | /** 44 | * @return The current value of the system timer, in nanoseconds. 45 | */ 46 | public static long ticks() { 47 | return INSTANCE.ticks(); 48 | } 49 | 50 | public static long nanoTime() { 51 | return toNanos(ticks()); 52 | } 53 | 54 | public static long toNanos(long ticks) { 55 | return INSTANCE.toNanos(ticks); 56 | } 57 | 58 | public static double toMicros(long ticks) { 59 | return INSTANCE.toMicros(ticks); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/ticker/impl/JNIClock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.ticker.impl; 19 | 20 | import net.openhft.ticker.ITicker; 21 | import software.chronicle.enterprise.internals.impl.NativeAffinity; 22 | 23 | import java.util.logging.Logger; 24 | 25 | /** 26 | * JNI-based implementation, trying to use rdtsc() system call 27 | * to access the most precise timer available 28 | * 29 | * @author cheremin 30 | * @since 29.12.11, 18:56 31 | */ 32 | public enum JNIClock implements ITicker { 33 | INSTANCE; 34 | 35 | public static final boolean LOADED; 36 | private static final Logger LOGGER = Logger.getLogger(JNIClock.class.getName()); 37 | private static final int FACTOR_BITS = 17; 38 | private static final long START; 39 | private static long RDTSC_FACTOR = 1 << FACTOR_BITS; 40 | private static double RDTSC_MICRO_FACTOR = 1e-3; 41 | private static long CPU_FREQUENCY = 1000; 42 | 43 | static { 44 | boolean loaded; 45 | long start; 46 | try { 47 | // ensure it is loaded. 48 | NativeAffinity.INSTANCE.getCpu(); 49 | 50 | estimateFrequency(50); 51 | estimateFrequency(200); 52 | LOGGER.info("Estimated clock frequency was " + CPU_FREQUENCY + " MHz"); 53 | start = rdtsc0(); 54 | loaded = true; 55 | } catch (UnsatisfiedLinkError ule) { 56 | LOGGER.fine("Unable to find libCEInternals in [" + System.getProperty("java.library.path") + "] " + ule); 57 | start = 0; 58 | loaded = false; 59 | } 60 | LOADED = loaded; 61 | START = start; 62 | } 63 | 64 | static long tscToNano(final long tsc) { 65 | return (tsc * RDTSC_FACTOR) >> FACTOR_BITS; 66 | } 67 | 68 | private static void estimateFrequency(int factor) { 69 | final long start = System.nanoTime(); 70 | long now; 71 | while ((now = System.nanoTime()) == start) { 72 | } 73 | 74 | long end = start + factor * 1000000; 75 | final long start0 = rdtsc0(); 76 | while ((now = System.nanoTime()) < end) { 77 | } 78 | long end0 = rdtsc0(); 79 | end = now; 80 | 81 | RDTSC_FACTOR = ((end - start) << FACTOR_BITS) / (end0 - start0) - 1; 82 | RDTSC_MICRO_FACTOR = 1e-3 * (end - start) / (end0 - start0); 83 | CPU_FREQUENCY = (end0 - start0 + 1) * 1000 / (end - start); 84 | } 85 | 86 | native static long rdtsc0(); 87 | 88 | public long nanoTime() { 89 | return tscToNano(rdtsc0() - START); 90 | } 91 | 92 | @Override 93 | public long ticks() { 94 | return rdtsc0(); 95 | } 96 | 97 | @Override 98 | public long toNanos(long ticks) { 99 | return tscToNano(ticks); 100 | } 101 | 102 | @Override 103 | public double toMicros(double ticks) { 104 | return ticks * RDTSC_MICRO_FACTOR; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /affinity/src/main/java/net/openhft/ticker/impl/SystemClock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.ticker.impl; 19 | 20 | import net.openhft.ticker.ITicker; 21 | 22 | /** 23 | * Default implementation, use plain {@link System#nanoTime()} 24 | * 25 | * @author cheremin 26 | * @since 29.12.11, 18:54 27 | */ 28 | public enum SystemClock implements ITicker { 29 | INSTANCE; 30 | 31 | @Override 32 | public long nanoTime() { 33 | return System.nanoTime(); 34 | } 35 | 36 | @Override 37 | public long ticks() { 38 | return nanoTime(); 39 | } 40 | 41 | @Override 42 | public long toNanos(long ticks) { 43 | return ticks; 44 | } 45 | 46 | @Override 47 | public double toMicros(double ticks) { 48 | return ticks / 1e3; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /affinity/src/main/java/software/chronicle/enterprise/internals/impl/NativeAffinity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package software.chronicle.enterprise.internals.impl; 19 | 20 | import net.openhft.affinity.IAffinity; 21 | 22 | import java.util.BitSet; 23 | 24 | public enum NativeAffinity implements IAffinity { 25 | INSTANCE; 26 | 27 | public static final boolean LOADED; 28 | 29 | static { 30 | LOADED = loadAffinityNativeLibrary(); 31 | } 32 | 33 | private native static byte[] getAffinity0(); 34 | 35 | private native static void setAffinity0(byte[] affinity); 36 | 37 | private native static int getCpu0(); 38 | 39 | private native static int getProcessId0(); 40 | 41 | private native static int getThreadId0(); 42 | 43 | private native static long rdtsc0(); 44 | 45 | private static boolean loadAffinityNativeLibrary() { 46 | try { 47 | System.loadLibrary("CEInternals"); 48 | return true; 49 | } catch (UnsatisfiedLinkError e) { 50 | return false; 51 | } 52 | } 53 | 54 | @Override 55 | public BitSet getAffinity() { 56 | final byte[] buff = getAffinity0(); 57 | if (buff == null) { 58 | return null; 59 | } 60 | return BitSet.valueOf(buff); 61 | } 62 | 63 | @Override 64 | public void setAffinity(BitSet affinity) { 65 | setAffinity0(affinity.toByteArray()); 66 | } 67 | 68 | @Override 69 | public int getCpu() { 70 | return getCpu0(); 71 | } 72 | 73 | @Override 74 | public int getProcessId() { 75 | return getProcessId0(); 76 | } 77 | 78 | @Override 79 | public int getThreadId() { 80 | return getThreadId0(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /affinity/src/test/java/net/openhft/affinity/AffinityLockBindMain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity; 19 | 20 | import static net.openhft.affinity.AffinityStrategies.*; 21 | 22 | /** 23 | * @author peter.lawrey 24 | */ 25 | public final class AffinityLockBindMain { 26 | private AffinityLockBindMain() { 27 | throw new InstantiationError("Must not instantiate this class"); 28 | } 29 | 30 | public static void main(String... args) throws InterruptedException { 31 | AffinityLock al = AffinityLock.acquireLock(); 32 | try { 33 | // find a cpu on a different socket, otherwise a different core. 34 | AffinityLock readerLock = al.acquireLock(DIFFERENT_SOCKET, DIFFERENT_CORE); 35 | new Thread(new SleepRunnable(readerLock, false), "reader").start(); 36 | 37 | // find a cpu on the same core, or the same socket, or any free cpu. 38 | AffinityLock writerLock = readerLock.acquireLock(SAME_CORE, SAME_SOCKET, ANY); 39 | new Thread(new SleepRunnable(writerLock, false), "writer").start(); 40 | 41 | Thread.sleep(200); 42 | } finally { 43 | al.release(); 44 | } 45 | 46 | // allocate a whole core to the engine so it doesn't have to compete for resources. 47 | al = AffinityLock.acquireCore(false); 48 | new Thread(new SleepRunnable(al, true), "engine").start(); 49 | 50 | Thread.sleep(200); 51 | System.out.println("\nThe assignment of CPUs is\n" + AffinityLock.dumpLocks()); 52 | } 53 | 54 | static class SleepRunnable implements Runnable { 55 | private final AffinityLock affinityLock; 56 | private final boolean wholeCore; 57 | 58 | SleepRunnable(AffinityLock affinityLock, boolean wholeCore) { 59 | this.affinityLock = affinityLock; 60 | this.wholeCore = wholeCore; 61 | } 62 | 63 | public void run() { 64 | affinityLock.bind(wholeCore); 65 | try { 66 | Thread.sleep(1000); 67 | } catch (InterruptedException e) { 68 | Thread.currentThread().interrupt(); 69 | } finally { 70 | affinityLock.release(); 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /affinity/src/test/java/net/openhft/affinity/AffinityLockMain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity; 19 | 20 | /** 21 | * @author peter.lawrey 22 | */ 23 | public final class AffinityLockMain { 24 | private AffinityLockMain() { 25 | throw new InstantiationError("Must not instantiate this class"); 26 | } 27 | 28 | public static void main(String... args) throws InterruptedException { 29 | AffinityLock al = AffinityLock.acquireLock(); 30 | try { 31 | new Thread(new SleepRunnable(), "reader").start(); 32 | new Thread(new SleepRunnable(), "writer").start(); 33 | Thread.sleep(200); 34 | } finally { 35 | al.release(); 36 | } 37 | new Thread(new SleepRunnable(), "engine").start(); 38 | 39 | Thread.sleep(200); 40 | System.out.println("\nThe assignment of CPUs is\n" + AffinityLock.dumpLocks()); 41 | } 42 | 43 | private static class SleepRunnable implements Runnable { 44 | public void run() { 45 | AffinityLock al = AffinityLock.acquireLock(); 46 | try { 47 | Thread.sleep(1000); 48 | } catch (InterruptedException e) { 49 | Thread.currentThread().interrupt(); 50 | } finally { 51 | al.release(); 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /affinity/src/test/java/net/openhft/affinity/AffinitySupportMain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity; 19 | 20 | /** 21 | * @author peter.lawrey 22 | */ 23 | public final class AffinitySupportMain { 24 | private AffinitySupportMain() { 25 | throw new InstantiationError("Must not instantiate this class"); 26 | } 27 | 28 | public static void main(String... args) { 29 | AffinityLock al = AffinityLock.acquireLock(); 30 | try { 31 | new Thread(new SleepRunnable(), "reader").start(); 32 | new Thread(new SleepRunnable(), "writer").start(); 33 | new Thread(new SleepRunnable(), "engine").start(); 34 | } finally { 35 | al.release(); 36 | } 37 | System.out.println("\nThe assignment of CPUs is\n" + AffinityLock.dumpLocks()); 38 | } 39 | 40 | private static class SleepRunnable implements Runnable { 41 | public void run() { 42 | AffinityLock al = AffinityLock.acquireLock(); 43 | try { 44 | Thread.sleep(1000); 45 | } catch (InterruptedException e) { 46 | Thread.currentThread().interrupt(); 47 | } finally { 48 | al.release(); 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /affinity/src/test/java/net/openhft/affinity/AffinityThreadFactoryMain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity; 19 | 20 | import java.util.concurrent.Callable; 21 | import java.util.concurrent.ExecutorService; 22 | import java.util.concurrent.Executors; 23 | import java.util.concurrent.TimeUnit; 24 | 25 | import static net.openhft.affinity.AffinityStrategies.*; 26 | 27 | /** 28 | * @author peter.lawrey 29 | */ 30 | public final class AffinityThreadFactoryMain { 31 | private static final ExecutorService ES = Executors.newFixedThreadPool(4, 32 | new AffinityThreadFactory("bg", SAME_CORE, DIFFERENT_SOCKET, ANY)); 33 | 34 | private AffinityThreadFactoryMain() { 35 | throw new InstantiationError("Must not instantiate this class"); 36 | } 37 | 38 | public static void main(String... args) throws InterruptedException { 39 | for (int i = 0; i < 12; i++) 40 | ES.submit(new Callable() { 41 | @Override 42 | public Void call() throws InterruptedException { 43 | Thread.sleep(100); 44 | return null; 45 | } 46 | }); 47 | Thread.sleep(200); 48 | System.out.println("\nThe assignment of CPUs is\n" + AffinityLock.dumpLocks()); 49 | ES.shutdown(); 50 | ES.awaitTermination(1, TimeUnit.SECONDS); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /affinity/src/test/java/net/openhft/affinity/BaseAffinityTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.openhft.affinity; 18 | 19 | import org.junit.After; 20 | import org.junit.Before; 21 | import org.junit.Rule; 22 | import org.junit.rules.TemporaryFolder; 23 | 24 | public class BaseAffinityTest { 25 | 26 | @Rule 27 | public TemporaryFolder folder = new TemporaryFolder(); 28 | private String originalTmpDir; 29 | 30 | @Before 31 | public void setTmpDirectory() { 32 | originalTmpDir = System.getProperty("java.io.tmpdir"); 33 | System.setProperty("java.io.tmpdir", folder.getRoot().getAbsolutePath()); 34 | } 35 | 36 | @After 37 | public void restoreTmpDirectoryAndReleaseAllLocks() { 38 | // don't leave any locks locked 39 | for (int i = 0; i < AffinityLock.PROCESSORS; i++) { 40 | LockCheck.releaseLock(i); 41 | } 42 | System.setProperty("java.io.tmpdir", originalTmpDir); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /affinity/src/test/java/net/openhft/affinity/BootClassPathTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.openhft.affinity; 18 | 19 | import org.junit.Test; 20 | 21 | import static org.junit.Assert.assertTrue; 22 | 23 | public class BootClassPathTest { 24 | @Test 25 | public void shouldDetectClassesOnClassPath() { 26 | if (!System.getProperty("java.version").startsWith("1.8")) 27 | return; 28 | assertTrue(BootClassPath.INSTANCE.has("java.lang.Thread")); 29 | assertTrue(BootClassPath.INSTANCE.has("java.lang.Runtime")); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /affinity/src/test/java/net/openhft/affinity/FileLockLockCheckTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity; 19 | 20 | import net.openhft.affinity.testimpl.TestFileLockBasedLockChecker; 21 | import org.junit.Assert; 22 | import org.junit.Assume; 23 | import org.junit.Before; 24 | import org.junit.Test; 25 | 26 | import java.io.File; 27 | import java.io.IOException; 28 | import java.io.RandomAccessFile; 29 | 30 | import static net.openhft.affinity.LockCheck.IS_LINUX; 31 | 32 | /** 33 | * @author Tom Shercliff 34 | */ 35 | public class FileLockLockCheckTest extends BaseAffinityTest { 36 | 37 | private final TestFileLockBasedLockChecker lockChecker = new TestFileLockBasedLockChecker(); 38 | private int cpu = 5; 39 | 40 | @Before 41 | public void before() { 42 | Assume.assumeTrue(IS_LINUX); 43 | } 44 | 45 | @Test 46 | public void test() throws IOException { 47 | Assert.assertTrue(LockCheck.isCpuFree(cpu)); 48 | LockCheck.updateCpu(cpu); 49 | Assert.assertEquals(LockCheck.getPID(), LockCheck.getProcessForCpu(cpu)); 50 | } 51 | 52 | @Test 53 | public void testPidOnLinux() { 54 | Assert.assertTrue(LockCheck.isProcessRunning(LockCheck.getPID())); 55 | } 56 | 57 | @Test 58 | public void testReplace() throws IOException { 59 | cpu++; 60 | Assert.assertTrue(LockCheck.isCpuFree(cpu + 1)); 61 | LockCheck.replacePid(cpu, 123L); 62 | Assert.assertEquals(123L, LockCheck.getProcessForCpu(cpu)); 63 | } 64 | 65 | @Test 66 | public void shouldNotBlowUpIfPidFileIsEmpty() throws Exception { 67 | LockCheck.updateCpu(cpu); 68 | 69 | final File file = lockChecker.doToFile(cpu); 70 | new RandomAccessFile(file, "rw").setLength(0); 71 | 72 | LockCheck.isCpuFree(cpu); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /affinity/src/test/java/net/openhft/affinity/InterrupedThread.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity; 19 | 20 | /** 21 | * @author peter.lawrey 22 | */ 23 | class InterrupedThread implements Runnable { 24 | public void run() { 25 | try { 26 | Thread.sleep(Integer.MAX_VALUE); 27 | } catch (InterruptedException e) { 28 | Thread.currentThread().interrupt(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /affinity/src/test/java/net/openhft/affinity/LockCheckTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity; 19 | 20 | import net.openhft.affinity.testimpl.TestFileLockBasedLockChecker; 21 | import org.junit.Assert; 22 | import org.junit.Assume; 23 | import org.junit.Before; 24 | import org.junit.Test; 25 | 26 | import java.io.File; 27 | import java.io.FileWriter; 28 | import java.io.IOException; 29 | import java.io.RandomAccessFile; 30 | 31 | import static net.openhft.affinity.LockCheck.IS_LINUX; 32 | 33 | /** 34 | * @author Rob Austin. 35 | */ 36 | public class LockCheckTest extends BaseAffinityTest { 37 | 38 | private final TestFileLockBasedLockChecker lockChecker = new TestFileLockBasedLockChecker(); 39 | private int cpu = 11; 40 | 41 | @Before 42 | public void before() { 43 | Assume.assumeTrue(IS_LINUX); 44 | } 45 | 46 | @Test 47 | public void test() throws IOException { 48 | Assert.assertTrue(LockCheck.isCpuFree(cpu)); 49 | LockCheck.updateCpu(cpu); 50 | Assert.assertEquals(LockCheck.getPID(), LockCheck.getProcessForCpu(cpu)); 51 | } 52 | 53 | @Test 54 | public void testPidOnLinux() { 55 | Assert.assertTrue(LockCheck.isProcessRunning(LockCheck.getPID())); 56 | } 57 | 58 | @Test 59 | public void testReplace() throws IOException { 60 | cpu++; 61 | Assert.assertTrue(LockCheck.isCpuFree(cpu + 1)); 62 | LockCheck.replacePid(cpu, 123L); 63 | Assert.assertEquals(123L, LockCheck.getProcessForCpu(cpu)); 64 | } 65 | 66 | @Test 67 | public void shouldNotBlowUpIfPidFileIsEmpty() throws Exception { 68 | LockCheck.updateCpu(cpu); 69 | 70 | final File file = lockChecker.doToFile(cpu); 71 | new RandomAccessFile(file, "rw").setLength(0); 72 | 73 | LockCheck.isCpuFree(cpu); 74 | } 75 | 76 | @Test 77 | public void shouldNotBlowUpIfPidFileIsCorrupt() throws Exception { 78 | LockCheck.updateCpu(cpu); 79 | 80 | final File file = lockChecker.doToFile(cpu); 81 | try (final FileWriter writer = new FileWriter(file, false)) { 82 | writer.append("not a number\nnot a date"); 83 | } 84 | 85 | LockCheck.isCpuFree(cpu); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /affinity/src/test/java/net/openhft/affinity/impl/AbstractAffinityImplTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity.impl; 19 | 20 | import net.openhft.affinity.IAffinity; 21 | import org.junit.After; 22 | import org.junit.Test; 23 | 24 | import java.util.BitSet; 25 | 26 | import static org.junit.Assert.assertEquals; 27 | import static org.junit.Assert.assertTrue; 28 | 29 | /** 30 | * @author cheremin 31 | * @since 29.12.11, 20:25 32 | */ 33 | public abstract class AbstractAffinityImplTest { 34 | 35 | protected static final int CORES = Runtime.getRuntime().availableProcessors(); 36 | protected static final BitSet CORES_MASK = new BitSet(CORES); 37 | 38 | static { 39 | CORES_MASK.set(0, CORES, true); 40 | } 41 | 42 | public abstract IAffinity getImpl(); 43 | 44 | @Test 45 | public void getAffinityCompletesGracefully() { 46 | getImpl().getAffinity(); 47 | } 48 | 49 | @Test 50 | public void getAffinityReturnsValidValue() { 51 | final BitSet affinity = getImpl().getAffinity(); 52 | assertTrue( 53 | "Affinity mask " + Utilities.toBinaryString(affinity) + " must be non-empty", 54 | !affinity.isEmpty() 55 | ); 56 | final long allCoresMask = (1L << CORES) - 1; 57 | assertTrue( 58 | "Affinity mask " + Utilities.toBinaryString(affinity) + " must be <=(2^" + CORES + "-1 = " + allCoresMask + ")", 59 | affinity.length() <= CORES_MASK.length() 60 | ); 61 | } 62 | 63 | @Test 64 | public void setAffinityCompletesGracefully() { 65 | BitSet affinity = new BitSet(1); 66 | affinity.set(0, true); 67 | getImpl().setAffinity(affinity); 68 | } 69 | 70 | @Test 71 | public void getAffinityReturnsValuePreviouslySet() { 72 | final IAffinity impl = getImpl(); 73 | for (int core = 0; core < CORES; core++) { 74 | final BitSet mask = new BitSet(); 75 | mask.set(core, true); 76 | getAffinityReturnsValuePreviouslySet(impl, mask); 77 | } 78 | } 79 | 80 | private void getAffinityReturnsValuePreviouslySet(final IAffinity impl, 81 | final BitSet mask) { 82 | 83 | impl.setAffinity(mask); 84 | final BitSet _mask = impl.getAffinity(); 85 | assertEquals(mask, _mask); 86 | } 87 | 88 | @After 89 | public void tearDown() { 90 | try { 91 | getImpl().setAffinity(CORES_MASK); 92 | } catch (Exception e) { 93 | e.printStackTrace(); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /affinity/src/test/java/net/openhft/affinity/impl/LinuxJNAAffinityTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity.impl; 19 | 20 | import org.junit.Assume; 21 | import org.junit.BeforeClass; 22 | import org.junit.Test; 23 | 24 | import java.util.BitSet; 25 | 26 | import static org.junit.Assert.assertEquals; 27 | 28 | /* 29 | * Created by Peter Lawrey on 23/03/16. 30 | */ 31 | public class LinuxJNAAffinityTest { 32 | @BeforeClass 33 | public static void checkJniLibraryPresent() { 34 | Assume.assumeTrue(LinuxJNAAffinity.LOADED); 35 | } 36 | 37 | @Test 38 | public void LinuxJNA() { 39 | int nbits = Runtime.getRuntime().availableProcessors(); 40 | BitSet affinity0 = LinuxJNAAffinity.INSTANCE.getAffinity(); 41 | System.out.println(affinity0); 42 | 43 | BitSet affinity = new BitSet(nbits); 44 | 45 | affinity.set(1); 46 | LinuxJNAAffinity.INSTANCE.setAffinity(affinity); 47 | BitSet affinity2 = LinuxJNAAffinity.INSTANCE.getAffinity(); 48 | System.out.println(affinity2); 49 | assertEquals(1, LinuxJNAAffinity.INSTANCE.getCpu()); 50 | assertEquals(affinity, affinity2); 51 | 52 | affinity.set(0, nbits); 53 | LinuxJNAAffinity.INSTANCE.setAffinity(affinity); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /affinity/src/test/java/net/openhft/affinity/impl/NativeAffinityImpTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity.impl; 19 | 20 | import net.openhft.affinity.Affinity; 21 | import net.openhft.affinity.IAffinity; 22 | import org.junit.Assume; 23 | import org.junit.BeforeClass; 24 | import org.junit.Test; 25 | import software.chronicle.enterprise.internals.impl.NativeAffinity; 26 | 27 | import static org.junit.Assert.assertTrue; 28 | 29 | /* 30 | * Created by andre on 22/06/15. 31 | */ 32 | public class NativeAffinityImpTest extends AbstractAffinityImplTest { 33 | @BeforeClass 34 | public static void checkJniLibraryPresent() { 35 | Assume.assumeTrue(NativeAffinity.LOADED); 36 | Assume.assumeTrue("linux".equalsIgnoreCase(System.getProperty("os.name"))); 37 | } 38 | 39 | @Override 40 | public IAffinity getImpl() { 41 | return NativeAffinity.INSTANCE; 42 | } 43 | 44 | @Test 45 | public void testGettid() { 46 | System.out.println("pid=" + getImpl().getProcessId()); 47 | System.out.println("tid=" + getImpl().getThreadId()); 48 | Affinity.setThreadId(); 49 | 50 | for (int j = 0; j < 3; j++) { 51 | final int runs = 100000; 52 | long tid = 0; 53 | long time = 0; 54 | for (int i = 0; i < runs; i++) { 55 | long start = System.nanoTime(); 56 | @SuppressWarnings("deprecation") 57 | long tid0 = Thread.currentThread().getId(); 58 | tid = tid0; 59 | time += System.nanoTime() - start; 60 | assertTrue(tid > 0); 61 | assertTrue(tid < 1 << 16); 62 | } 63 | System.out.printf("gettid took an average of %,d ns, tid=%d%n", time / runs, tid); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /affinity/src/test/java/net/openhft/affinity/impl/PosixJNAAffinityTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity.impl; 19 | 20 | import net.openhft.affinity.Affinity; 21 | import net.openhft.affinity.IAffinity; 22 | import org.junit.Assume; 23 | import org.junit.BeforeClass; 24 | import org.junit.Test; 25 | 26 | import static org.junit.Assert.assertTrue; 27 | 28 | /** 29 | * @author peter.lawrey 30 | */ 31 | public class PosixJNAAffinityTest extends AbstractAffinityImplTest { 32 | @BeforeClass 33 | public static void checkJniLibraryPresent() { 34 | Assume.assumeTrue("linux".equalsIgnoreCase(System.getProperty("os.name"))); 35 | } 36 | 37 | @Override 38 | public IAffinity getImpl() { 39 | return Affinity.getAffinityImpl(); 40 | } 41 | 42 | @Test 43 | public void testGettid() { 44 | System.out.println("pid=" + getImpl().getProcessId()); 45 | System.out.println("tid=" + getImpl().getThreadId()); 46 | Affinity.setThreadId(); 47 | 48 | for (int j = 0; j < 3; j++) { 49 | final int runs = 100000; 50 | long tid = 0; 51 | long time = 0; 52 | for (int i = 0; i < runs; i++) { 53 | long start = System.nanoTime(); 54 | @SuppressWarnings("deprecation") 55 | long tid0 = Thread.currentThread().getId(); 56 | tid = tid0; 57 | time += System.nanoTime() - start; 58 | assertTrue(tid > 0); 59 | assertTrue(tid < 1 << 24); 60 | } 61 | System.out.printf("gettid took an average of %,d ns, tid=%d%n", time / runs, tid); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /affinity/src/test/java/net/openhft/affinity/impl/VanillaCpuLayoutTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity.impl; 19 | 20 | import org.junit.Test; 21 | 22 | import java.io.IOException; 23 | import java.io.InputStream; 24 | 25 | import static org.junit.Assert.assertEquals; 26 | 27 | /** 28 | * @author peter.lawrey 29 | */ 30 | public class VanillaCpuLayoutTest { 31 | 32 | @Test 33 | public void testFromCpuInfoI7() throws IOException { 34 | final InputStream i7 = getClass().getClassLoader().getResourceAsStream("i7.cpuinfo"); 35 | VanillaCpuLayout vcl = VanillaCpuLayout.fromCpuInfo(i7); 36 | assertEquals("0: CpuInfo{socketId=0, coreId=0, threadId=0}\n" + 37 | "1: CpuInfo{socketId=0, coreId=1, threadId=0}\n" + 38 | "2: CpuInfo{socketId=0, coreId=2, threadId=0}\n" + 39 | "3: CpuInfo{socketId=0, coreId=3, threadId=0}\n" + 40 | "4: CpuInfo{socketId=0, coreId=0, threadId=1}\n" + 41 | "5: CpuInfo{socketId=0, coreId=1, threadId=1}\n" + 42 | "6: CpuInfo{socketId=0, coreId=2, threadId=1}\n" + 43 | "7: CpuInfo{socketId=0, coreId=3, threadId=1}\n", vcl.toString()); 44 | } 45 | 46 | @Test 47 | public void testFromCpuInfoOthers() throws IOException { 48 | { 49 | final InputStream is = getClass().getClassLoader().getResourceAsStream("amd64.dual.core.cpuinfo"); 50 | VanillaCpuLayout vcl = VanillaCpuLayout.fromCpuInfo(is); 51 | assertEquals("0: CpuInfo{socketId=0, coreId=0, threadId=0}\n" + 52 | "1: CpuInfo{socketId=0, coreId=1, threadId=0}\n", vcl.toString()); 53 | } 54 | { 55 | final InputStream is = getClass().getClassLoader().getResourceAsStream("core.duo.cpuinfo"); 56 | VanillaCpuLayout vcl = VanillaCpuLayout.fromCpuInfo(is); 57 | assertEquals("0: CpuInfo{socketId=0, coreId=0, threadId=0}\n" + 58 | "1: CpuInfo{socketId=0, coreId=1, threadId=0}\n", vcl.toString()); 59 | } 60 | { 61 | final InputStream is = getClass().getClassLoader().getResourceAsStream("amd64.quad.core.cpuinfo"); 62 | VanillaCpuLayout vcl = VanillaCpuLayout.fromCpuInfo(is); 63 | assertEquals("0: CpuInfo{socketId=0, coreId=0, threadId=0}\n" + 64 | "1: CpuInfo{socketId=0, coreId=1, threadId=0}\n" + 65 | "2: CpuInfo{socketId=0, coreId=2, threadId=0}\n" + 66 | "3: CpuInfo{socketId=0, coreId=3, threadId=0}\n", vcl.toString()); 67 | } 68 | { 69 | final InputStream is = getClass().getClassLoader().getResourceAsStream("dual.xeon.cpuinfo"); 70 | VanillaCpuLayout vcl = VanillaCpuLayout.fromCpuInfo(is); 71 | assertEquals("0: CpuInfo{socketId=0, coreId=0, threadId=0}\n" + 72 | "1: CpuInfo{socketId=0, coreId=0, threadId=1}\n" + 73 | "2: CpuInfo{socketId=3, coreId=3, threadId=0}\n" + 74 | "3: CpuInfo{socketId=3, coreId=3, threadId=1}\n", vcl.toString()); 75 | } 76 | { 77 | final InputStream is = getClass().getClassLoader().getResourceAsStream("i3.cpuinfo"); 78 | VanillaCpuLayout vcl = VanillaCpuLayout.fromCpuInfo(is); 79 | assertEquals("0: CpuInfo{socketId=0, coreId=0, threadId=0}\n" + 80 | "1: CpuInfo{socketId=0, coreId=2, threadId=0}\n" + 81 | "2: CpuInfo{socketId=0, coreId=0, threadId=1}\n" + 82 | "3: CpuInfo{socketId=0, coreId=2, threadId=1}\n", vcl.toString()); 83 | } 84 | { 85 | final InputStream is = getClass().getClassLoader().getResourceAsStream("q6600.noht.cpuinfo"); 86 | VanillaCpuLayout vcl = VanillaCpuLayout.fromCpuInfo(is); 87 | assertEquals("0: CpuInfo{socketId=0, coreId=0, threadId=0}\n" + 88 | "1: CpuInfo{socketId=0, coreId=2, threadId=0}\n" + 89 | "2: CpuInfo{socketId=0, coreId=1, threadId=0}\n" + 90 | "3: CpuInfo{socketId=0, coreId=3, threadId=0}\n", vcl.toString()); 91 | } 92 | { 93 | final InputStream is = getClass().getClassLoader().getResourceAsStream("dual.E5405.cpuinfo"); 94 | VanillaCpuLayout vcl = VanillaCpuLayout.fromCpuInfo(is); 95 | assertEquals("0: CpuInfo{socketId=0, coreId=0, threadId=0}\n" + 96 | "1: CpuInfo{socketId=0, coreId=1, threadId=0}\n" + 97 | "2: CpuInfo{socketId=0, coreId=2, threadId=0}\n" + 98 | "3: CpuInfo{socketId=0, coreId=3, threadId=0}\n" + 99 | "4: CpuInfo{socketId=1, coreId=4, threadId=0}\n" + 100 | "5: CpuInfo{socketId=1, coreId=5, threadId=0}\n" + 101 | "6: CpuInfo{socketId=1, coreId=6, threadId=0}\n" + 102 | "7: CpuInfo{socketId=1, coreId=7, threadId=0}\n", vcl.toString()); 103 | } 104 | } 105 | 106 | @Test 107 | public void testNoIDs() throws IOException { 108 | final InputStream noids = getClass().getClassLoader().getResourceAsStream("q6600.vm.cpuinfo"); 109 | VanillaCpuLayout vcl = VanillaCpuLayout.fromCpuInfo(noids); 110 | assertEquals("0: CpuInfo{socketId=0, coreId=0, threadId=0}\n" + 111 | "1: CpuInfo{socketId=0, coreId=1, threadId=0}\n" + 112 | "2: CpuInfo{socketId=0, coreId=2, threadId=0}\n" + 113 | "3: CpuInfo{socketId=0, coreId=3, threadId=0}\n", vcl.toString()); 114 | } 115 | 116 | @Test 117 | public void testFromProperties() throws IOException { 118 | final InputStream i7 = getClass().getClassLoader().getResourceAsStream("i7.properties"); 119 | VanillaCpuLayout vcl = VanillaCpuLayout.fromProperties(i7); 120 | assertEquals("0: CpuInfo{socketId=0, coreId=0, threadId=0}\n" + 121 | "1: CpuInfo{socketId=0, coreId=1, threadId=0}\n" + 122 | "2: CpuInfo{socketId=0, coreId=2, threadId=0}\n" + 123 | "3: CpuInfo{socketId=0, coreId=3, threadId=0}\n" + 124 | "4: CpuInfo{socketId=0, coreId=0, threadId=1}\n" + 125 | "5: CpuInfo{socketId=0, coreId=1, threadId=1}\n" + 126 | "6: CpuInfo{socketId=0, coreId=2, threadId=1}\n" + 127 | "7: CpuInfo{socketId=0, coreId=3, threadId=1}\n", vcl.toString()); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /affinity/src/test/java/net/openhft/affinity/impl/VersionHelperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.affinity.impl; 19 | 20 | import org.junit.Assert; 21 | import org.junit.Test; 22 | 23 | public class VersionHelperTest { 24 | 25 | @Test 26 | public void isSameOrNewerTest() { 27 | final VersionHelper v0 = new VersionHelper(0, 0, 0); 28 | final VersionHelper v2_6 = new VersionHelper(2, 6, 0); 29 | final VersionHelper v4_1 = new VersionHelper(4, 1, 1); 30 | final VersionHelper v4_9 = new VersionHelper(4, 9, 0); 31 | final VersionHelper v9_9 = new VersionHelper(9, 9, 9); 32 | 33 | VersionHelper[] versions = new VersionHelper[]{v0, v2_6, v4_1, v4_9, v9_9}; 34 | 35 | for (int i = 0; i < versions.length; i++) { 36 | for (int j = 0; j < versions.length; j++) { 37 | Assert.assertEquals(String.format("expected %s.isSameOrNewer(%s) to be %b", versions[i], versions[j], i >= j), 38 | i >= j, versions[i].isSameOrNewer(versions[j])); 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /affinity/src/test/java/net/openhft/affinity/testimpl/TestFileLockBasedLockChecker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package net.openhft.affinity.testimpl; 18 | 19 | import net.openhft.affinity.lockchecker.FileLockBasedLockChecker; 20 | 21 | import java.io.File; 22 | 23 | public class TestFileLockBasedLockChecker extends FileLockBasedLockChecker { 24 | 25 | public File doToFile(int cpu) { 26 | return toFile(cpu); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /affinity/src/test/java/net/openhft/ticker/impl/JNIClockTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package net.openhft.ticker.impl; 19 | 20 | import net.openhft.affinity.Affinity; 21 | import org.junit.Ignore; 22 | import org.junit.Test; 23 | 24 | import static org.junit.Assert.assertEquals; 25 | 26 | /* 27 | * Created by Peter Lawrey on 13/07/15. 28 | */ 29 | public class JNIClockTest { 30 | 31 | @Test 32 | @Ignore("TODO Fix") 33 | public void testNanoTime() throws InterruptedException { 34 | for (int i = 0; i < 20000; i++) 35 | System.nanoTime(); 36 | Affinity.setAffinity(2); 37 | 38 | JNIClock instance = JNIClock.INSTANCE; 39 | for (int i = 0; i < 50; i++) { 40 | long start0 = System.nanoTime(); 41 | long start1 = instance.ticks(); 42 | Thread.sleep(10); 43 | long time0 = System.nanoTime(); 44 | long time1 = instance.ticks(); 45 | if (i > 1) { 46 | assertEquals(10_100_000, time0 - start0, 100_000); 47 | assertEquals(10_100_000, instance.toNanos(time1 - start1), 100_000); 48 | assertEquals(instance.toNanos(time1 - start1) / 1e3, instance.toMicros(time1 - start1), 0.6); 49 | } 50 | } 51 | } 52 | 53 | @Test 54 | @Ignore("Long running") 55 | public void testJitter() { 56 | Affinity.setAffinity(2); 57 | assertEquals(2, Affinity.getCpu()); 58 | int samples = 100000, count = 0; 59 | long[] time = new long[samples]; 60 | long[] length = new long[samples]; 61 | 62 | JNIClock clock = JNIClock.INSTANCE; 63 | long start = clock.ticks(), prev = start, prevJump = start; 64 | for (int i = 0; i < 1000_000_000; i++) { 65 | long now = clock.ticks(); 66 | long delta = now - prev; 67 | if (delta > 4_000) { 68 | time[count] = now - prevJump; 69 | prevJump = now; 70 | length[count] = delta; 71 | count++; 72 | if (count >= samples) 73 | break; 74 | } 75 | prev = now; 76 | } 77 | for (int i = 0; i < count; i++) { 78 | System.out.println(((long) (clock.toMicros(time[i]) * 10)) / 10.0 + ", " + ((long) (clock.toMicros(length[i]) * 10) / 10.0)); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /affinity/src/test/java/software/chronicle/enterprise/internals/JnaAffinityTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package software.chronicle.enterprise.internals; 19 | 20 | import net.openhft.affinity.IAffinity; 21 | import net.openhft.affinity.impl.LinuxJNAAffinity; 22 | import net.openhft.affinity.impl.Utilities; 23 | import org.junit.After; 24 | import org.junit.Assume; 25 | import org.junit.BeforeClass; 26 | import org.junit.Test; 27 | 28 | import java.util.BitSet; 29 | 30 | import static org.junit.Assert.assertEquals; 31 | import static org.junit.Assert.assertTrue; 32 | 33 | /** 34 | * @author peter.lawrey 35 | */ 36 | public class JnaAffinityTest { 37 | protected static final int CORES = Runtime.getRuntime().availableProcessors(); 38 | protected static final BitSet CORES_MASK = new BitSet(CORES); 39 | 40 | static { 41 | CORES_MASK.set(0, CORES, true); 42 | } 43 | 44 | @BeforeClass 45 | public static void checkJniLibraryPresent() { 46 | Assume.assumeTrue(LinuxJNAAffinity.LOADED); 47 | } 48 | 49 | @Test 50 | public void getAffinityCompletesGracefully() { 51 | System.out.println("affinity: " + Utilities.toBinaryString(getImpl().getAffinity())); 52 | } 53 | 54 | @Test 55 | public void getAffinityReturnsValidValue() { 56 | final BitSet affinity = getImpl().getAffinity(); 57 | assertTrue( 58 | "Affinity mask " + Utilities.toBinaryString(affinity) + " must be non-empty", 59 | !affinity.isEmpty() 60 | ); 61 | final int allCoresMask = (1 << CORES) - 1; 62 | assertTrue( 63 | "Affinity mask " + Utilities.toBinaryString(affinity) + " must be <=(2^" + CORES + "-1 = " + allCoresMask + ")", 64 | affinity.length() <= CORES_MASK.length() 65 | ); 66 | } 67 | 68 | @Test 69 | public void setAffinityCompletesGracefully() { 70 | BitSet affinity = new BitSet(1); 71 | affinity.set(0, true); 72 | getImpl().setAffinity(affinity); 73 | } 74 | 75 | @Test 76 | public void getAffinityReturnsValuePreviouslySet() { 77 | String osName = System.getProperty("os.name"); 78 | if (!osName.startsWith("Linux")) { 79 | System.out.println("Skipping Linux tests"); 80 | return; 81 | } 82 | final IAffinity impl = LinuxJNAAffinity.INSTANCE; 83 | final int cores = CORES; 84 | for (int core = 0; core < cores; core++) { 85 | final BitSet mask = new BitSet(); 86 | mask.set(core, true); 87 | getAffinityReturnsValuePreviouslySet(impl, mask); 88 | } 89 | } 90 | 91 | @Test 92 | public void showOtherIds() { 93 | System.out.println("processId: " + LinuxJNAAffinity.INSTANCE.getProcessId()); 94 | System.out.println("threadId: " + LinuxJNAAffinity.INSTANCE.getThreadId()); 95 | System.out.println("cpu: " + LinuxJNAAffinity.INSTANCE.getCpu()); 96 | } 97 | 98 | private void getAffinityReturnsValuePreviouslySet(final IAffinity impl, 99 | final BitSet mask) { 100 | 101 | impl.setAffinity(mask); 102 | final BitSet _mask = impl.getAffinity(); 103 | assertEquals(mask, _mask); 104 | } 105 | 106 | @After 107 | public void tearDown() { 108 | getImpl().setAffinity(CORES_MASK); 109 | } 110 | 111 | public IAffinity getImpl() { 112 | return LinuxJNAAffinity.INSTANCE; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /affinity/src/test/java/software/chronicle/enterprise/internals/NativeAffinityTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2025 chronicle.software 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package software.chronicle.enterprise.internals; 19 | 20 | import net.openhft.affinity.IAffinity; 21 | import net.openhft.affinity.impl.LinuxJNAAffinity; 22 | import net.openhft.affinity.impl.Utilities; 23 | import org.junit.*; 24 | import software.chronicle.enterprise.internals.impl.NativeAffinity; 25 | 26 | import java.util.BitSet; 27 | 28 | import static org.junit.Assert.assertEquals; 29 | import static org.junit.Assert.assertTrue; 30 | 31 | /** 32 | * @author peter.lawrey 33 | */ 34 | public class NativeAffinityTest { 35 | protected static final int CORES = Runtime.getRuntime().availableProcessors(); 36 | protected static final BitSet CORES_MASK = new BitSet(CORES); 37 | 38 | static { 39 | CORES_MASK.set(0, CORES, true); 40 | } 41 | 42 | @BeforeClass 43 | public static void checkJniLibraryPresent() { 44 | Assume.assumeTrue(NativeAffinity.LOADED); 45 | } 46 | 47 | @Test 48 | public void getAffinityCompletesGracefully() { 49 | System.out.println("affinity: " + Utilities.toBinaryString(getImpl().getAffinity())); 50 | } 51 | 52 | @Test 53 | public void getAffinityReturnsValidValue() { 54 | final BitSet affinity = getImpl().getAffinity(); 55 | assertTrue( 56 | "Affinity mask " + Utilities.toBinaryString(affinity) + " must be non-empty", 57 | !affinity.isEmpty() 58 | ); 59 | final int allCoresMask = (1 << CORES) - 1; 60 | assertTrue( 61 | "Affinity mask " + Utilities.toBinaryString(affinity) + " must be <=(2^" + CORES + "-1 = " + allCoresMask + ")", 62 | affinity.length() <= CORES_MASK.length() 63 | ); 64 | } 65 | 66 | @Test 67 | public void setAffinityCompletesGracefully() { 68 | BitSet affinity = new BitSet(1); 69 | affinity.set(0, true); 70 | getImpl().setAffinity(affinity); 71 | } 72 | 73 | @Test 74 | @Ignore("TODO AFFINITY-25") 75 | public void getAffinityReturnsValuePreviouslySet() { 76 | String osName = System.getProperty("os.name"); 77 | if (!osName.startsWith("Linux")) { 78 | System.out.println("Skipping Linux tests"); 79 | return; 80 | } 81 | final IAffinity impl = NativeAffinity.INSTANCE; 82 | final int cores = CORES; 83 | for (int core = 0; core < cores; core++) { 84 | final BitSet mask = new BitSet(); 85 | mask.set(core, true); 86 | getAffinityReturnsValuePreviouslySet(impl, mask); 87 | } 88 | } 89 | 90 | @Test 91 | @Ignore("TODO AFFINITY-25") 92 | public void JNAwithJNI() { 93 | String osName = System.getProperty("os.name"); 94 | if (!osName.startsWith("Linux")) { 95 | System.out.println("Skipping Linux tests"); 96 | return; 97 | } 98 | int nbits = Runtime.getRuntime().availableProcessors(); 99 | BitSet affinity = new BitSet(nbits); 100 | affinity.set(1); 101 | NativeAffinity.INSTANCE.setAffinity(affinity); 102 | BitSet affinity2 = LinuxJNAAffinity.INSTANCE.getAffinity(); 103 | assertEquals(1, NativeAffinity.INSTANCE.getCpu()); 104 | assertEquals(affinity, affinity2); 105 | 106 | affinity.clear(); 107 | affinity.set(2); 108 | LinuxJNAAffinity.INSTANCE.setAffinity(affinity); 109 | BitSet affinity3 = NativeAffinity.INSTANCE.getAffinity(); 110 | assertEquals(2, LinuxJNAAffinity.INSTANCE.getCpu()); 111 | assertEquals(affinity, affinity3); 112 | 113 | affinity.set(0, nbits); 114 | LinuxJNAAffinity.INSTANCE.setAffinity(affinity); 115 | } 116 | 117 | @Test 118 | public void showOtherIds() { 119 | System.out.println("processId: " + NativeAffinity.INSTANCE.getProcessId()); 120 | System.out.println("threadId: " + NativeAffinity.INSTANCE.getThreadId()); 121 | System.out.println("cpu: " + NativeAffinity.INSTANCE.getCpu()); 122 | } 123 | 124 | private void getAffinityReturnsValuePreviouslySet(final IAffinity impl, 125 | final BitSet mask) { 126 | 127 | impl.setAffinity(mask); 128 | final BitSet _mask = impl.getAffinity(); 129 | assertEquals(mask, _mask); 130 | } 131 | 132 | @After 133 | public void tearDown() { 134 | getImpl().setAffinity(CORES_MASK); 135 | } 136 | 137 | public IAffinity getImpl() { 138 | return NativeAffinity.INSTANCE; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /affinity/src/test/resources/amd64.dual.core.cpuinfo: -------------------------------------------------------------------------------- 1 | processor : 0 2 | vendor_id : AuthenticAMD 3 | cpu family : 15 4 | model : 107 5 | model name : Athlon 64 Dual Core 5000+ 6 | stepping : 2 7 | cpu MHz : 2599.998 8 | cache size : 512 KB 9 | physical id : 0 10 | siblings : 2 11 | core id : 0 12 | cpu cores : 2 13 | fpu : yes 14 | fpu_exception : yes 15 | cpuid level : 1 16 | wp : yes 17 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt rdtscp lm 3dnowext 3dnow rep_good pni cx16 lahf_lm cmp_legacy svm extapic cr8_legacy 3dnowprefetch 18 | bogomips : 5204.18 19 | TLB size : 1024 4K pages 20 | clflush size : 64 21 | cache_alignment : 64 22 | address sizes : 40 bits physical, 48 bits virtual 23 | power management: ts fid vid ttp tm stc 100mhzsteps 24 | 25 | processor : 1 26 | vendor_id : AuthenticAMD 27 | cpu family : 15 28 | model : 107 29 | model name : Athlon 64 Dual Core 5000+ 30 | stepping : 2 31 | cpu MHz : 2599.998 32 | cache size : 512 KB 33 | physical id : 0 34 | siblings : 2 35 | core id : 1 36 | cpu cores : 2 37 | fpu : yes 38 | fpu_exception : yes 39 | cpuid level : 1 40 | wp : yes 41 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt rdtscp lm 3dnowext 3dnow rep_good pni cx16 lahf_lm cmp_legacy svm extapic cr8_legacy 3dnowprefetch 42 | bogomips : 5200.04 43 | TLB size : 1024 4K pages 44 | clflush size : 64 45 | cache_alignment : 64 46 | address sizes : 40 bits physical, 48 bits virtual 47 | power management: ts fid vid ttp tm stc 100mhzsteps 48 | 49 | -------------------------------------------------------------------------------- /affinity/src/test/resources/amd64.quad.core.cpuinfo: -------------------------------------------------------------------------------- 1 | processor : 0 2 | vendor_id : AuthenticAMD 3 | cpu family : 16 4 | model : 4 5 | model name : Quad-Core AMD Opteron(tm) Processor 2374 HE 6 | stepping : 2 7 | cpu MHz : 2194.255 8 | cache size : 512 KB 9 | physical id : 0 10 | siblings : 4 11 | core id : 0 12 | cpu cores : 4 13 | apicid : 0 14 | initial apicid : 0 15 | fpu : yes 16 | fpu_exception : yes 17 | cpuid level : 5 18 | wp : yes 19 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm 3dnowext 3dnow constant_tsc rep_good nonstop_tsc extd_apicid pni monitor cx16 popcnt lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs skinit wdt 20 | bogomips : 4388.50 21 | TLB size : 1024 4K pages 22 | clflush size : 64 23 | cache_alignment : 64 24 | address sizes : 48 bits physical, 48 bits virtual 25 | power management: ts ttp tm stc 100mhzsteps hwpstate 26 | 27 | processor : 1 28 | vendor_id : AuthenticAMD 29 | cpu family : 16 30 | model : 4 31 | model name : Quad-Core AMD Opteron(tm) Processor 2374 HE 32 | stepping : 2 33 | cpu MHz : 2194.255 34 | cache size : 512 KB 35 | physical id : 0 36 | siblings : 4 37 | core id : 1 38 | cpu cores : 4 39 | apicid : 1 40 | initial apicid : 1 41 | fpu : yes 42 | fpu_exception : yes 43 | cpuid level : 5 44 | wp : yes 45 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm 3dnowext 3dnow constant_tsc rep_good nonstop_tsc extd_apicid pni monitor cx16 popcnt lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs skinit wdt 46 | bogomips : 4389.05 47 | TLB size : 1024 4K pages 48 | clflush size : 64 49 | cache_alignment : 64 50 | address sizes : 48 bits physical, 48 bits virtual 51 | power management: ts ttp tm stc 100mhzsteps hwpstate 52 | 53 | processor : 2 54 | vendor_id : AuthenticAMD 55 | cpu family : 16 56 | model : 4 57 | model name : Quad-Core AMD Opteron(tm) Processor 2374 HE 58 | stepping : 2 59 | cpu MHz : 2194.255 60 | cache size : 512 KB 61 | physical id : 0 62 | siblings : 4 63 | core id : 2 64 | cpu cores : 4 65 | apicid : 2 66 | initial apicid : 2 67 | fpu : yes 68 | fpu_exception : yes 69 | cpuid level : 5 70 | wp : yes 71 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm 3dnowext 3dnow constant_tsc rep_good nonstop_tsc extd_apicid pni monitor cx16 popcnt lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs skinit wdt 72 | bogomips : 4389.05 73 | TLB size : 1024 4K pages 74 | clflush size : 64 75 | cache_alignment : 64 76 | address sizes : 48 bits physical, 48 bits virtual 77 | power management: ts ttp tm stc 100mhzsteps hwpstate 78 | 79 | processor : 3 80 | vendor_id : AuthenticAMD 81 | cpu family : 16 82 | model : 4 83 | model name : Quad-Core AMD Opteron(tm) Processor 2374 HE 84 | stepping : 2 85 | cpu MHz : 2194.255 86 | cache size : 512 KB 87 | physical id : 0 88 | siblings : 4 89 | core id : 3 90 | cpu cores : 4 91 | apicid : 3 92 | initial apicid : 3 93 | fpu : yes 94 | fpu_exception : yes 95 | cpuid level : 5 96 | wp : yes 97 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm 3dnowext 3dnow constant_tsc rep_good nonstop_tsc extd_apicid pni monitor cx16 popcnt lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs skinit wdt 98 | bogomips : 4389.05 99 | TLB size : 1024 4K pages 100 | clflush size : 64 101 | cache_alignment : 64 102 | address sizes : 48 bits physical, 48 bits virtual 103 | power management: ts ttp tm stc 100mhzsteps hwpstate 104 | 105 | -------------------------------------------------------------------------------- /affinity/src/test/resources/core.duo.cpuinfo: -------------------------------------------------------------------------------- 1 | processor : 0 2 | vendor_id : GenuineIntel 3 | cpu family : 6 4 | model : 23 5 | model name : Intel(R) Core(TM)2 Duo CPU T8300 @ 2.40GHz 6 | stepping : 6 7 | cpu MHz : 800.000 8 | cache size : 3072 KB 9 | physical id : 0 10 | siblings : 2 11 | core id : 0 12 | cpu cores : 2 13 | apicid : 0 14 | initial apicid : 0 15 | fpu : yes 16 | fpu_exception : yes 17 | cpuid level : 10 18 | wp : yes 19 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good nopl pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 lahf_lm ida 20 | bogomips : 4787.93 21 | clflush size : 64 22 | cache_alignment : 64 23 | address sizes : 36 bits physical, 48 bits virtual 24 | power management: 25 | 26 | processor : 1 27 | vendor_id : GenuineIntel 28 | cpu family : 6 29 | model : 23 30 | model name : Intel(R) Core(TM)2 Duo CPU T8300 @ 2.40GHz 31 | stepping : 6 32 | cpu MHz : 800.000 33 | cache size : 3072 KB 34 | physical id : 0 35 | siblings : 2 36 | core id : 1 37 | cpu cores : 2 38 | apicid : 1 39 | initial apicid : 1 40 | fpu : yes 41 | fpu_exception : yes 42 | cpuid level : 10 43 | wp : yes 44 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good nopl pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 lahf_lm ida 45 | bogomips : 4787.96 46 | clflush size : 64 47 | cache_alignment : 64 48 | address sizes : 36 bits physical, 48 bits virtual 49 | power management: 50 | 51 | -------------------------------------------------------------------------------- /affinity/src/test/resources/dual.E5405.cpuinfo: -------------------------------------------------------------------------------- 1 | processor : 0 2 | vendor_id : GenuineIntel 3 | cpu family : 6 4 | model : 7 5 | model name : Intel(R) Xeon(R) CPU E5405 @ 2.00GHz 6 | stepping : 6 7 | cpu MHz : 1995.138 8 | cache size : 6144 KB 9 | physical id : 0 10 | siblings : 4 11 | core id : 0 12 | cpu cores : 4 13 | fdiv_bug : no 14 | hlt_bug : no 15 | f00f_bug : no 16 | coma_bug : no 17 | fpu : yes 18 | fpu_exception : yes 19 | cpuid level : 10 20 | wp : yes 21 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm pni monitor ds_cpl tm2 xtpr 22 | bogomips : 3992.50 23 | 24 | processor : 1 25 | vendor_id : GenuineIntel 26 | cpu family : 6 27 | model : 7 28 | model name : Intel(R) Xeon(R) CPU E5405 @ 2.00GHz 29 | stepping : 6 30 | cpu MHz : 1995.138 31 | cache size : 6144 KB 32 | physical id : 0 33 | siblings : 4 34 | core id : 1 35 | cpu cores : 4 36 | fdiv_bug : no 37 | hlt_bug : no 38 | f00f_bug : no 39 | coma_bug : no 40 | fpu : yes 41 | fpu_exception : yes 42 | cpuid level : 10 43 | wp : yes 44 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm pni monitor ds_cpl tm2 xtpr 45 | bogomips : 3990.03 46 | 47 | processor : 2 48 | vendor_id : GenuineIntel 49 | cpu family : 6 50 | model : 7 51 | model name : Intel(R) Xeon(R) CPU E5405 @ 2.00GHz 52 | stepping : 6 53 | cpu MHz : 1995.138 54 | cache size : 6144 KB 55 | physical id : 0 56 | siblings : 4 57 | core id : 2 58 | cpu cores : 4 59 | fdiv_bug : no 60 | hlt_bug : no 61 | f00f_bug : no 62 | coma_bug : no 63 | fpu : yes 64 | fpu_exception : yes 65 | cpuid level : 10 66 | wp : yes 67 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm pni monitor ds_cpl tm2 xtpr 68 | bogomips : 3990.01 69 | 70 | processor : 3 71 | vendor_id : GenuineIntel 72 | cpu family : 6 73 | model : 7 74 | model name : Intel(R) Xeon(R) CPU E5405 @ 2.00GHz 75 | stepping : 6 76 | cpu MHz : 1995.138 77 | cache size : 6144 KB 78 | physical id : 0 79 | siblings : 4 80 | core id : 3 81 | cpu cores : 4 82 | fdiv_bug : no 83 | hlt_bug : no 84 | f00f_bug : no 85 | coma_bug : no 86 | fpu : yes 87 | fpu_exception : yes 88 | cpuid level : 10 89 | wp : yes 90 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm pni monitor ds_cpl tm2 xtpr 91 | bogomips : 3990.11 92 | 93 | processor : 4 94 | vendor_id : GenuineIntel 95 | cpu family : 6 96 | model : 7 97 | model name : Intel(R) Xeon(R) CPU E5405 @ 2.00GHz 98 | stepping : 6 99 | cpu MHz : 1995.138 100 | cache size : 6144 KB 101 | physical id : 1 102 | siblings : 4 103 | core id : 4 104 | cpu cores : 4 105 | fdiv_bug : no 106 | hlt_bug : no 107 | f00f_bug : no 108 | coma_bug : no 109 | fpu : yes 110 | fpu_exception : yes 111 | cpuid level : 10 112 | wp : yes 113 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm pni monitor ds_cpl tm2 xtpr 114 | bogomips : 3990.09 115 | 116 | processor : 5 117 | vendor_id : GenuineIntel 118 | cpu family : 6 119 | model : 7 120 | model name : Intel(R) Xeon(R) CPU E5405 @ 2.00GHz 121 | stepping : 6 122 | cpu MHz : 1995.138 123 | cache size : 6144 KB 124 | physical id : 1 125 | siblings : 4 126 | core id : 5 127 | cpu cores : 4 128 | fdiv_bug : no 129 | hlt_bug : no 130 | f00f_bug : no 131 | coma_bug : no 132 | fpu : yes 133 | fpu_exception : yes 134 | cpuid level : 10 135 | wp : yes 136 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm pni monitor ds_cpl tm2 xtpr 137 | bogomips : 3990.05 138 | 139 | processor : 6 140 | vendor_id : GenuineIntel 141 | cpu family : 6 142 | model : 7 143 | model name : Intel(R) Xeon(R) CPU E5405 @ 2.00GHz 144 | stepping : 6 145 | cpu MHz : 1995.138 146 | cache size : 6144 KB 147 | physical id : 1 148 | siblings : 4 149 | core id : 6 150 | cpu cores : 4 151 | fdiv_bug : no 152 | hlt_bug : no 153 | f00f_bug : no 154 | coma_bug : no 155 | fpu : yes 156 | fpu_exception : yes 157 | cpuid level : 10 158 | wp : yes 159 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm pni monitor ds_cpl tm2 xtpr 160 | bogomips : 3990.07 161 | 162 | processor : 7 163 | vendor_id : GenuineIntel 164 | cpu family : 6 165 | model : 7 166 | model name : Intel(R) Xeon(R) CPU E5405 @ 2.00GHz 167 | stepping : 6 168 | cpu MHz : 1995.138 169 | cache size : 6144 KB 170 | physical id : 1 171 | siblings : 4 172 | core id : 7 173 | cpu cores : 4 174 | fdiv_bug : no 175 | hlt_bug : no 176 | f00f_bug : no 177 | coma_bug : no 178 | fpu : yes 179 | fpu_exception : yes 180 | cpuid level : 10 181 | wp : yes 182 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm pni monitor ds_cpl tm2 xtpr 183 | bogomips : 3990.02 184 | 185 | -------------------------------------------------------------------------------- /affinity/src/test/resources/dual.xeon.cpuinfo: -------------------------------------------------------------------------------- 1 | processor : 0 2 | vendor_id : GenuineIntel 3 | cpu family : 15 4 | model : 4 5 | model name : Intel(R) Xeon(TM) MP CPU 3.66GHz 6 | stepping : 1 7 | cpu MHz : 3670.025 8 | cache size : 1024 KB 9 | physical id : 0 10 | siblings : 2 11 | core id : 0 12 | cpu cores : 1 13 | fpu : yes 14 | fpu_exception : yes 15 | cpuid level : 5 16 | wp : yes 17 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall lm pni monitor ds_cpl est tm2 cid cx16 xtpr 18 | bogomips : 7208.96 19 | clflush size : 64 20 | cache_alignment : 128 21 | address sizes : 40 bits physical, 48 bits virtual 22 | power management: 23 | 24 | processor : 1 25 | vendor_id : GenuineIntel 26 | cpu family : 15 27 | model : 4 28 | model name : Intel(R) Xeon(TM) MP CPU 3.66GHz 29 | stepping : 1 30 | cpu MHz : 3670.025 31 | cache size : 1024 KB 32 | physical id : 0 33 | siblings : 2 34 | core id : 0 35 | cpu cores : 1 36 | fpu : yes 37 | fpu_exception : yes 38 | cpuid level : 5 39 | wp : yes 40 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall lm pni monitor ds_cpl est tm2 cid cx16 xtpr 41 | bogomips : 7323.64 42 | clflush size : 64 43 | cache_alignment : 128 44 | address sizes : 40 bits physical, 48 bits virtual 45 | power management: 46 | 47 | processor : 2 48 | vendor_id : GenuineIntel 49 | cpu family : 15 50 | model : 4 51 | model name : Intel(R) Xeon(TM) MP CPU 3.66GHz 52 | stepping : 1 53 | cpu MHz : 3670.025 54 | cache size : 1024 KB 55 | physical id : 3 56 | siblings : 2 57 | core id : 3 58 | cpu cores : 1 59 | fpu : yes 60 | fpu_exception : yes 61 | cpuid level : 5 62 | wp : yes 63 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall lm pni monitor ds_cpl est tm2 cid cx16 xtpr 64 | bogomips : 7323.64 65 | clflush size : 64 66 | cache_alignment : 128 67 | address sizes : 40 bits physical, 48 bits virtual 68 | power management: 69 | 70 | processor : 3 71 | vendor_id : GenuineIntel 72 | cpu family : 15 73 | model : 4 74 | model name : Intel(R) Xeon(TM) MP CPU 3.66GHz 75 | stepping : 1 76 | cpu MHz : 3670.025 77 | cache size : 1024 KB 78 | physical id : 3 79 | siblings : 2 80 | core id : 3 81 | cpu cores : 1 82 | fpu : yes 83 | fpu_exception : yes 84 | cpuid level : 5 85 | wp : yes 86 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall lm pni monitor ds_cpl est tm2 cid cx16 xtpr 87 | bogomips : 7323.64 88 | clflush size : 64 89 | cache_alignment : 128 90 | address sizes : 40 bits physical, 48 bits virtual 91 | power management: 92 | 93 | -------------------------------------------------------------------------------- /affinity/src/test/resources/i3.cpuinfo: -------------------------------------------------------------------------------- 1 | processor : 0 2 | vendor_id : GenuineIntel 3 | cpu family : 6 4 | model : 37 5 | model name : Intel(R) Core(TM) i3 CPU 530 @ 2.93GHz 6 | stepping : 2 7 | cpu MHz : 1200.000 8 | cache size : 4096 KB 9 | physical id : 0 10 | siblings : 4 11 | core id : 0 12 | cpu cores : 2 13 | apicid : 0 14 | initial apicid : 0 15 | fdiv_bug : no 16 | hlt_bug : no 17 | f00f_bug : no 18 | coma_bug : no 19 | fpu : yes 20 | fpu_exception : yes 21 | cpuid level : 11 22 | wp : yes 23 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology nonstop_tsc aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 popcnt lahf_lm arat tpr_shadow vnmi flexpriority ept vpid 24 | bogomips : 5866.15 25 | clflush size : 64 26 | cache_alignment : 64 27 | address sizes : 36 bits physical, 48 bits virtual 28 | power management: 29 | 30 | processor : 1 31 | vendor_id : GenuineIntel 32 | cpu family : 6 33 | model : 37 34 | model name : Intel(R) Core(TM) i3 CPU 530 @ 2.93GHz 35 | stepping : 2 36 | cpu MHz : 1200.000 37 | cache size : 4096 KB 38 | physical id : 0 39 | siblings : 4 40 | core id : 2 41 | cpu cores : 2 42 | apicid : 4 43 | initial apicid : 4 44 | fdiv_bug : no 45 | hlt_bug : no 46 | f00f_bug : no 47 | coma_bug : no 48 | fpu : yes 49 | fpu_exception : yes 50 | cpuid level : 11 51 | wp : yes 52 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology nonstop_tsc aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 popcnt lahf_lm arat tpr_shadow vnmi flexpriority ept vpid 53 | bogomips : 5866.64 54 | clflush size : 64 55 | cache_alignment : 64 56 | address sizes : 36 bits physical, 48 bits virtual 57 | power management: 58 | 59 | processor : 2 60 | vendor_id : GenuineIntel 61 | cpu family : 6 62 | model : 37 63 | model name : Intel(R) Core(TM) i3 CPU 530 @ 2.93GHz 64 | stepping : 2 65 | cpu MHz : 1200.000 66 | cache size : 4096 KB 67 | physical id : 0 68 | siblings : 4 69 | core id : 0 70 | cpu cores : 2 71 | apicid : 1 72 | initial apicid : 1 73 | fdiv_bug : no 74 | hlt_bug : no 75 | f00f_bug : no 76 | coma_bug : no 77 | fpu : yes 78 | fpu_exception : yes 79 | cpuid level : 11 80 | wp : yes 81 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology nonstop_tsc aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 popcnt lahf_lm arat tpr_shadow vnmi flexpriority ept vpid 82 | bogomips : 5866.62 83 | clflush size : 64 84 | cache_alignment : 64 85 | address sizes : 36 bits physical, 48 bits virtual 86 | power management: 87 | 88 | processor : 3 89 | vendor_id : GenuineIntel 90 | cpu family : 6 91 | model : 37 92 | model name : Intel(R) Core(TM) i3 CPU 530 @ 2.93GHz 93 | stepping : 2 94 | cpu MHz : 1200.000 95 | cache size : 4096 KB 96 | physical id : 0 97 | siblings : 4 98 | core id : 2 99 | cpu cores : 2 100 | apicid : 5 101 | initial apicid : 5 102 | fdiv_bug : no 103 | hlt_bug : no 104 | f00f_bug : no 105 | coma_bug : no 106 | fpu : yes 107 | fpu_exception : yes 108 | cpuid level : 11 109 | wp : yes 110 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx rdtscp lm constant_tsc arch_perfmon pebs bts xtopology nonstop_tsc aperfmperf pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 popcnt lahf_lm arat tpr_shadow vnmi flexpriority ept vpid 111 | bogomips : 5866.65 112 | clflush size : 64 113 | cache_alignment : 64 114 | address sizes : 36 bits physical, 48 bits virtual 115 | power management: 116 | 117 | -------------------------------------------------------------------------------- /affinity/src/test/resources/i7.cpuinfo: -------------------------------------------------------------------------------- 1 | processor : 0 2 | vendor_id : GenuineIntel 3 | cpu family : 6 4 | model : 42 5 | model name : Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz 6 | stepping : 7 7 | cpu MHz : 3400.235 8 | cache size : 8192 KB 9 | physical id : 0 10 | siblings : 8 11 | core id : 0 12 | cpu cores : 4 13 | apicid : 0 14 | fpu : yes 15 | fpu_exception : yes 16 | cpuid level : 13 17 | wp : yes 18 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc arat pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm 19 | bogomips : 6800.47 20 | clflush size : 64 21 | cache_alignment : 64 22 | address sizes : 36 bits physical, 48 bits virtual 23 | power management: [8] 24 | 25 | processor : 1 26 | vendor_id : GenuineIntel 27 | cpu family : 6 28 | model : 42 29 | model name : Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz 30 | stepping : 7 31 | cpu MHz : 3400.235 32 | cache size : 8192 KB 33 | physical id : 0 34 | siblings : 8 35 | core id : 1 36 | cpu cores : 4 37 | apicid : 2 38 | fpu : yes 39 | fpu_exception : yes 40 | cpuid level : 13 41 | wp : yes 42 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc arat pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm 43 | bogomips : 6800.26 44 | clflush size : 64 45 | cache_alignment : 64 46 | address sizes : 36 bits physical, 48 bits virtual 47 | power management: [8] 48 | 49 | processor : 2 50 | vendor_id : GenuineIntel 51 | cpu family : 6 52 | model : 42 53 | model name : Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz 54 | stepping : 7 55 | cpu MHz : 3400.235 56 | cache size : 8192 KB 57 | physical id : 0 58 | siblings : 8 59 | core id : 2 60 | cpu cores : 4 61 | apicid : 4 62 | fpu : yes 63 | fpu_exception : yes 64 | cpuid level : 13 65 | wp : yes 66 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc arat pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm 67 | bogomips : 6800.07 68 | clflush size : 64 69 | cache_alignment : 64 70 | address sizes : 36 bits physical, 48 bits virtual 71 | power management: [8] 72 | 73 | processor : 3 74 | vendor_id : GenuineIntel 75 | cpu family : 6 76 | model : 42 77 | model name : Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz 78 | stepping : 7 79 | cpu MHz : 3400.235 80 | cache size : 8192 KB 81 | physical id : 0 82 | siblings : 8 83 | core id : 3 84 | cpu cores : 4 85 | apicid : 6 86 | fpu : yes 87 | fpu_exception : yes 88 | cpuid level : 13 89 | wp : yes 90 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc arat pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm 91 | bogomips : 6800.11 92 | clflush size : 64 93 | cache_alignment : 64 94 | address sizes : 36 bits physical, 48 bits virtual 95 | power management: [8] 96 | 97 | processor : 4 98 | vendor_id : GenuineIntel 99 | cpu family : 6 100 | model : 42 101 | model name : Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz 102 | stepping : 7 103 | cpu MHz : 3400.235 104 | cache size : 8192 KB 105 | physical id : 0 106 | siblings : 8 107 | core id : 0 108 | cpu cores : 4 109 | apicid : 1 110 | fpu : yes 111 | fpu_exception : yes 112 | cpuid level : 13 113 | wp : yes 114 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc arat pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm 115 | bogomips : 6799.97 116 | clflush size : 64 117 | cache_alignment : 64 118 | address sizes : 36 bits physical, 48 bits virtual 119 | power management: [8] 120 | 121 | processor : 5 122 | vendor_id : GenuineIntel 123 | cpu family : 6 124 | model : 42 125 | model name : Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz 126 | stepping : 7 127 | cpu MHz : 3400.235 128 | cache size : 8192 KB 129 | physical id : 0 130 | siblings : 8 131 | core id : 1 132 | cpu cores : 4 133 | apicid : 3 134 | fpu : yes 135 | fpu_exception : yes 136 | cpuid level : 13 137 | wp : yes 138 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc arat pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm 139 | bogomips : 6800.06 140 | clflush size : 64 141 | cache_alignment : 64 142 | address sizes : 36 bits physical, 48 bits virtual 143 | power management: [8] 144 | 145 | processor : 6 146 | vendor_id : GenuineIntel 147 | cpu family : 6 148 | model : 42 149 | model name : Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz 150 | stepping : 7 151 | cpu MHz : 3400.235 152 | cache size : 8192 KB 153 | physical id : 0 154 | siblings : 8 155 | core id : 2 156 | cpu cores : 4 157 | apicid : 5 158 | fpu : yes 159 | fpu_exception : yes 160 | cpuid level : 13 161 | wp : yes 162 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc arat pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm 163 | bogomips : 6800.03 164 | clflush size : 64 165 | cache_alignment : 64 166 | address sizes : 36 bits physical, 48 bits virtual 167 | power management: [8] 168 | 169 | processor : 7 170 | vendor_id : GenuineIntel 171 | cpu family : 6 172 | model : 42 173 | model name : Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz 174 | stepping : 7 175 | cpu MHz : 3400.235 176 | cache size : 8192 KB 177 | physical id : 0 178 | siblings : 8 179 | core id : 3 180 | cpu cores : 4 181 | apicid : 7 182 | fpu : yes 183 | fpu_exception : yes 184 | cpuid level : 13 185 | wp : yes 186 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall nx rdtscp lm constant_tsc ida nonstop_tsc arat pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 sse4_2 popcnt lahf_lm 187 | bogomips : 6799.88 188 | clflush size : 64 189 | cache_alignment : 64 190 | address sizes : 36 bits physical, 48 bits virtual 191 | power management: [8] 192 | 193 | -------------------------------------------------------------------------------- /affinity/src/test/resources/i7.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2016-2025 chronicle.software 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | # 17 | 0=0,0,0 18 | 1=0,1,0 19 | 2=0,2,0 20 | 3=0,3,0 21 | 4=0,0,1 22 | 5=0,1,1 23 | 6=0,2,1 24 | 7=0,3,1 25 | -------------------------------------------------------------------------------- /affinity/src/test/resources/q6600.noht.cpuinfo: -------------------------------------------------------------------------------- 1 | processor : 0 2 | vendor_id : GenuineIntel 3 | cpu family : 6 4 | model : 15 5 | model name : Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz 6 | stepping : 11 7 | cpu MHz : 1596.000 8 | cache size : 4096 KB 9 | physical id : 0 10 | siblings : 4 11 | core id : 0 12 | cpu cores : 4 13 | apicid : 0 14 | initial apicid : 0 15 | fpu : yes 16 | fpu_exception : yes 17 | cpuid level : 10 18 | wp : yes 19 | flags : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm lahf_lm tpr_shadow vnmi flexpriority 20 | bogomips : 4810.72 21 | clflush size : 64 22 | cache_alignment : 64 23 | address sizes : 36 bits physical, 48 bits virtual 24 | power management: 25 | 26 | processor : 1 27 | vendor_id : GenuineIntel 28 | cpu family : 6 29 | model : 15 30 | model name : Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz 31 | stepping : 11 32 | cpu MHz : 1596.000 33 | cache size : 4096 KB 34 | physical id : 0 35 | siblings : 4 36 | core id : 2 37 | cpu cores : 4 38 | apicid : 2 39 | initial apicid : 2 40 | fpu : yes 41 | fpu_exception : yes 42 | cpuid level : 10 43 | wp : yes 44 | flags : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm lahf_lm tpr_shadow vnmi flexpriority 45 | bogomips : 4810.82 46 | clflush size : 64 47 | cache_alignment : 64 48 | address sizes : 36 bits physical, 48 bits virtual 49 | power management: 50 | 51 | processor : 2 52 | vendor_id : GenuineIntel 53 | cpu family : 6 54 | model : 15 55 | model name : Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz 56 | stepping : 11 57 | cpu MHz : 1596.000 58 | cache size : 4096 KB 59 | physical id : 0 60 | siblings : 4 61 | core id : 1 62 | cpu cores : 4 63 | apicid : 1 64 | initial apicid : 1 65 | fpu : yes 66 | fpu_exception : yes 67 | cpuid level : 10 68 | wp : yes 69 | flags : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm lahf_lm tpr_shadow vnmi flexpriority 70 | bogomips : 4810.81 71 | clflush size : 64 72 | cache_alignment : 64 73 | address sizes : 36 bits physical, 48 bits virtual 74 | power management: 75 | 76 | processor : 3 77 | vendor_id : GenuineIntel 78 | cpu family : 6 79 | model : 15 80 | model name : Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz 81 | stepping : 11 82 | cpu MHz : 1596.000 83 | cache size : 4096 KB 84 | physical id : 0 85 | siblings : 4 86 | core id : 3 87 | cpu cores : 4 88 | apicid : 3 89 | initial apicid : 3 90 | fpu : yes 91 | fpu_exception : yes 92 | cpuid level : 10 93 | wp : yes 94 | flags : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm lahf_lm tpr_shadow vnmi flexpriority 95 | bogomips : 4810.82 96 | clflush size : 64 97 | cache_alignment : 64 98 | address sizes : 36 bits physical, 48 bits virtual 99 | power management: 100 | 101 | -------------------------------------------------------------------------------- /affinity/src/test/resources/q6600.vm.cpuinfo: -------------------------------------------------------------------------------- 1 | processor : 0 2 | vendor_id : GenuineIntel 3 | cpu family : 6 4 | model : 15 5 | model name : Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz 6 | stepping : 11 7 | cpu MHz : 1596.000 8 | cache size : 4096 KB 9 | fpu : yes 10 | fpu_exception : yes 11 | cpuid level : 10 12 | wp : yes 13 | flags : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm lahf_lm tpr_shadow vnmi flexpriority 14 | bogomips : 4810.72 15 | clflush size : 64 16 | cache_alignment : 64 17 | address sizes : 36 bits physical, 48 bits virtual 18 | power management: 19 | 20 | processor : 1 21 | vendor_id : GenuineIntel 22 | cpu family : 6 23 | model : 15 24 | model name : Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz 25 | stepping : 11 26 | cpu MHz : 1596.000 27 | cache size : 4096 KB 28 | fpu : yes 29 | fpu_exception : yes 30 | cpuid level : 10 31 | wp : yes 32 | flags : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm lahf_lm tpr_shadow vnmi flexpriority 33 | bogomips : 4810.82 34 | clflush size : 64 35 | cache_alignment : 64 36 | address sizes : 36 bits physical, 48 bits virtual 37 | power management: 38 | 39 | processor : 2 40 | vendor_id : GenuineIntel 41 | cpu family : 6 42 | model : 15 43 | model name : Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz 44 | stepping : 11 45 | cpu MHz : 1596.000 46 | cache size : 4096 KB 47 | fpu : yes 48 | fpu_exception : yes 49 | cpuid level : 10 50 | wp : yes 51 | flags : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm lahf_lm tpr_shadow vnmi flexpriority 52 | bogomips : 4810.81 53 | clflush size : 64 54 | cache_alignment : 64 55 | address sizes : 36 bits physical, 48 bits virtual 56 | power management: 57 | 58 | processor : 3 59 | vendor_id : GenuineIntel 60 | cpu family : 6 61 | model : 15 62 | model name : Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz 63 | stepping : 11 64 | cpu MHz : 1596.000 65 | cache size : 4096 KB 66 | fpu : yes 67 | fpu_exception : yes 68 | cpuid level : 10 69 | wp : yes 70 | flags : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good pni dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm lahf_lm tpr_shadow vnmi flexpriority 71 | bogomips : 4810.82 72 | clflush size : 64 73 | cache_alignment : 64 74 | address sizes : 36 bits physical, 48 bits virtual 75 | power management: 76 | 77 | -------------------------------------------------------------------------------- /docs/images/Thread-Affinity_line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenHFT/Java-Thread-Affinity/28c10cb27faf862fec1b762c62795139de8f6a2c/docs/images/Thread-Affinity_line.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 4.0.0 20 | 21 | 22 | net.openhft 23 | java-parent-pom 24 | 1.27ea0 25 | 26 | 27 | 28 | Java-Thread-Affinity 29 | 3.27ea1-SNAPSHOT 30 | pom 31 | 32 | OpenHFT/Java-Thread-Affinity Parent 33 | Java Thread Affinity library 34 | 35 | 36 | affinity 37 | affinity-test 38 | 39 | 40 | 41 | scm:git:git@github.com:OpenHFT/Java-Thread-Affinity.git 42 | scm:git:git@github.com:OpenHFT/Java-Thread-Affinity.git 43 | scm:git:git@github.com:OpenHFT/Java-Thread-Affinity.git 44 | 45 | ea 46 | 47 | 48 | 49 | --------------------------------------------------------------------------------