New Chronicle-Map

This commit is contained in:
leventov
2014-09-05 17:39:51 +04:00
parent 614308f38a
commit ea16356d46
95 changed files with 17623 additions and 2655 deletions
@@ -0,0 +1,84 @@
/*
* Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.openhft.chronicle.map.fromdocs;
import net.openhft.lang.model.constraints.MaxSize;
public interface BondVOInterface {
/* add support for entry based locking */
void busyLockEntry() throws InterruptedException;
void unlockEntry();
long getIssueDate();
void setIssueDate(long issueDate); /* time in millis */
long getMaturityDate();
void setMaturityDate(long maturityDate); /* time in millis */
long addAtomicMaturityDate(long toAdd);
boolean compareAndSwapCoupon(double expected, double value);
double getCoupon();
void setCoupon(double coupon);
double addAtomicCoupon(double toAdd);
String getSymbol();
void setSymbol(@MaxSize(20) String symbol);
// OpenHFT Off-Heap array[ ] processing notice ‘At’ suffix
void setMarketPxIntraDayHistoryAt(@MaxSize(7) int tradingDayHour, MarketPx mPx);
/* 7 Hours in the Trading Day:
* index_0 = 9.30am,
* index_1 = 10.30am,
…,
* index_6 = 4.30pm
*/
MarketPx getMarketPxIntraDayHistoryAt(int tradingDayHour);
/* nested interface - empowering an Off-Heap hierarchical “TIER of prices”
as array[ ] value */
interface MarketPx {
double getCallPx();
void setCallPx(double px);
double getParPx();
void setParPx(double px);
double getMaturityPx();
void setMaturityPx(double px);
double getBidPx();
void setBidPx(double px);
double getAskPx();
void setAskPx(double px);
}
}
@@ -0,0 +1,66 @@
/*
* Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.openhft.chronicle.map.fromdocs;
import net.openhft.chronicle.map.ChronicleMapBuilder;
import org.junit.Ignore;
import org.junit.Test;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import static org.junit.Assert.assertEquals;
/**
* Created by peter on 28/02/14.
*/
public class GettingStartedTest {
@Test
@Ignore
public void testTheCodeInGuide() throws IOException {
String tmpdir = System.getProperty("java.io.tmpdir");
Map<String, String> map = ChronicleMapBuilder.of(String.class, String.class)
.create(new File(tmpdir + "/shared.map"));
map.put("some.json", "missing");
map.get("some.json");
map.put("Hello", "World");
String hi = map.get("Hello");
map.put("Long String", "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789");
String json = "{\"menu\": {\n" +
" \"id\": \"file\",\n" +
" \"value\": \"File\",\n" +
" \"popup\": {\n" +
" \"menuitem\": [\n" +
" {\"value\": \"New\", \"onclick\": \"CreateNew()\"},\n" +
" {\"value\": \"Open\", \"onclick\": \"OpenDoc()\"},\n" +
" {\"value\": \"Close\", \"onclick\": \"CloseDoc()\"}\n" +
" ]\n" +
" }\n" +
"}}";
map.put("some.json", json);
String s2 = map.get("some.json");
assertEquals(json, s2);
((Closeable) map).close();
}
}
@@ -0,0 +1,151 @@
/*
* Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.openhft.chronicle.map.fromdocs;
import net.openhft.affinity.AffinitySupport;
import net.openhft.chronicle.map.ChronicleMap;
import net.openhft.chronicle.map.ChronicleMapBuilder;
import net.openhft.lang.model.DataValueClasses;
import org.junit.Ignore;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import static org.junit.Assert.assertEquals;
/**
* These code fragments will appear in an article on OpenHFT. These tests to ensure that the examples compile and behave as expected.
*/
public class OpenJDKAndHashMapExamplesTest {
private static final SimpleDateFormat YYYYMMDD = new SimpleDateFormat("yyyyMMdd");
private static final String TMP = System.getProperty("java.io.tmpdir");
private static long parseYYYYMMDD(String s) {
try {
return YYYYMMDD.parse(s).getTime();
} catch (ParseException e) {
throw new AssertionError(e);
}
}
@Test
@Ignore
public void bondExample() throws IOException, InterruptedException {
ChronicleMap<String, BondVOInterface> chm = ChronicleMapBuilder
.of(String.class, BondVOInterface.class)
.entrySize(512)
.create(new File(TMP + "/chm-myBondPortfolioCHM"));
BondVOInterface bondVO = DataValueClasses.newDirectReference(BondVOInterface.class);
chm.acquireUsing("369604103", bondVO);
bondVO.setIssueDate(parseYYYYMMDD("20130915"));
bondVO.setMaturityDate(parseYYYYMMDD("20140915"));
bondVO.setCoupon(5.0 / 100); // 5.0%
BondVOInterface.MarketPx mpx930 = bondVO.getMarketPxIntraDayHistoryAt(0);
mpx930.setAskPx(109.2);
mpx930.setBidPx(106.9);
BondVOInterface.MarketPx mpx1030 = bondVO.getMarketPxIntraDayHistoryAt(1);
mpx1030.setAskPx(109.7);
mpx1030.setBidPx(107.6);
ChronicleMap<String, BondVOInterface> chmB = ChronicleMapBuilder
.of(String.class, BondVOInterface.class)
.entrySize(320)
.create(new File(TMP + "/chm-myBondPortfolioCHM"));
// ZERO Copy but creates a new off heap reference each time
BondVOInterface bondVOB = chmB.get("369604103");
assertEquals(5.0 / 100, bondVOB.getCoupon(), 0.0);
BondVOInterface.MarketPx mpx930B = bondVOB.getMarketPxIntraDayHistoryAt(0);
assertEquals(109.2, mpx930B.getAskPx(), 0.0);
assertEquals(106.9, mpx930B.getBidPx(), 0.0);
BondVOInterface.MarketPx mpx1030B = bondVOB.getMarketPxIntraDayHistoryAt(1);
assertEquals(109.7, mpx1030B.getAskPx(), 0.0);
assertEquals(107.6, mpx1030B.getBidPx(), 0.0);
//ZERO-COPY
// our reusable, mutable off heap reference, generated from the interface.
BondVOInterface bondZC = DataValueClasses.newDirectReference(BondVOInterface.class);
// lookup the key and give me a reference to the data.
if (chm.getUsing("369604103", bondZC) != null) {
// found a key and bondZC has been set
// get directly without touching the rest of the record.
long _matDate = bondZC.getMaturityDate();
// write just this field, again we need to assume we are the only writer.
bondZC.setMaturityDate(parseYYYYMMDD("20440315"));
//demo of how to do OpenHFT off-heap array[ ] processing
int tradingHour = 2; //current trading hour intra-day
BondVOInterface.MarketPx mktPx = bondZC.getMarketPxIntraDayHistoryAt(tradingHour);
if (mktPx.getCallPx() < 103.50) {
mktPx.setParPx(100.50);
mktPx.setAskPx(102.00);
mktPx.setBidPx(99.00);
// setMarketPxIntraDayHistoryAt is not needed as we are using zero copy,
// the original has been changed.
}
}
// bondZC will be full of default values and zero length string the first time.
// from this point, all operations are completely record/entry local,
// no other resource is involved.
// now perform thread safe operations on my reference
bondZC.addAtomicMaturityDate(16 * 24 * 3600 * 1000L); //20440331
bondZC.addAtomicCoupon(-1 * bondZC.getCoupon()); //MT-safe! now a Zero Coupon Bond.
// say I need to do something more complicated
// set the Threads getId() to match the process id of the thread.
AffinitySupport.setThreadId();
bondZC.busyLockEntry();
try {
String str = bondZC.getSymbol();
if (str.equals("IBM_HY_2044"))
bondZC.setSymbol("OPENHFT_IG_2044");
} finally {
bondZC.unlockEntry();
}
// cleanup.
chm.close();
chmB.close();
new File("/dev/chm/myBondPortfolioCHM").delete();
}
}
@@ -0,0 +1,68 @@
/*
* Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.openhft.chronicle.map.fromdocs.pingpong_latency;
import net.openhft.chronicle.map.ChronicleMap;
import net.openhft.chronicle.map.fromdocs.BondVOInterface;
import java.io.IOException;
import java.util.Arrays;
import static net.openhft.lang.model.DataValueClasses.newDirectReference;
public class PingPongAddLeft {
public static void main(String... ignored) throws IOException {
ChronicleMap<String, BondVOInterface> chm = PingPongCASLeft.acquireCHM();
playPingPong(chm, +1, true, "PingPongAddLEFT");
}
static void playPingPong(ChronicleMap<String, BondVOInterface> chm, double add, boolean setFirst, final String desc) {
BondVOInterface bond1 = newDirectReference(BondVOInterface.class);
BondVOInterface bond2 = newDirectReference(BondVOInterface.class);
BondVOInterface bond3 = newDirectReference(BondVOInterface.class);
BondVOInterface bond4 = newDirectReference(BondVOInterface.class);
chm.acquireUsing("369604101", bond1);
chm.acquireUsing("369604102", bond2);
chm.acquireUsing("369604103", bond3);
chm.acquireUsing("369604104", bond4);
System.out.printf("\n\n" + desc + ": Timing off-heap operations on /dev/chm/RDR_DIM_Mock\n");
if (setFirst) {
bond1.setCoupon(add);
bond2.setCoupon(add);
bond3.setCoupon(add);
bond4.setCoupon(add);
}
int timeToCallNanoTime = 30;
int runs = 1000000;
long[] timings = new long[runs];
for (int j = 0; j < 100; j++) {
for (int i = 0; i < runs; i++) {
long _start = System.nanoTime();
bond1.addAtomicCoupon(add);
bond2.addAtomicCoupon(add);
bond3.addAtomicCoupon(add);
bond4.addAtomicCoupon(add);
timings[i] = (System.nanoTime() - _start - timeToCallNanoTime) / 4;
}
Arrays.sort(timings);
System.out.printf("#%d: atomic add coupon 50/90/99%%tile was %,d / %,d / %,d%n",
j, timings[runs / 2], timings[runs * 9 / 10], timings[runs * 99 / 100]);
}
}
}
@@ -0,0 +1,33 @@
/*
* Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.openhft.chronicle.map.fromdocs.pingpong_latency;
import net.openhft.chronicle.map.ChronicleMap;
import net.openhft.chronicle.map.fromdocs.BondVOInterface;
import java.io.IOException;
import static net.openhft.chronicle.map.fromdocs.pingpong_latency.PingPongAddLeft.playPingPong;
public class PingPongAddRight {
public static void main(String... ignored) throws IOException {
ChronicleMap<String, BondVOInterface> chm = PingPongCASLeft.acquireCHM();
playPingPong(chm, -1, false, "PingPongAddRIGHT");
}
}
@@ -0,0 +1,99 @@
/*
* Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.openhft.chronicle.map.fromdocs.pingpong_latency;
import net.openhft.affinity.AffinitySupport;
import net.openhft.chronicle.map.ChronicleMap;
import net.openhft.chronicle.map.ChronicleMapBuilder;
import net.openhft.chronicle.map.fromdocs.BondVOInterface;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import static net.openhft.lang.model.DataValueClasses.newDirectReference;
/* on an i7-4500 laptop.
PingPongLEFT: Timing 1 x off-heap operations on /dev/chm/RDR_DIM_Mock
#0: compareAndSwapCoupon() 50/90/99%tile was 41 / 52 / 132
#1: compareAndSwapCoupon() 50/90/99%tile was 40 / 56 / 119
#2: compareAndSwapCoupon() 50/90/99%tile was 39 / 48 / 54
#3: compareAndSwapCoupon() 50/90/99%tile was 39 / 48 / 56
#4: compareAndSwapCoupon() 50/90/99%tile was 39 / 48 / 54
#5: compareAndSwapCoupon() 50/90/99%tile was 39 / 48 / 54
#6: compareAndSwapCoupon() 50/90/99%tile was 39 / 48 / 55
#7: compareAndSwapCoupon() 50/90/99%tile was 39 / 48 / 55
#8: compareAndSwapCoupon() 50/90/99%tile was 39 / 48 / 54
#9: compareAndSwapCoupon() 50/90/99%tile was 39 / 48 / 54
*/
public class PingPongCASLeft {
public static void main(String... ignored) throws IOException {
ChronicleMap<String, BondVOInterface> chm = PingPongCASLeft.acquireCHM();
playPingPong(chm, 4, 5, true, "PingPongCASLEFT");
}
static void playPingPong(ChronicleMap<String, BondVOInterface> chm, double _coupon, double _coupon2, boolean setFirst, final String desc) {
BondVOInterface bond1 = newDirectReference(BondVOInterface.class);
BondVOInterface bond2 = newDirectReference(BondVOInterface.class);
BondVOInterface bond3 = newDirectReference(BondVOInterface.class);
BondVOInterface bond4 = newDirectReference(BondVOInterface.class);
chm.acquireUsing("369604101", bond1);
chm.acquireUsing("369604102", bond2);
chm.acquireUsing("369604103", bond3);
chm.acquireUsing("369604104", bond4);
System.out.printf("\n\n" + desc + ": Timing 1 x off-heap operations on /dev/chm/RDR_DIM_Mock\n");
if (setFirst) {
bond1.setCoupon(_coupon);
bond2.setCoupon(_coupon);
bond3.setCoupon(_coupon);
bond4.setCoupon(_coupon);
}
int timeToCallNanoTime = 30;
int runs = 1000000;
long[] timings = new long[runs];
for (int j = 0; j < 10; j++) {
for (int i = 0; i < runs; i++) {
long _start = System.nanoTime(); //
while (!bond1.compareAndSwapCoupon(_coupon, _coupon2)) ;
while (!bond2.compareAndSwapCoupon(_coupon, _coupon2)) ;
while (!bond3.compareAndSwapCoupon(_coupon, _coupon2)) ;
while (!bond4.compareAndSwapCoupon(_coupon, _coupon2)) ;
timings[i] = (System.nanoTime() - _start - timeToCallNanoTime) / 4;
}
Arrays.sort(timings);
System.out.printf("#%d: compareAndSwapCoupon() 50/90/99%%tile was %,d / %,d / %,d%n",
j, timings[runs / 2], timings[runs * 9 / 10], timings[runs * 99 / 100]);
}
}
static ChronicleMap<String, BondVOInterface> acquireCHM() throws IOException {
// ensure thread ids are globally unique.
AffinitySupport.setThreadId();
String TMP = System.getProperty("java.io.tmpdir");
return ChronicleMapBuilder.of(String.class, BondVOInterface.class)
.entries(16)
.entrySize(64)
.create(new File(TMP + "/BondPortfolioCHM"));
}
}
@@ -0,0 +1,32 @@
/*
* Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.openhft.chronicle.map.fromdocs.pingpong_latency;
import net.openhft.chronicle.map.ChronicleMap;
import net.openhft.chronicle.map.fromdocs.BondVOInterface;
import java.io.IOException;
import static net.openhft.chronicle.map.fromdocs.pingpong_latency.PingPongCASLeft.playPingPong;
public class PingPongCASRight {
public static void main(String... ignored) throws IOException {
ChronicleMap<String, BondVOInterface> chm = PingPongCASLeft.acquireCHM();
playPingPong(chm, 5, 4, false, "PingPongCASLEFT");
}
}
@@ -0,0 +1,85 @@
/*
* Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.openhft.chronicle.map.fromdocs.pingpong_latency;
import net.openhft.chronicle.map.ChronicleMap;
import net.openhft.chronicle.map.fromdocs.BondVOInterface;
import java.io.IOException;
import java.util.Arrays;
import static net.openhft.lang.model.DataValueClasses.newDirectReference;
public class PingPongLockLeft {
public static void main(String... ignored) throws IOException, InterruptedException {
ChronicleMap<String, BondVOInterface> chm = PingPongCASLeft.acquireCHM();
playPingPong(chm, 4, 5, true, "PingPongLockLEFT");
}
static void playPingPong(ChronicleMap<String, BondVOInterface> chm, double _coupon, double _coupon2, boolean setFirst, final String desc) throws InterruptedException {
BondVOInterface bond1 = newDirectReference(BondVOInterface.class);
BondVOInterface bond2 = newDirectReference(BondVOInterface.class);
BondVOInterface bond3 = newDirectReference(BondVOInterface.class);
BondVOInterface bond4 = newDirectReference(BondVOInterface.class);
chm.acquireUsing("369604101", bond1);
chm.acquireUsing("369604102", bond2);
chm.acquireUsing("369604103", bond3);
chm.acquireUsing("369604104", bond4);
System.out.printf("\n\n" + desc + ": Timing 1 x off-heap operations on " + chm.file() + "\n");
if (setFirst) {
bond1.setCoupon(_coupon);
bond2.setCoupon(_coupon);
bond3.setCoupon(_coupon);
bond4.setCoupon(_coupon);
}
int timeToCallNanoTime = 30;
int runs = 1000000;
long[] timings = new long[runs];
for (int j = 0; j < 10; j++) {
for (int i = 0; i < runs; i++) {
long _start = System.nanoTime();
toggleCoupon(bond1, _coupon, _coupon2);
toggleCoupon(bond2, _coupon, _coupon2);
toggleCoupon(bond3, _coupon, _coupon2);
toggleCoupon(bond4, _coupon, _coupon2);
timings[i] = (System.nanoTime() - _start - timeToCallNanoTime) / 4;
}
Arrays.sort(timings);
System.out.printf("#%d: lock,compare,set,unlock 50/90/99%%tile was %,d / %,d / %,d%n",
j, timings[runs / 2], timings[runs * 9 / 10], timings[runs * 99 / 100]);
}
}
private static void toggleCoupon(BondVOInterface bond, double _coupon, double _coupon2) throws InterruptedException {
for (int i = 0; ; i++) {
bond.busyLockEntry();
try {
if (bond.getCoupon() == _coupon) {
bond.setCoupon(_coupon2);
return;
}
if (i > 1000)
Thread.yield();
} finally {
bond.unlockEntry();
}
}
}
}
@@ -0,0 +1,30 @@
/*
* Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.openhft.chronicle.map.fromdocs.pingpong_latency;
import net.openhft.chronicle.map.ChronicleMap;
import net.openhft.chronicle.map.fromdocs.BondVOInterface;
import java.io.IOException;
public class PingPongLockRight {
public static void main(String... ignored) throws IOException, InterruptedException {
ChronicleMap<String, BondVOInterface> chm = PingPongCASLeft.acquireCHM();
PingPongLockLeft.playPingPong(chm, 5, 4, false, "PingPongLockRIGHT");
}
}