Skip to content

Commit 11cb30d

Browse files
author
Rob Austin
committed
now instead of allocating any CPU will allocate a free CPU
1 parent 4628217 commit 11cb30d

6 files changed

Lines changed: 102 additions & 37 deletions

File tree

affinity/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
<modelVersion>4.0.0</modelVersion>
2929
<artifactId>affinity</artifactId>
30-
<version>3.0.7-SNAPSHOT</version>
30+
<version>3.1.0-SNAPSHOT</version>
3131
<packaging>bundle</packaging>
3232

3333
<name>OpenHFT/Java-Thread-Affinity/affinity</name>

affinity/src/main/java/net/openhft/affinity/Affinity.java

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import org.slf4j.Logger;
2222
import org.slf4j.LoggerFactory;
2323

24-
import java.io.IOException;
2524
import java.io.PrintWriter;
2625
import java.io.StringWriter;
2726
import java.lang.reflect.Field;
@@ -39,7 +38,7 @@ public enum Affinity {
3938
@NotNull
4039
private static final IAffinity AFFINITY_IMPL;
4140
private static Boolean JNAAvailable;
42-
private static LockCheck LOCK_CHECK = new LockCheck();
41+
4342

4443
static {
4544
String osName = System.getProperty("os.name");
@@ -156,16 +155,16 @@ public static BitSet getAffinity() {
156155
return AFFINITY_IMPL.getAffinity();
157156
}
158157

159-
public static void setAffinity(final BitSet affinity) {
160-
AFFINITY_IMPL.setAffinity(affinity);
161-
}
162-
163158
public static void setAffinity(int cpu) {
164159
BitSet affinity = new BitSet(Runtime.getRuntime().availableProcessors());
165160
affinity.set(cpu);
166161
setAffinity(affinity);
167162
}
168163

164+
public static void setAffinity(final BitSet affinity) {
165+
AFFINITY_IMPL.setAffinity(affinity);
166+
}
167+
169168
public static int getCpu() {
170169
return AFFINITY_IMPL.getCpu();
171170
}
@@ -198,20 +197,7 @@ public static boolean isJNAAvailable() {
198197
return JNAAvailable;
199198
}
200199

201-
public static long getPID() {
202-
String processName =
203-
java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
204-
return Long.parseLong(processName.split("@")[0]);
205-
}
206-
207200
public static AffinityLock acquireLock() {
208-
if (LockCheck.IS_LINUX)
209-
210-
try {
211-
LOCK_CHECK.isCoreAlreadyAssigned(getCpu(), getPID());
212-
} catch (IOException e) {
213-
// unknown state
214-
}
215201
return isNonForkingAffinityAvailable() ? NonForkingAffinityLock.acquireLock() : AffinityLock.acquireLock();
216202
}
217203

affinity/src/main/java/net/openhft/affinity/AffinityStrategies.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,38 @@
1616

1717
package net.openhft.affinity;
1818

19+
import java.io.IOException;
20+
1921
/**
2022
* Pre-defined strategies for determining which thread to pick next.
2123
*
2224
* @author peter.lawrey
2325
*/
2426
public enum AffinityStrategies implements AffinityStrategy {
27+
28+
2529
/**
2630
* Any free cpu.
2731
*/
2832
ANY {
2933
@Override
3034
public boolean matches(int cpuId, int cpuId2) {
35+
if (LockCheck.IS_LINUX) {
36+
if (cpuId == -1 && cpuId2 != -1)
37+
return isFreeCpu(cpuId2);
38+
else if (cpuId != -1 && cpuId2 == -1)
39+
return isFreeCpu(cpuId);
40+
}
3141
return true;
3242
}
43+
44+
private boolean isFreeCpu(int cpuId2) {
45+
try {
46+
return lc.isFreeCpu(cpuId2);
47+
} catch (IOException e) {
48+
return true;
49+
}
50+
}
3351
},
3452
/**
3553
* Must be a cpu on the same core.
@@ -73,5 +91,7 @@ public boolean matches(int cpuId, int cpuId2) {
7391
CpuLayout cpuLayout = AffinityLock.cpuLayout();
7492
return cpuLayout.socketId(cpuId) != cpuLayout.socketId(cpuId2);
7593
}
76-
}
94+
};
95+
96+
LockCheck lc = new LockCheck();
7797
}

affinity/src/main/java/net/openhft/affinity/LockCheck.java

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
class LockCheck {
1414

1515
static final String TMP = System.getProperty("java.io.tmpdir");
16+
public static final String TARGET = System.getProperty("project.build.directory", findTarget());
1617
private static final String OS = System.getProperty("os.name").toLowerCase();
1718
static final boolean IS_LINUX = OS.startsWith("linux");
18-
1919
private ThreadLocal<SimpleDateFormat> df = new ThreadLocal() {
2020

2121
@Override
@@ -33,6 +33,32 @@ private static String findTarget() {
3333
return TMP + "/target";
3434
}
3535

36+
public static long getPID() {
37+
String processName =
38+
java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
39+
return Long.parseLong(processName.split("@")[0]);
40+
}
41+
42+
boolean isFreeCpu(int cpu) throws IOException {
43+
long processID = getPID();
44+
45+
final File file = toFile(cpu);
46+
final boolean exists = file.exists();
47+
48+
if (!exists) {
49+
// create a lock file
50+
storePid(processID, file);
51+
return true;
52+
} else {
53+
int currentProcess = getProcessForCore(file);
54+
if (!isProcessRunning(currentProcess)) {
55+
replacePid(file, processID);
56+
return true;
57+
}
58+
return false;
59+
}
60+
}
61+
3662
/**
3763
* stores the process id for a give pid
3864
*
@@ -41,26 +67,35 @@ private static String findTarget() {
4167
* @return
4268
* @throws IOException
4369
*/
44-
boolean isCoreAlreadyAssigned(int core, long processID) throws IOException {
70+
private boolean isFreeCpu(int core, long processID) throws IOException {
4571

46-
final File file = new File(tmpDir(), "core-" + core + ".lock");
72+
final File file = toFile(core);
4773
final boolean exists = file.exists();
4874

4975
if (!exists) {
5076
// create a lock file
5177
storePid(processID, file);
5278
return true;
5379
} else {
54-
int currentProcess = getPid(file);
80+
int currentProcess = getProcessForCore(file);
5581
if (!isProcessRunning(currentProcess)) {
56-
replacePid(processID, file);
82+
replacePid(file, processID);
5783
return true;
5884
}
5985
return false;
6086
}
6187
}
6288

63-
private void replacePid(long processID, File file) throws IOException {
89+
@NotNull
90+
private File toFile(int core) {
91+
return new File(tmpDir(), "cpu-" + core + ".lock");
92+
}
93+
94+
void replacePid(int core, long processID) throws IOException {
95+
replacePid(toFile(core), processID);
96+
}
97+
98+
private void replacePid(File file, long processID) throws IOException {
6499
file.delete();
65100
storePid(processID, file);
66101
}
@@ -88,16 +123,15 @@ private void storePid(long processID, File coreFile) throws IOException {
88123
}
89124
}
90125

91-
int getPid(int core) throws IOException {
92-
return getPid(new File(tmpDir(), "core-" + core + ".lock"));
126+
int getProcessForCore(int core) throws IOException {
127+
return getProcessForCore(toFile(core));
93128
}
94129

95-
private int getPid(@NotNull File coreFile) throws IOException {
130+
private int getProcessForCore(@NotNull File coreFile) throws IOException {
96131

97132
try (LineNumberReader reader = new LineNumberReader(
98133
new BufferedReader(new InputStreamReader(new FileInputStream(coreFile), "utf-8")))) {
99134
String s = reader.readLine().trim();
100-
System.out.println("" + s);
101135
return Integer.parseInt(s);
102136
}
103137
}

affinity/src/main/java/net/openhft/affinity/LockInventory.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ public final synchronized void set(CpuLayout cpuLayout) {
7979
}
8080

8181
public final synchronized AffinityLock acquireLock(boolean bind, int cpuId, AffinityStrategy... strategies) {
82+
83+
8284
for (AffinityStrategy strategy : strategies) {
8385
// consider all processors except cpu 0 which is usually used by the OS.
8486
// if you have only one core, this library is not appropriate in any case.
Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,54 @@
11
package net.openhft.affinity;
22

33
import org.junit.Assert;
4+
import org.junit.Before;
45
import org.junit.Test;
56

67
import java.io.IOException;
78

9+
import static net.openhft.affinity.LockCheck.IS_LINUX;
10+
811
/**
912
* @author Rob Austin.
1013
*/
1114
public class LockCheckTest {
1215

13-
private static final int CORE = 1111;
1416
private static final int PROCESS_ID = 2222;
17+
private static int CORE = 1111;
18+
19+
@Before
20+
public void before() {
21+
System.setProperty("java.io.tmpdir", LockCheck.TMP + "/" + System.nanoTime());
22+
}
1523

1624
@Test
1725
public void test() throws IOException {
18-
LockCheck lockCheck = new LockCheck();
19-
lockCheck.isCoreAlreadyAssigned(CORE, PROCESS_ID);
20-
Assert.assertEquals(PROCESS_ID, lockCheck.getPid(CORE));
26+
if (IS_LINUX) {
27+
LockCheck lockCheck = new LockCheck();
28+
Assert.assertTrue(lockCheck.isFreeCpu(CORE));
29+
Assert.assertEquals(LockCheck.getPID(), lockCheck.getProcessForCore(CORE));
30+
}
2131
}
2232

2333
@Test
2434
public void testPidOnLinux() {
2535
final LockCheck lockCheck = new LockCheck();
2636

27-
if (LockCheck.IS_LINUX)
28-
Assert.assertTrue(lockCheck.isProcessRunning(Affinity.getPID()));
37+
if (IS_LINUX)
38+
Assert.assertTrue(lockCheck.isProcessRunning(LockCheck.getPID()));
39+
40+
}
2941

42+
@Test
43+
public void testReplace() throws IOException {
44+
CORE++;
45+
if (IS_LINUX) {
46+
LockCheck lockCheck = new LockCheck();
47+
Assert.assertTrue(lockCheck.isFreeCpu(CORE + 1));
48+
lockCheck.replacePid(CORE, 123L);
49+
Assert.assertEquals(123L, lockCheck.getProcessForCore(CORE));
50+
}
3051
}
52+
53+
3154
}

0 commit comments

Comments
 (0)