MongoDB ACKNOWLEDGED write concern faster than UNACKNOWLEDGED? - java

I've got a very simple test program that performs faster with ACKNOWLEDGED bulk inserts than with UNACKNOWLEDGED. And it's not just a little faster - I'm seeing a factor of nearly 100!
My understanding of the difference between these two write concerns is solely that with ACKNOWLEDGED the client waits for confirmation from the server that the operation has been executed (but not necessarily made durable), while with UNACKNOWLEDGED the client only knows that the request made it out onto the wire. So it would seem preposterous that the former could actually perform at a higher speed, yet that's what I'm seeing.
I'm using the Java driver (v2.12.0) with Oracle's Java JDK v1.7.0_71, and mongo version 3.0.0 on 64-bit Windows 7. I'm running mongod, completely out-of-the-box (fresh install), no sharding or anything. And before each test I ensure that the collection is empty and has no non-default indexes.
I would appreciate any insight into why I'm consistently seeing the opposite of what I'd expect.
Thanks.
Here's my code:
package test;
import com.mongodb.BasicDBObject;
import com.mongodb.BulkWriteOperation;
import com.mongodb.BulkWriteResult;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;
import com.mongodb.ServerAddress;
import com.mongodb.WriteConcern;
import java.util.Arrays;
public class Test {
private static final int BATCHES = 100;
private static final int BATCH_SIZE = 1000;
private static final int COUNT = BATCHES * BATCH_SIZE;
public static void main(String[] argv) throws Exception {
DBCollection coll = new MongoClient(new ServerAddress()).getDB("test").getCollection("test");
for (String wcName : Arrays.asList("UNACKNOWLEDGED", "ACKNOWLEDGED")) {
WriteConcern wc = (WriteConcern) WriteConcern.class.getField(wcName).get(null);
coll.dropIndexes();
coll.remove(new BasicDBObject());
long start = System.currentTimeMillis();
BulkWriteOperation bulkOp = coll.initializeUnorderedBulkOperation();
for (int i = 1; i < COUNT; i++) {
DBObject doc = new BasicDBObject().append("int", i).append("string", Integer.toString(i));
bulkOp.insert(doc);
if (i % BATCH_SIZE == 0) {
BulkWriteResult results = bulkOp.execute(wc);
if (wc == WriteConcern.ACKNOWLEDGED && results.getInsertedCount() != 1000) {
throw new RuntimeException("Bogus insert count: " + results.getInsertedCount());
}
bulkOp = coll.initializeUnorderedBulkOperation();
}
}
long time = System.currentTimeMillis() - start;
double rate = COUNT / (time / 1000.0);
System.out.printf("%s[w=%s,j=%s]: Inserted %d documents in %s # %f/sec\n",
wcName, wc.getW(), wc.getJ(), COUNT, duration(time), rate);
}
}
private static String duration(long msec) {
return String.format("%d:%02d:%02d.%03d",
msec / (60 * 60 * 1000),
(msec % (60 * 60 * 1000)) / (60 * 1000),
(msec % (60 * 1000)) / 1000,
msec % 1000);
}
}
And here's typical output:
UNACKNOWLEDGED[w=0,j=false]: Inserted 100000 documents in 0:01:27.025 # 1149.095088/sec
ACKNOWLEDGED[w=1,j=false]: Inserted 100000 documents in 0:00:00.927 # 107874.865156/sec
EDIT
Ran more extensive tests, per request from Markus W. Mahlberg. For these tests, I ran the code with four write concerns: UNACKNOWLEDGED, ACKNOWLEDGED, JOURNALED, and FSYNCED. (I would expect this order to show decreasing speed.) I ran 112 repetitions, each of which performed 100 batches of 1000 inserts under each of the four write concerns, each time into an empty collection with no indexes. Code was identical to original post but with two additional write concerns, and with output to CSV format for easy analysis.
Results summary:
UNACKNOWLEDGED: 1147.105004 docs/sec avg, std dev 27.88577035
ACKNOWLEDGED: 77539.27653 docs/sec avg, std dev 1567.520303
JOURNALED: 29574.45243 docs/sec avg, std dev 123.9927554
FSYNCED: 29567.02467 docs/sec avg, std dev 147.6150994
The huge inverted performance difference between UNACKNOWLEDGED and ACKNOWLEDGED is what's got me baffled.
Here's the raw data if anyone cares for it ("time" is elapsed msec for 100*1000 insertions; "rate" is docs/second):
"UNACK time","UNACK rate","ACK time","ACK rate","JRNL time","JRNL rate","FSYNC time","FSYNC rate"
92815,1077.4120562409094,1348,74183.9762611276,3380,29585.798816568047,3378,29603.31557134399
90209,1108.5368422219512,1303,76745.97083653108,3377,29612.081729345577,3375,29629.62962962963
91089,1097.8273995762386,1319,75815.01137225171,3382,29568.30277942046,3413,29299.73630237328
90159,1109.1516099335618,1320,75757.57575757576,3375,29629.62962962963,3377,29612.081729345577
89922,1112.0749093658949,1315,76045.62737642587,3380,29585.798816568047,3376,29620.853080568722
89997,1111.1481493827573,1306,76569.67840735069,3381,29577.048210588586,3379,29594.55460195324
90141,1109.373093264996,1319,75815.01137225171,3386,29533.372711163614,3378,29603.31557134399
89771,1113.9454835080371,1325,75471.69811320755,3387,29524.65308532625,3521,28401.022436807725
89716,1114.6283828971423,1325,75471.69811320755,3379,29594.55460195324,3379,29594.55460195324
90205,1108.5859985588381,1323,75585.78987150417,3377,29612.081729345577,3376,29620.853080568722
90092,1109.976468498868,1328,75301.2048192771,3382,29568.30277942046,3379,29594.55460195324
89822,1113.3129968159249,1322,75642.965204236,3385,29542.097488921714,3383,29559.562518474726
89821,1113.3253916122064,1310,76335.87786259541,3380,29585.798816568047,3383,29559.562518474726
89945,1111.7905386625162,1318,75872.53414264036,3379,29594.55460195324,3379,29594.55460195324
89917,1112.1367483345753,1352,73964.49704142011,3381,29577.048210588586,3377,29612.081729345577
90358,1106.7088691648773,1303,76745.97083653108,3377,29612.081729345577,3380,29585.798816568047
90187,1108.8072560346836,1348,74183.9762611276,3387,29524.65308532625,3395,29455.081001472754
90634,1103.3387029150208,1322,75642.965204236,3384,29550.827423167848,3381,29577.048210588586
90148,1109.2869503483162,1331,75131.48009015778,3389,29507.22927117144,3381,29577.048210588586
89767,1113.9951207013714,1321,75700.22710068131,3380,29585.798816568047,3382,29568.30277942046
89910,1112.2233344455567,1321,75700.22710068131,3381,29577.048210588586,3385,29542.097488921714
89852,1112.9412812180028,1316,75987.84194528875,3381,29577.048210588586,3401,29403.116730373422
89537,1116.8567184515898,1319,75815.01137225171,3380,29585.798816568047,3380,29585.798816568047
89763,1114.0447623185498,1331,75131.48009015778,3380,29585.798816568047,3382,29568.30277942046
90070,1110.2475852115022,1325,75471.69811320755,3383,29559.562518474726,3378,29603.31557134399
89771,1113.9454835080371,1302,76804.91551459293,3389,29507.22927117144,3378,29603.31557134399
90518,1104.7526458825869,1325,75471.69811320755,3383,29559.562518474726,3380,29585.798816568047
90314,1107.2480457071995,1322,75642.965204236,3380,29585.798816568047,3384,29550.827423167848
89874,1112.6688474976079,1329,75244.54477050414,3386,29533.372711163614,3379,29594.55460195324
89954,1111.6793027547415,1318,75872.53414264036,3381,29577.048210588586,3381,29577.048210588586
89903,1112.3099340400208,1325,75471.69811320755,3379,29594.55460195324,3388,29515.9386068477
89842,1113.0651588343983,1314,76103.500761035,3382,29568.30277942046,3377,29612.081729345577
89746,1114.2557885588217,1325,75471.69811320755,3378,29603.31557134399,3385,29542.097488921714
93249,1072.3975592231552,1327,75357.95026375283,3381,29577.048210588586,3377,29612.081729345577
93638,1067.9425019756936,1331,75131.48009015778,3377,29612.081729345577,3392,29481.132075471698
87775,1139.2765593847905,1340,74626.86567164179,3379,29594.55460195324,3378,29603.31557134399
86495,1156.136192843517,1271,78678.20613690009,3375,29629.62962962963,3376,29620.853080568722
85584,1168.442699570013,1276,78369.90595611285,3432,29137.529137529138,3376,29620.853080568722
86648,1154.094728095282,1278,78247.2613458529,3382,29568.30277942046,3411,29316.91586045148
85745,1166.2487608606916,1274,78492.93563579278,3380,29585.798816568047,3363,29735.355337496283
85813,1165.3246011676551,1279,78186.08287724786,3375,29629.62962962963,3376,29620.853080568722
85831,1165.0802157728558,1288,77639.75155279503,3376,29620.853080568722,3377,29612.081729345577
85807,1165.4060857505797,1259,79428.11755361399,3466,28851.702250432772,3375,29629.62962962963
85964,1163.2776511097668,1258,79491.2559618442,3378,29603.31557134399,3378,29603.31557134399
85854,1164.7680946723508,1257,79554.49482895785,3382,29568.30277942046,3375,29629.62962962963
85787,1165.6777833471272,1257,79554.49482895785,3377,29612.081729345577,3377,29612.081729345577
85537,1169.084723569917,1272,78616.35220125786,3377,29612.081729345577,3377,29612.081729345577
85408,1170.8505058074186,1271,78678.20613690009,3375,29629.62962962963,3425,29197.080291970804
85577,1168.5382754712132,1261,79302.14115781126,3378,29603.31557134399,3375,29629.62962962963
85663,1167.365140142185,1261,79302.14115781126,3377,29612.081729345577,3378,29603.31557134399
85812,1165.3381811401669,1273,78554.59544383347,3377,29612.081729345577,3378,29603.31557134399
85783,1165.7321380693145,1273,78554.59544383347,3377,29612.081729345577,3376,29620.853080568722
85682,1167.106276697556,1280,78125.0,3381,29577.048210588586,3376,29620.853080568722
85753,1166.1399601180133,1260,79365.07936507936,3379,29594.55460195324,3377,29612.081729345577
85573,1168.5928972923703,1332,75075.07507507507,3377,29612.081729345577,3377,29612.081729345577
86206,1160.0120641254668,1263,79176.56373713381,3376,29620.853080568722,3383,29559.562518474726
85593,1168.31983923919,1264,79113.92405063291,3380,29585.798816568047,3378,29603.31557134399
85903,1164.1036983574495,1261,79302.14115781126,3378,29603.31557134399,3377,29612.081729345577
85516,1169.3718134618082,1277,78308.53563038372,3375,29629.62962962963,3376,29620.853080568722
85553,1168.8660830128692,1291,77459.3338497289,3490,28653.295128939826,3377,29612.081729345577
85550,1168.907071887785,1293,77339.52049497294,3379,29594.55460195324,3379,29594.55460195324
85610,1168.0878402055835,1298,77041.60246533128,3384,29550.827423167848,3378,29603.31557134399
85522,1169.2897733916418,1267,78926.59826361484,3379,29594.55460195324,3379,29594.55460195324
85595,1168.2925404521293,1276,78369.90595611285,3379,29594.55460195324,3376,29620.853080568722
85451,1170.2613193526115,1286,77760.49766718507,3376,29620.853080568722,3391,29489.82601002654
85792,1165.609847071988,1252,79872.20447284346,3382,29568.30277942046,3376,29620.853080568722
86501,1156.0559993526085,1255,79681.2749003984,3379,29594.55460195324,3379,29594.55460195324
85718,1166.616113301757,1269,78802.20646178094,3382,29568.30277942046,3376,29620.853080568722
85605,1168.156065650371,1265,79051.38339920949,3378,29603.31557134399,3380,29585.798816568047
85398,1170.9876109510762,1274,78492.93563579278,3377,29612.081729345577,3395,29455.081001472754
86370,1157.809424568716,1273,78554.59544383347,3376,29620.853080568722,3376,29620.853080568722
85905,1164.0765962400326,1280,78125.0,3379,29594.55460195324,3379,29594.55460195324
86020,1162.5203441060219,1285,77821.01167315176,3375,29629.62962962963,3376,29620.853080568722
85726,1166.5072440099852,1272,78616.35220125786,3380,29585.798816568047,3380,29585.798816568047
85628,1167.8422945765403,1270,78740.15748031496,3379,29594.55460195324,3376,29620.853080568722
85989,1162.93944574306,1258,79491.2559618442,3376,29620.853080568722,3378,29603.31557134399
85981,1163.047650062223,1276,78369.90595611285,3376,29620.853080568722,3376,29620.853080568722
86558,1155.2947156819703,1269,78802.20646178094,3385,29542.097488921714,3378,29603.31557134399
85745,1166.2487608606916,1293,77339.52049497294,3378,29603.31557134399,3375,29629.62962962963
85544,1168.9890582624148,1266,78988.94154818325,3376,29620.853080568722,3377,29612.081729345577
85536,1169.0983913206135,1268,78864.35331230283,3380,29585.798816568047,3380,29585.798816568047
85477,1169.9053546568082,1278,78247.2613458529,3388,29515.9386068477,3377,29612.081729345577
85434,1170.4941826439124,1253,79808.45969672786,3378,29603.31557134399,3375,29629.62962962963
85609,1168.1014846569872,1276,78369.90595611285,3364,29726.516052318668,3376,29620.853080568722
85740,1166.316771635176,1258,79491.2559618442,3377,29612.081729345577,3377,29612.081729345577
85640,1167.6786548341897,1266,78988.94154818325,3378,29603.31557134399,3377,29612.081729345577
85648,1167.569587147394,1281,78064.012490242,3378,29603.31557134399,3376,29620.853080568722
85697,1166.9019919017,1287,77700.0777000777,3377,29612.081729345577,3378,29603.31557134399
85696,1166.9156086631815,1256,79617.83439490446,3379,29594.55460195324,3376,29620.853080568722
85782,1165.7457275419085,1258,79491.2559618442,3379,29594.55460195324,3379,29594.55460195324
85837,1164.9987767512844,1264,79113.92405063291,3379,29594.55460195324,3376,29620.853080568722
85632,1167.7877428998504,1278,78247.2613458529,3380,29585.798816568047,3459,28910.089621277824
85517,1169.3581393173288,1256,79617.83439490446,3379,29594.55460195324,3380,29585.798816568047
85990,1162.925921618793,1302,76804.91551459293,3380,29585.798816568047,3377,29612.081729345577
86690,1153.535586572846,1281,78064.012490242,3375,29629.62962962963,3381,29577.048210588586
86045,1162.1825788831425,1274,78492.93563579278,3380,29585.798816568047,3383,29559.562518474726
86146,1160.820003250296,1274,78492.93563579278,3382,29568.30277942046,3418,29256.87536571094
86027,1162.4257500552153,1280,78125.0,3382,29568.30277942046,3381,29577.048210588586
85992,1162.8988743138896,1281,78064.012490242,3376,29620.853080568722,3380,29585.798816568047
85857,1164.727395553071,1288,77639.75155279503,3382,29568.30277942046,3376,29620.853080568722
85853,1164.7816616775185,1284,77881.6199376947,3375,29629.62962962963,3374,29638.41138114997
86069,1161.8585088707896,1295,77220.07722007722,3378,29603.31557134399,3378,29603.31557134399
85842,1164.930919596468,1296,77160.49382716049,3378,29603.31557134399,3376,29620.853080568722
86195,1160.160102094089,1301,76863.95080707148,3376,29620.853080568722,3379,29594.55460195324
85523,1169.2761011657683,1305,76628.35249042146,3376,29620.853080568722,3378,29603.31557134399
85752,1166.1535591006625,1275,78431.37254901961,3374,29638.41138114997,3377,29612.081729345577
85441,1170.3982865369085,1286,77760.49766718507,3377,29612.081729345577,3380,29585.798816568047
85566,1168.6884977678048,1265,79051.38339920949,3377,29612.081729345577,3380,29585.798816568047
85523,1169.2761011657683,1267,78926.59826361484,3377,29612.081729345577,3376,29620.853080568722
86152,1160.7391586962578,1285,77821.01167315176,3374,29638.41138114997,3378,29603.31557134399
85684,1167.0790345922226,1272,78616.35220125786,3378,29603.31557134399,3384,29550.827423167848
86252,1159.3934053703103,1271,78678.20613690009,3376,29620.853080568722,3377,29612.081729345577

Related

Strange bottleneck with apache HttpClients (sync and async)

I'm trying to test the limits of the apache http client libraries and I'm running into a strange bottleneck. My test consists of the following:
A wiremock server that simulates a fixed 80ms delay
A unit test which uses an org.apache.http.impl.nio.client.CloseableHttpAsyncClient to make a configurable number of requests to the wiremock server as fast as possible, while gathering statistics.
A unit test which uses an org.apache.http.impl.client.CloseableHttpClient to make a configurable number of requests to the wiremock server as fast as possible, from a configurable number of threads, while gathering statistics.
A unit test which uses an org.springframework.web.reactive.function.client.WebClient to make a configurable number of requests to the wiremock server as fast as possible, while gathering statistics.
All of the the tests show the same performance numbers of 570 requests / second on my local machine. The CPU is very low when running these tests, about 5% utilization. So I can assume that the bottleneck is not in the CPU, but rather somewhere else...
My question is where is this bottleneck and how can we widen it?
My System Configuration:
Processor: 3.1 GHz Quad-Core Intel Core i7
Memory: 16 GB 2133 MHz LPDDR3
OS: OSX 10.15.5
Java version: 11.0.4
My Unit Test:
package com.blakeparmeter.bottleneck_mystery;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.net.URI;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.stream.IntStream;
/**
* Used to illustrate a performance bottleneck with the apache HttpClients
*/
public class BottleneckTest {
// Test variables
final int totalTests = 5_000;
final long messageInterval = 1000; //ms
final URI testUri = URI.create("http://localhost:5000/wait/fixed/empty");
#Test
public void testSync() throws InterruptedException, ExecutionException {
final int numThreads = 100;
// Creates the sync client (unit under test)
final CloseableHttpClient unitUnderTest = HttpClientBuilder
.create()
.setMaxConnTotal(5000)
.setMaxConnPerRoute(5000)
.build();
// Run the test on an executor, send results to a stats aggregator
final ForkJoinPool executor = new ForkJoinPool(numThreads);
final StatsAggregator statsAggregator = new StatsAggregator(totalTests, messageInterval);
executor.submit(() -> IntStream.range(0, numThreads)
.parallel()
.forEach(threadNum -> IntStream.range(0, totalTests / numThreads).forEach(testNum -> {
final long runStart = System.currentTimeMillis();
try (final CloseableHttpResponse response = unitUnderTest.execute(new HttpGet(testUri))) {
// we don't need to do anything with the response, just make sure it's sent.
} catch (final IOException e) {
Assertions.fail(e);
}
statsAggregator.addTestDuration(System.currentTimeMillis() - runStart);
})))
.get();
// print the stats one last time (await is not needed since we wait on the executor)
statsAggregator.printStats();
}
#Test
public void testAsync() throws InterruptedException {
// Creates the async client (unit under test)
final CloseableHttpAsyncClient unitUnderTest = HttpAsyncClients.custom()
.setMaxConnTotal(5000)
.setMaxConnPerRoute(5000)
.build();
unitUnderTest.start();
// Runs all of the tests, sends results to a stats aggregator
final CountDownLatch testCountdown = new CountDownLatch(totalTests);
final StatsAggregator statsAggregator = new StatsAggregator(totalTests, messageInterval);
IntStream.range(0, totalTests).forEach(testNum -> {
final long runStart = System.currentTimeMillis();
unitUnderTest.execute(new HttpGet(testUri), new FutureCallback<>() {
#Override
public void completed(final HttpResponse response) {
statsAggregator.addTestDuration(System.currentTimeMillis() - runStart);
testCountdown.countDown();
}
#Override
public void failed(final Exception ex) {
Assertions.fail(ex.getMessage());
}
#Override
public void cancelled() {
Assertions.fail("Http Request Cancelled");
}
});
});
// await execution then print the stats one last time
testCountdown.await();
statsAggregator.printStats();
}
#Test
public void testReactive() {
final WebClient unitUnderTest = WebClient.builder().build();
// Runs all of the tests, sends results to a stats aggregator
final StatsAggregator statsAggregator = new StatsAggregator(totalTests, messageInterval);
Flux.range(0, totalTests)
.flatMap(testNum -> {
final long runStart = System.currentTimeMillis();
return unitUnderTest.get()
.uri(testUri)
.retrieve()
.bodyToMono(Object.class)
.doOnSuccess(obj -> statsAggregator.addTestDuration(System.currentTimeMillis() - runStart));
})
.then()
.block();
// print the stats one last time
statsAggregator.printStats();
}
}
StatsAggregator.java:
package com.blakeparmeter.bottleneck_mystery;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
/**
* #author Blake L. Parmeter
*/
public class StatsAggregator {
private static final DecimalFormat testCompleteFormat = new DecimalFormat("###,###,###");
private static final DecimalFormat avgRequestFormat = new DecimalFormat("###,###.##");
private final long start = System.currentTimeMillis();
private final List<Long> times;
private final TimerTask renderStatisticsTask;
// Creates a timer task to calculate and render runtime stats in realtime.
public StatsAggregator(final int totalTests, final long messageIntervalMillis) {
this.times = new ArrayList<>(totalTests);
renderStatisticsTask = new TimerTask() {
private Long lastLogTime = null;
private Integer lastLogSize = null;
#Override
public void run() {
// Init variables needed for calculations
final long logTime = System.currentTimeMillis();
final List<Long> statsCopy;
synchronized (times) {
if (!times.isEmpty()) {
statsCopy = new ArrayList<>(times);
} else {
System.out.println("No statistics have been loaded. Statistics will not be calculated.");
return;
}
}
Collections.sort(statsCopy);
// print execution completion status
System.out.println();
final double percentComplete = ((double) statsCopy.size() / (double) totalTests);
final long runtime = logTime - start; //ms
final double estimatedTimeRemaining = ((double) runtime / percentComplete) - (double) runtime; //ms
System.out.println(testCompleteFormat.format(statsCopy.size())
+ "\tTests completed of:"
+ testCompleteFormat.format(totalTests)
+ "\t"
+ avgRequestFormat.format(percentComplete * 100)
+ "% complete. "
+ "Running for: "
+ runtime / 1000d
+ " seconds. "
+ "Estimated Time remaining: "
+ testCompleteFormat.format(estimatedTimeRemaining / 1000d)
+ " seconds.");
// print running average requests / second
String sinceLastLogStats = "";
if (lastLogSize != null && lastLogTime != null) {
double numSinceLastLog = (double) statsCopy.size() - lastLogSize;
double timeSinceLastLog = (double) logTime - lastLogTime;
double avgReqPerSecSinceLastLogSec = 1000 * (numSinceLastLog / timeSinceLastLog);
sinceLastLogStats = "\tavg req/sec:"
+ avgRequestFormat.format(avgReqPerSecSinceLastLogSec)
+ "(since last run)";
}
lastLogSize = statsCopy.size();
lastLogTime = logTime;
double avgReqPerSec = 1000 * ((double) statsCopy.size() / (double) (logTime - start));
System.out.println("\tavg req/sec:"
+ avgRequestFormat.format(avgReqPerSec)
+ "(total)"
+ sinceLastLogStats);
// print average min and max
double avg = (double) statsCopy.stream().reduce(Long::sum).orElseThrow() / (double) statsCopy.size();
System.out.println("\tavg:" + avgRequestFormat.format(avg) +
"\tmin:" + statsCopy.get(0) +
"\tmax:" + statsCopy.get(statsCopy.size() - 1));
// print percentiles
System.out.println("\tRequest duration percentiles:\n" +
"\t\t1%:" + percentile(statsCopy, 1) +
"\t5%:" + percentile(statsCopy, 5) +
"\t10%:" + percentile(statsCopy, 10) +
"\t50%:" + percentile(statsCopy, 50) +
"\t90%:" + percentile(statsCopy, 90) +
"\t95%:" + percentile(statsCopy, 95) +
"\t99%:" + percentile(statsCopy, 99) +
"\t99.9%:" + percentile(statsCopy, 99.9) +
"\t99.99%:" + percentile(statsCopy, 99.99));
System.out.println("\tCalculations took:" + (System.currentTimeMillis() - logTime) + "ms.");
}
};
// Schedule printing of statistics on a timer
final Timer timer = new Timer("test-output-timer", true);
timer.schedule(renderStatisticsTask,messageIntervalMillis,messageIntervalMillis);
}
public void printStats() {
renderStatisticsTask.run();
}
public void addTestDuration(final long time) {
times.add(time);
}
private static long percentile(List<Long> times, double percentile) {
int index = (int) Math.ceil(percentile / 100.0 * times.size());
return times.get(index - 1);
}
}
Running wiremock for this test:
Download the standalone jar from here: http://wiremock.org/docs/running-standalone/ into a directory which will be referred to as <wiremock_directory> in these instructions. The file downloaded will be referred as <wiremock.jar>
Create a directory <wiremock_directory>/mappings
Create a file named endpoint.json and put it in <wiremock_directory>/mappings
{
"request": {
"method": "GET",
"urlPathPattern": "/wait/fixed/empty"
},
"response": {
"headers": {
"Content-Type": "application/json;charset=UTF-8"
},
"status": 200,
"fixedDelayMilliseconds": 80
}
}
Run wiremock in a mode that can handle high concurrency using the command: java -jar <wiremock.jar> --port 5000 --container-threads 250 --jetty-acceptor-threads 200 --no-request-journal
NOTE: replace the file name in the command with the file downloaded.
If you cannot max out your CPU's cores, that means your threads are waiting. Most likely for IO. As you are making a network call. In general, as soon as IO comes into play, you are unlikely to create a CPU bound load. To find out what your threads are doing create a thread dump while your test is running and have a look at their stacktraces.
A couple more things:
Better not use a ForkJoinPool if you do not create tasks that are geared towards work stealing. I.e. ForkJoinTasks. In your case a simple ThreadPoolExecutoris likely to perform better.
You might be shooting yourself in the knee with the parallel stream. You create an executor with lots of threads that each receive a Runnable to execute which uses the parallels engine which in turn uses a single shared ForkJoinPool with as many threads as you have logical CPU cores. If you have 8 logical cores that means you have 100 threads driving tasks that all share a single 8-thread-pool to do their work. (Though if that was the case you should only get about 100 requests per second, if I got my math right.)
Collecting the timing of each request can be costly, too. I'd rather not call System.currentTimeMillis() twice on each request. (Most likely the cost is negligible compared to the cost of the networked request the http client does, though.)

how calculate running time of method containing other method using new Date().getTime() in java? [duplicate]

How do I get a method's execution time?
Is there a Timer utility class for things like timing how long a task takes, etc?
Most of the searches on Google return results for timers that schedule threads and tasks, which is not what I want.
There is always the old-fashioned way:
long startTime = System.nanoTime();
methodToTime();
long endTime = System.nanoTime();
long duration = (endTime - startTime); //divide by 1000000 to get milliseconds.
I go with the simple answer. Works for me.
long startTime = System.currentTimeMillis();
doReallyLongThing();
long endTime = System.currentTimeMillis();
System.out.println("That took " + (endTime - startTime) + " milliseconds");
It works quite well. The resolution is obviously only to the millisecond, you can do better with System.nanoTime(). There are some limitations to both (operating system schedule slices, etc.) but this works pretty well.
Average across a couple of runs (the more the better) and you'll get a decent idea.
Come on guys! Nobody mentioned the Guava way to do that (which is arguably awesome):
import com.google.common.base.Stopwatch;
Stopwatch timer = Stopwatch.createStarted();
//method invocation
LOG.info("Method took: " + timer.stop());
The nice thing is that Stopwatch.toString() does a good job of selecting time units for the measurement. I.e. if the value is small, it'll output 38 ns, if it's long, it'll show 5m 3s
Even nicer:
Stopwatch timer = Stopwatch.createUnstarted();
for (...) {
timer.start();
methodToTrackTimeFor();
timer.stop();
methodNotToTrackTimeFor();
}
LOG.info("Method took: " + timer);
Note: Google Guava requires Java 1.6+
Using Instant and Duration from Java 8's new API,
Instant start = Instant.now();
Thread.sleep(5000);
Instant end = Instant.now();
System.out.println(Duration.between(start, end));
outputs,
PT5S
Gathered all possible ways together into one place.
Date
Date startDate = Calendar.getInstance().getTime();
long d_StartTime = new Date().getTime();
Thread.sleep(1000 * 4);
Date endDate = Calendar.getInstance().getTime();
long d_endTime = new Date().getTime();
System.out.format("StartDate : %s, EndDate : %s \n", startDate, endDate);
System.out.format("Milli = %s, ( D_Start : %s, D_End : %s ) \n", (d_endTime - d_StartTime),d_StartTime, d_endTime);
System.currentTimeMillis()
long startTime = System.currentTimeMillis();
Thread.sleep(1000 * 4);
long endTime = System.currentTimeMillis();
long duration = (endTime - startTime);
System.out.format("Milli = %s, ( S_Start : %s, S_End : %s ) \n", duration, startTime, endTime );
System.out.println("Human-Readable format : "+millisToShortDHMS( duration ) );
Human Readable Format
public static String millisToShortDHMS(long duration) {
String res = ""; // java.util.concurrent.TimeUnit;
long days = TimeUnit.MILLISECONDS.toDays(duration);
long hours = TimeUnit.MILLISECONDS.toHours(duration) -
TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(duration));
long minutes = TimeUnit.MILLISECONDS.toMinutes(duration) -
TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(duration));
long seconds = TimeUnit.MILLISECONDS.toSeconds(duration) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration));
long millis = TimeUnit.MILLISECONDS.toMillis(duration) -
TimeUnit.SECONDS.toMillis(TimeUnit.MILLISECONDS.toSeconds(duration));
if (days == 0) res = String.format("%02d:%02d:%02d.%04d", hours, minutes, seconds, millis);
else res = String.format("%dd %02d:%02d:%02d.%04d", days, hours, minutes, seconds, millis);
return res;
}
Guava: Google StopwatchJAR « An object of Stopwatch is to measures elapsed time in nanoseconds.
com.google.common.base.Stopwatch g_SW = Stopwatch.createUnstarted();
g_SW.start();
Thread.sleep(1000 * 4);
g_SW.stop();
System.out.println("Google StopWatch : "+g_SW);
Apache Commons LangJAR
« StopWatch provides a convenient API for timings.
org.apache.commons.lang3.time.StopWatch sw = new StopWatch();
sw.start();
Thread.sleep(1000 * 4);
sw.stop();
System.out.println("Apache StopWatch : "+ millisToShortDHMS(sw.getTime()) );
JODA-TIME
public static void jodaTime() throws InterruptedException, ParseException{
java.text.SimpleDateFormat ms_SDF = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
String start = ms_SDF.format( new Date() ); // java.util.Date
Thread.sleep(10000);
String end = ms_SDF.format( new Date() );
System.out.println("Start:"+start+"\t Stop:"+end);
Date date_1 = ms_SDF.parse(start);
Date date_2 = ms_SDF.parse(end);
Interval interval = new org.joda.time.Interval( date_1.getTime(), date_2.getTime() );
Period period = interval.toPeriod(); //org.joda.time.Period
System.out.format("%dY/%dM/%dD, %02d:%02d:%02d.%04d \n",
period.getYears(), period.getMonths(), period.getDays(),
period.getHours(), period.getMinutes(), period.getSeconds(), period.getMillis());
}
Java date time API from Java 8 « A Duration object represents a period of time between two Instant objects.
Instant start = java.time.Instant.now();
Thread.sleep(1000);
Instant end = java.time.Instant.now();
Duration between = java.time.Duration.between(start, end);
System.out.println( between ); // PT1.001S
System.out.format("%dD, %02d:%02d:%02d.%04d \n", between.toDays(),
between.toHours(), between.toMinutes(), between.getSeconds(), between.toMillis()); // 0D, 00:00:01.1001
Spring Framework provides StopWatch utility class to measure elapsed time in Java.
StopWatch sw = new org.springframework.util.StopWatch();
sw.start("Method-1"); // Start a named task
Thread.sleep(500);
sw.stop();
sw.start("Method-2");
Thread.sleep(300);
sw.stop();
sw.start("Method-3");
Thread.sleep(200);
sw.stop();
System.out.println("Total time in milliseconds for all tasks :\n"+sw.getTotalTimeMillis());
System.out.println("Table describing all tasks performed :\n"+sw.prettyPrint());
System.out.format("Time taken by the last task : [%s]:[%d]",
sw.getLastTaskName(),sw.getLastTaskTimeMillis());
System.out.println("\n Array of the data for tasks performed « Task Name: Time Taken");
TaskInfo[] listofTasks = sw.getTaskInfo();
for (TaskInfo task : listofTasks) {
System.out.format("[%s]:[%d]\n",
task.getTaskName(), task.getTimeMillis());
}
OutPut:
Total time in milliseconds for all tasks :
999
Table describing all tasks performed :
StopWatch '': running time (millis) = 999
-----------------------------------------
ms % Task name
-----------------------------------------
00500 050% Method-1
00299 030% Method-2
00200 020% Method-3
Time taken by the last task : [Method-3]:[200]
Array of the data for tasks performed « Task Name: Time Taken
[Method-1]:[500]
[Method-2]:[299]
[Method-3]:[200]
Use a profiler (JProfiler, Netbeans Profiler, Visual VM, Eclipse Profiler, etc). You'll get the most accurate results and is the least intrusive. They use the built-in JVM mechanism for profiling which can also give you extra information like stack traces, execution paths, and more comprehensive results if necessary.
When using a fully integrated profiler, it's faily trivial to profile a method. Right click, Profiler -> Add to Root Methods. Then run the profiler just like you were doing a test run or debugger.
System.currentTimeMillis(); IS NOT a good approach for measuring the performance of your algorithms. It measures the total time you experience as a user watching the computer screen. It includes also time consumed by everything else running on your computer in the background. This could make a huge difference in case you have a lot of programs running on your workstation.
Proper approach is using java.lang.management package.
From http://nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarking website (archive link):
"User time" is the time spent running your application's own code.
"System time" is the time spent running OS code on behalf of your application (such as for I/O).
getCpuTime() method gives you sum of those:
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
public class CPUUtils {
/** Get CPU time in nanoseconds. */
public static long getCpuTime( ) {
ThreadMXBean bean = ManagementFactory.getThreadMXBean( );
return bean.isCurrentThreadCpuTimeSupported( ) ?
bean.getCurrentThreadCpuTime( ) : 0L;
}
/** Get user time in nanoseconds. */
public static long getUserTime( ) {
ThreadMXBean bean = ManagementFactory.getThreadMXBean( );
return bean.isCurrentThreadCpuTimeSupported( ) ?
bean.getCurrentThreadUserTime( ) : 0L;
}
/** Get system time in nanoseconds. */
public static long getSystemTime( ) {
ThreadMXBean bean = ManagementFactory.getThreadMXBean( );
return bean.isCurrentThreadCpuTimeSupported( ) ?
(bean.getCurrentThreadCpuTime( ) - bean.getCurrentThreadUserTime( )) : 0L;
}
}
This probably isn't what you wanted me to say, but this is a good use of AOP. Whip an proxy interceptor around your method, and do the timing in there.
The what, why and how of AOP is rather beyond the scope of this answer, sadly, but that's how I'd likely do it.
Edit: Here's a link to Spring AOP to get you started, if you're keen. This is the most accessible implementation of AOP that Iive come across for java.
Also, given everyone else's very simple suggestions, I should add that AOP is for when you don't want stuff like timing to invade your code. But in many cases, that sort of simple and easy approach is fine.
With Java 8 you can do also something like this with every normal methods:
Object returnValue = TimeIt.printTime(() -> methodeWithReturnValue());
//do stuff with your returnValue
with TimeIt like:
public class TimeIt {
public static <T> T printTime(Callable<T> task) {
T call = null;
try {
long startTime = System.currentTimeMillis();
call = task.call();
System.out.print((System.currentTimeMillis() - startTime) / 1000d + "s");
} catch (Exception e) {
//...
}
return call;
}
}
With this methode you can make easy time measurement anywhere in your code without breaking it. In this simple example i just print the time. May you add a Switch for TimeIt, e.g. to only print the time in DebugMode or something.
If you are working with Function you can do somthing like this:
Function<Integer, Integer> yourFunction= (n) -> {
return IntStream.range(0, n).reduce(0, (a, b) -> a + b);
};
Integer returnValue = TimeIt.printTime2(yourFunction).apply(10000);
//do stuff with your returnValue
public static <T, R> Function<T, R> printTime2(Function<T, R> task) {
return (t) -> {
long startTime = System.currentTimeMillis();
R apply = task.apply(t);
System.out.print((System.currentTimeMillis() - startTime) / 1000d
+ "s");
return apply;
};
}
Also We can use StopWatch class of Apache commons for measuring the time.
Sample code
org.apache.commons.lang.time.StopWatch sw = new org.apache.commons.lang.time.StopWatch();
System.out.println("getEventFilterTreeData :: Start Time : " + sw.getTime());
sw.start();
// Method execution code
sw.stop();
System.out.println("getEventFilterTreeData :: End Time : " + sw.getTime());
JEP 230: Microbenchmark Suite
FYI, JEP 230: Microbenchmark Suite is an OpenJDK project to:
Add a basic suite of microbenchmarks to the JDK source code, and make it easy for developers to run existing microbenchmarks and create new ones.
This feature arrived in Java 12.
Java Microbenchmark Harness (JMH)
For earlier versions of Java, take a look at the Java Microbenchmark Harness (JMH) project on which JEP 230 is based.
Just a small twist, if you don't use tooling and want to time methods with low execution time: execute it many times, each time doubling the number of times it is executed until you reach a second, or so. Thus, the time of the Call to System.nanoTime and so forth, nor the accuracy of System.nanoTime does affect the result much.
int runs = 0, runsPerRound = 10;
long begin = System.nanoTime(), end;
do {
for (int i=0; i<runsPerRound; ++i) timedMethod();
end = System.nanoTime();
runs += runsPerRound;
runsPerRound *= 2;
} while (runs < Integer.MAX_VALUE / 2 && 1000000000L > end - begin);
System.out.println("Time for timedMethod() is " +
0.000000001 * (end-begin) / runs + " seconds");
Of course, the caveats about using the wall clock apply: influences of JIT-compilation, multiple threads / processes etc. Thus, you need to first execute the method a lot of times first, such that the JIT compiler does its work, and then repeat this test multiple times and take the lowest execution time.
We are using AspectJ and Java annotations for this purpose. If we need to know to execution time for a method, we simple annotate it. A more advanced version could use an own log level that can enabled and disabled at runtime.
public #interface Trace {
boolean showParameters();
}
#Aspect
public class TraceAspect {
[...]
#Around("tracePointcut() && #annotation(trace) && !within(TraceAspect)")
public Object traceAdvice ( ProceedingJintPoint jP, Trace trace ) {
Object result;
// initilize timer
try {
result = jp.procced();
} finally {
// calculate execution time
}
return result;
}
[...]
}
Really good code.
http://www.rgagnon.com/javadetails/java-0585.html
import java.util.concurrent.TimeUnit;
long startTime = System.currentTimeMillis();
........
........
........
long finishTime = System.currentTimeMillis();
String diff = millisToShortDHMS(finishTime - startTime);
/**
* converts time (in milliseconds) to human-readable format
* "<dd:>hh:mm:ss"
*/
public static String millisToShortDHMS(long duration) {
String res = "";
long days = TimeUnit.MILLISECONDS.toDays(duration);
long hours = TimeUnit.MILLISECONDS.toHours(duration)
- TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(duration));
long minutes = TimeUnit.MILLISECONDS.toMinutes(duration)
- TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(duration));
long seconds = TimeUnit.MILLISECONDS.toSeconds(duration)
- TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration));
if (days == 0) {
res = String.format("%02d:%02d:%02d", hours, minutes, seconds);
}
else {
res = String.format("%dd%02d:%02d:%02d", days, hours, minutes, seconds);
}
return res;
}
Spring provides a utility class org.springframework.util.StopWatch, as per JavaDoc:
Simple stop watch, allowing for timing of a number of tasks, exposing
total running time and running time for each named task.
Usage:
StopWatch stopWatch = new StopWatch("Performance Test Result");
stopWatch.start("Method 1");
doSomething1();//method to test
stopWatch.stop();
stopWatch.start("Method 2");
doSomething2();//method to test
stopWatch.stop();
System.out.println(stopWatch.prettyPrint());
Output:
StopWatch 'Performance Test Result': running time (millis) = 12829
-----------------------------------------
ms % Task name
-----------------------------------------
11907 036% Method 1
00922 064% Method 2
With Aspects:
#Around("execution(* my.package..*.*(..))")
public Object logTime(ProceedingJoinPoint joinPoint) throws Throwable {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
Object retVal = joinPoint.proceed();
stopWatch.stop();
log.info(" execution time: " + stopWatch.getTotalTimeMillis() + " ms");
return retVal;
}
You can use Perf4j. Very cool utility. Usage is simple
String watchTag = "target.SomeMethod";
StopWatch stopWatch = new LoggingStopWatch(watchTag);
Result result = null; // Result is a type of a return value of a method
try {
result = target.SomeMethod();
stopWatch.stop(watchTag + ".success");
} catch (Exception e) {
stopWatch.stop(watchTag + ".fail", "Exception was " + e);
throw e;
}
More information can be found in Developer Guide
Edit: Project seems dead
I have written a method to print the method execution time in a much readable form.
For example, to calculate the factorial of 1 Million, it takes approximately 9 minutes. So the execution time get printed as:
Execution Time: 9 Minutes, 36 Seconds, 237 MicroSeconds, 806193 NanoSeconds
The code is here:
public class series
{
public static void main(String[] args)
{
long startTime = System.nanoTime();
long n = 10_00_000;
printFactorial(n);
long endTime = System.nanoTime();
printExecutionTime(startTime, endTime);
}
public static void printExecutionTime(long startTime, long endTime)
{
long time_ns = endTime - startTime;
long time_ms = TimeUnit.NANOSECONDS.toMillis(time_ns);
long time_sec = TimeUnit.NANOSECONDS.toSeconds(time_ns);
long time_min = TimeUnit.NANOSECONDS.toMinutes(time_ns);
long time_hour = TimeUnit.NANOSECONDS.toHours(time_ns);
System.out.print("\nExecution Time: ");
if(time_hour > 0)
System.out.print(time_hour + " Hours, ");
if(time_min > 0)
System.out.print(time_min % 60 + " Minutes, ");
if(time_sec > 0)
System.out.print(time_sec % 60 + " Seconds, ");
if(time_ms > 0)
System.out.print(time_ms % 1E+3 + " MicroSeconds, ");
if(time_ns > 0)
System.out.print(time_ns % 1E+6 + " NanoSeconds");
}
}
In Spring framework we have a call called StopWatch (org.springframework.util.StopWatch)
//measuring elapsed time using Spring StopWatch
StopWatch watch = new StopWatch();
watch.start();
for(int i=0; i< 1000; i++){
Object obj = new Object();
}
watch.stop();
System.out.println("Total execution time to create 1000 objects in Java using StopWatch in millis: "
+ watch.getTotalTimeMillis());
new Timer(""){{
// code to time
}}.timeMe();
public class Timer {
private final String timerName;
private long started;
public Timer(String timerName) {
this.timerName = timerName;
this.started = System.currentTimeMillis();
}
public void timeMe() {
System.out.println(
String.format("Execution of '%s' takes %dms.",
timerName,
started-System.currentTimeMillis()));
}
}
Using AOP/AspectJ and #Loggable annotation from jcabi-aspects you can do it easy and compact:
#Loggable(Loggable.DEBUG)
public String getSomeResult() {
// return some value
}
Every call to this method will be sent to SLF4J logging facility with DEBUG logging level. And every log message will include execution time.
You can use Metrics library which provides various measuring instruments. Add dependency:
<dependencies>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
<version>${metrics.version}</version>
</dependency>
</dependencies>
And configure it for your environment.
Methods can be annotated with #Timed:
#Timed
public void exampleMethod(){
// some code
}
or piece of code wrapped with Timer:
final Timer timer = metricsRegistry.timer("some_name");
final Timer.Context context = timer.time();
// timed code
context.stop();
Aggregated metrics can exported to console, JMX, CSV or other.
#Timed metrics output example:
com.example.ExampleService.exampleMethod
count = 2
mean rate = 3.11 calls/minute
1-minute rate = 0.96 calls/minute
5-minute rate = 0.20 calls/minute
15-minute rate = 0.07 calls/minute
min = 17.01 milliseconds
max = 1006.68 milliseconds
mean = 511.84 milliseconds
stddev = 699.80 milliseconds
median = 511.84 milliseconds
75% <= 1006.68 milliseconds
95% <= 1006.68 milliseconds
98% <= 1006.68 milliseconds
99% <= 1006.68 milliseconds
99.9% <= 1006.68 milliseconds
I basically do variations of this, but considering how hotspot compilation works, if you want to get accurate results you need to throw out the first few measurements and make sure you are using the method in a real world (read application specific) application.
If the JIT decides to compile it your numbers will vary heavily. so just be aware
There are a couple of ways to do that. I normally fall back to just using something like this:
long start = System.currentTimeMillis();
// ... do something ...
long end = System.currentTimeMillis();
or the same thing with System.nanoTime();
For something more on the benchmarking side of things there seems also to be this one: http://jetm.void.fm/ Never tried it though.
If you want wall-clock time
long start_time = System.currentTimeMillis();
object.method();
long end_time = System.currentTimeMillis();
long execution_time = end_time - start_time;
As "skaffman" said, use AOP OR you can use run time bytecode weaving, just like unit test method coverage tools use to transparently add timing info to methods invoked.
You can look at code used by open source tools tools like Emma (http://downloads.sourceforge.net/emma/emma-2.0.5312-src.zip?modtime=1118607545&big_mirror=0). The other opensource coverage tool is http://prdownloads.sourceforge.net/cobertura/cobertura-1.9-src.zip?download.
If you eventually manage to do what you set out for, pls. share it back with the community here with your ant task/jars.
long startTime = System.currentTimeMillis();
// code goes here
long finishTime = System.currentTimeMillis();
long elapsedTime = finishTime - startTime; // elapsed time in milliseconds
I modified the code from correct answer to get result in seconds:
long startTime = System.nanoTime();
methodCode ...
long endTime = System.nanoTime();
double duration = (double)(endTime - startTime) / (Math.pow(10, 9));
Log.v(TAG, "MethodName time (s) = " + duration);
Ok, this is a simple class to be used for simple simple timing of your functions. There is an example below it.
public class Stopwatch {
static long startTime;
static long splitTime;
static long endTime;
public Stopwatch() {
start();
}
public void start() {
startTime = System.currentTimeMillis();
splitTime = System.currentTimeMillis();
endTime = System.currentTimeMillis();
}
public void split() {
split("");
}
public void split(String tag) {
endTime = System.currentTimeMillis();
System.out.println("Split time for [" + tag + "]: " + (endTime - splitTime) + " ms");
splitTime = endTime;
}
public void end() {
end("");
}
public void end(String tag) {
endTime = System.currentTimeMillis();
System.out.println("Final time for [" + tag + "]: " + (endTime - startTime) + " ms");
}
}
Sample of use:
public static Schedule getSchedule(Activity activity_context) {
String scheduleJson = null;
Schedule schedule = null;
/*->*/ Stopwatch stopwatch = new Stopwatch();
InputStream scheduleJsonInputStream = activity_context.getResources().openRawResource(R.raw.skating_times);
/*->*/ stopwatch.split("open raw resource");
scheduleJson = FileToString.convertStreamToString(scheduleJsonInputStream);
/*->*/ stopwatch.split("file to string");
schedule = new Gson().fromJson(scheduleJson, Schedule.class);
/*->*/ stopwatch.split("parse Json");
/*->*/ stopwatch.end("Method getSchedule");
return schedule;
}
Sample of console output:
Split time for [file to string]: 672 ms
Split time for [parse Json]: 893 ms
Final time for [get Schedule]: 1565 ms
In Java 8 a new class named Instant is introduced. As per doc:
Instant represents the start of a nanosecond on the time line. This
class is useful for generating a time stamp to represent machine time.
The range of an instant requires the storage of a number larger than a
long. To achieve this, the class stores a long representing
epoch-seconds and an int representing nanosecond-of-second, which will
always be between 0 and 999,999,999. The epoch-seconds are measured
from the standard Java epoch of 1970-01-01T00:00:00Z where instants
after the epoch have positive values, and earlier instants have
negative values. For both the epoch-second and nanosecond parts, a
larger value is always later on the time-line than a smaller value.
This can be used as:
Instant start = Instant.now();
try {
Thread.sleep(7000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Instant end = Instant.now();
System.out.println(Duration.between(start, end));
It prints PT7.001S.
You can use stopwatch class from spring core project:
Code:
StopWatch stopWatch = new StopWatch()
stopWatch.start(); //start stopwatch
// write your function or line of code.
stopWatch.stop(); //stop stopwatch
stopWatch.getTotalTimeMillis() ; ///get total time
Documentation for Stopwatch:
Simple stop watch, allowing for timing of a number of tasks, exposing total running time and running time for each named task.
Conceals use of System.currentTimeMillis(), improving the readability of application code and reducing the likelihood of calculation errors.
Note that this object is not designed to be thread-safe and does not use synchronization.
This class is normally used to verify performance during proof-of-concepts and in development, rather than as part of production applications.

Unexpected output of InfluxDB batch write

I am using batch processing to write into InfluxDB and below is my code for doing that.
String dbName = "test";
influxDB.query(new Query("CREATE DATABASE " + dbName, dbName));
Stopwatch watch = Stopwatch.createStarted();
influxDB.enableBatch(2000, 100, TimeUnit.MILLISECONDS);
for (int j = 0; j < 100000; j++) {
Point point = Point.measurement("cpu")
.addField("idle", (double) j)
.addField("system", 3.0 * j).build();
influxDB.write(dbName, "autogen", point);
}
influxDB.disableBatch();
System.out.println("Write for " + 100000 + " Points took:" + watch);
}
Here i am writing 100000 points and which is taking very reasonable time to write, however only few records are written into DB instead of expected 100000 records.
select count(idle) from cpu gives me only "89" i am expecting it to be "100000"
While select * from cpu gives me following:
cpu
time idle system
2016-10-06T23:57:41.184Z 8 24
2016-10-06T23:57:41.185Z 196 588
2016-10-06T23:57:41.186Z 436 1308
2016-10-06T23:57:41.187Z 660 1980
2016-10-06T23:57:41.188Z 916 2748
2016-10-06T23:57:41.189Z 1278 3834
2016-10-06T23:57:41.19Z 1405 4215
2016-10-06T23:57:41.191Z 1409 4227
2016-10-06T23:57:41.192Z 1802 5406
2016-10-06T23:57:41.193Z 1999 5997
2016-10-06T23:57:41.456Z 3757 11271
2016-10-06T23:57:41.457Z 3999 11997
2016-10-06T23:57:41.858Z 4826 14478 and so on.....
Here my question is why the values of idle are missing, for example, after 8 it should 9, 10, 11, and so on but these values were not persisted and comes directly 196 and then missing in between and then 436. Any idea how to persist all value of loop variable "j" in this situation?
This line
influxDB.enableBatch(2000, 100, TimeUnit.MILLISECONDS);
says that it will flush input data if there are more than 2000 samples per 100 ms period. Since you are trying to write 100k samples then logically most of them get flushed.
Instead, write less samples in a single batch. My recommendation would be to write 5000 samples in a single batch, and make multiple batches until all your data is in the db.
// Batch 1
influxDB.enableBatch(5000, 100, TimeUnit.MILLISECONDS);
for (int j = 0; j < 5000; j++) {
Point point = Point.measurement("cpu")
.addField("idle", (double) j)
.addField("system", 3.0 * j).build();
influxDB.write(dbName, "autogen", point);
}
influxDB.disableBatch();
// Batch 2
// ...

OpenLDAP 2.3/2.4 concurrency issue

Experiencing concurrency issues when authenticating and other read requests with Open LDAP (version tested 2.3.43 and 2.4.39)
When making 100 concurrent bind requests the test code takes around 150 milliseconds. Increasing this to 1000 concurrent requests sees the time taken increase to 9303 milliseconds.
So from x10 concurrent requests we are seeing a x62 increase in time taken.
Is this expected behaviour? Or is there something missing in our OpenLDAP server configuration/linux host configuration?
NOTE: We have run this test code against a Windows based Apache DS server 2.0.0 (same tree structure, etc) for comparison and against that server, the performance results where what we would normally expect (i.e. 100x takes ~80ms, 1000x takes ~400ms, 10,000x takes ~2700ms)
Settings in slapd.conf:
cachesize 100000
idlcachesize 300000
database bdb
suffix "dc=company,dc=com"
rootdn "uid=admin,ou=system"
rootpw secret
directory /var/lib/ldap
index objectClass eq,pres
index ou,cn,mail,surname,givenname eq,pres,sub
index uidNumber,gidNumber,loginShell eq,pres
index uid,memberUid eq,pres,sub
index nisMapName,nisMapEntry eq,pres,sub
sizelimit 100000
loglevel 256
Test code:
import java.util.ArrayList;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.LdapContextSource;
public class DirectoryServiceMain {
public static void main(String[] args) {
int concurrentThreadCount = 100;
LdapContextSource ctx = new LdapContextSource();
ctx.setUrls(new String [] { "ldap://ldap1.dev.company.com:389/", "ldap://ldap1.dev.company.com:389/" });
ctx.setBase("dc=company,dc=com");
ctx.setUserDn("uid=admin,ou=system");
ctx.setPassword("secret");
ctx.setPooled(true);
ctx.setCacheEnvironmentProperties(false);
LdapTemplate template = new LdapTemplate();
template.setContextSource(ctx);
long startTime = System.currentTimeMillis();
ArrayList<Thread> threads = new ArrayList<>();
for(int i = 0; i < concurrentThreadCount; i++) {
Thread t = new Thread(
() -> {
DirContext context = template.getContextSource().getContext("uid=username,dc=users,uid=office,dc=suborganisations,uid=ABC,dc=organisations,dc=company,dc=com",
"password");
try {
context.close();
} catch(NamingException e) {}
});
t.start();
threads.add(t);
}
boolean alive = true;
while(alive) {
alive = false;
for(Thread t : threads) {
if(t.isAlive()) {
alive = true;
try {Thread.sleep(10);} catch(InterruptedException e) {}
}
}
}
long endTime = System.currentTimeMillis();
System.out.println("Total time: " + (endTime - startTime));
}
}
ulimit -n
131072
* UPDATE *
If a slight delay (e.g. Thread.sleep(1)) is added after each t.start(), then processing time of n concurrent threads drops considerably.
A longer answer is if you are using BDB as the database then you will likely see linear scaling problems above a certain number of concurrent requests. BDB has its own db_config file that you can configure to provide better performance characteristics. You could also consider change to MDB which was specifically written for open ldap and has better linear scaling with minimal configuration.
You should also consider limiting the number of concurrent connection made by setting the jndi ldap connection pool sizes against the LDAPContextSource:
Map<String, Object> map = new HashMap<>();
map.put("com.sun.jndi.ldap.connect.pool.initsize", 2);
map.put("com.sun.jndi.ldap.connect.pool.maxsize", 2);
map.put("com.sun.jndi.ldap.connect.pool.prefsize", 2);
ctx.setBaseEnvironmentProperties(map);

How do I time a method's execution in Java?

How do I get a method's execution time?
Is there a Timer utility class for things like timing how long a task takes, etc?
Most of the searches on Google return results for timers that schedule threads and tasks, which is not what I want.
There is always the old-fashioned way:
long startTime = System.nanoTime();
methodToTime();
long endTime = System.nanoTime();
long duration = (endTime - startTime); //divide by 1000000 to get milliseconds.
I go with the simple answer. Works for me.
long startTime = System.currentTimeMillis();
doReallyLongThing();
long endTime = System.currentTimeMillis();
System.out.println("That took " + (endTime - startTime) + " milliseconds");
It works quite well. The resolution is obviously only to the millisecond, you can do better with System.nanoTime(). There are some limitations to both (operating system schedule slices, etc.) but this works pretty well.
Average across a couple of runs (the more the better) and you'll get a decent idea.
Come on guys! Nobody mentioned the Guava way to do that (which is arguably awesome):
import com.google.common.base.Stopwatch;
Stopwatch timer = Stopwatch.createStarted();
//method invocation
LOG.info("Method took: " + timer.stop());
The nice thing is that Stopwatch.toString() does a good job of selecting time units for the measurement. I.e. if the value is small, it'll output 38 ns, if it's long, it'll show 5m 3s
Even nicer:
Stopwatch timer = Stopwatch.createUnstarted();
for (...) {
timer.start();
methodToTrackTimeFor();
timer.stop();
methodNotToTrackTimeFor();
}
LOG.info("Method took: " + timer);
Note: Google Guava requires Java 1.6+
Using Instant and Duration from Java 8's new API,
Instant start = Instant.now();
Thread.sleep(5000);
Instant end = Instant.now();
System.out.println(Duration.between(start, end));
outputs,
PT5S
Gathered all possible ways together into one place.
Date
Date startDate = Calendar.getInstance().getTime();
long d_StartTime = new Date().getTime();
Thread.sleep(1000 * 4);
Date endDate = Calendar.getInstance().getTime();
long d_endTime = new Date().getTime();
System.out.format("StartDate : %s, EndDate : %s \n", startDate, endDate);
System.out.format("Milli = %s, ( D_Start : %s, D_End : %s ) \n", (d_endTime - d_StartTime),d_StartTime, d_endTime);
System.currentTimeMillis()
long startTime = System.currentTimeMillis();
Thread.sleep(1000 * 4);
long endTime = System.currentTimeMillis();
long duration = (endTime - startTime);
System.out.format("Milli = %s, ( S_Start : %s, S_End : %s ) \n", duration, startTime, endTime );
System.out.println("Human-Readable format : "+millisToShortDHMS( duration ) );
Human Readable Format
public static String millisToShortDHMS(long duration) {
String res = ""; // java.util.concurrent.TimeUnit;
long days = TimeUnit.MILLISECONDS.toDays(duration);
long hours = TimeUnit.MILLISECONDS.toHours(duration) -
TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(duration));
long minutes = TimeUnit.MILLISECONDS.toMinutes(duration) -
TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(duration));
long seconds = TimeUnit.MILLISECONDS.toSeconds(duration) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration));
long millis = TimeUnit.MILLISECONDS.toMillis(duration) -
TimeUnit.SECONDS.toMillis(TimeUnit.MILLISECONDS.toSeconds(duration));
if (days == 0) res = String.format("%02d:%02d:%02d.%04d", hours, minutes, seconds, millis);
else res = String.format("%dd %02d:%02d:%02d.%04d", days, hours, minutes, seconds, millis);
return res;
}
Guava: Google StopwatchJAR « An object of Stopwatch is to measures elapsed time in nanoseconds.
com.google.common.base.Stopwatch g_SW = Stopwatch.createUnstarted();
g_SW.start();
Thread.sleep(1000 * 4);
g_SW.stop();
System.out.println("Google StopWatch : "+g_SW);
Apache Commons LangJAR
« StopWatch provides a convenient API for timings.
org.apache.commons.lang3.time.StopWatch sw = new StopWatch();
sw.start();
Thread.sleep(1000 * 4);
sw.stop();
System.out.println("Apache StopWatch : "+ millisToShortDHMS(sw.getTime()) );
JODA-TIME
public static void jodaTime() throws InterruptedException, ParseException{
java.text.SimpleDateFormat ms_SDF = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
String start = ms_SDF.format( new Date() ); // java.util.Date
Thread.sleep(10000);
String end = ms_SDF.format( new Date() );
System.out.println("Start:"+start+"\t Stop:"+end);
Date date_1 = ms_SDF.parse(start);
Date date_2 = ms_SDF.parse(end);
Interval interval = new org.joda.time.Interval( date_1.getTime(), date_2.getTime() );
Period period = interval.toPeriod(); //org.joda.time.Period
System.out.format("%dY/%dM/%dD, %02d:%02d:%02d.%04d \n",
period.getYears(), period.getMonths(), period.getDays(),
period.getHours(), period.getMinutes(), period.getSeconds(), period.getMillis());
}
Java date time API from Java 8 « A Duration object represents a period of time between two Instant objects.
Instant start = java.time.Instant.now();
Thread.sleep(1000);
Instant end = java.time.Instant.now();
Duration between = java.time.Duration.between(start, end);
System.out.println( between ); // PT1.001S
System.out.format("%dD, %02d:%02d:%02d.%04d \n", between.toDays(),
between.toHours(), between.toMinutes(), between.getSeconds(), between.toMillis()); // 0D, 00:00:01.1001
Spring Framework provides StopWatch utility class to measure elapsed time in Java.
StopWatch sw = new org.springframework.util.StopWatch();
sw.start("Method-1"); // Start a named task
Thread.sleep(500);
sw.stop();
sw.start("Method-2");
Thread.sleep(300);
sw.stop();
sw.start("Method-3");
Thread.sleep(200);
sw.stop();
System.out.println("Total time in milliseconds for all tasks :\n"+sw.getTotalTimeMillis());
System.out.println("Table describing all tasks performed :\n"+sw.prettyPrint());
System.out.format("Time taken by the last task : [%s]:[%d]",
sw.getLastTaskName(),sw.getLastTaskTimeMillis());
System.out.println("\n Array of the data for tasks performed « Task Name: Time Taken");
TaskInfo[] listofTasks = sw.getTaskInfo();
for (TaskInfo task : listofTasks) {
System.out.format("[%s]:[%d]\n",
task.getTaskName(), task.getTimeMillis());
}
OutPut:
Total time in milliseconds for all tasks :
999
Table describing all tasks performed :
StopWatch '': running time (millis) = 999
-----------------------------------------
ms % Task name
-----------------------------------------
00500 050% Method-1
00299 030% Method-2
00200 020% Method-3
Time taken by the last task : [Method-3]:[200]
Array of the data for tasks performed « Task Name: Time Taken
[Method-1]:[500]
[Method-2]:[299]
[Method-3]:[200]
Use a profiler (JProfiler, Netbeans Profiler, Visual VM, Eclipse Profiler, etc). You'll get the most accurate results and is the least intrusive. They use the built-in JVM mechanism for profiling which can also give you extra information like stack traces, execution paths, and more comprehensive results if necessary.
When using a fully integrated profiler, it's faily trivial to profile a method. Right click, Profiler -> Add to Root Methods. Then run the profiler just like you were doing a test run or debugger.
System.currentTimeMillis(); IS NOT a good approach for measuring the performance of your algorithms. It measures the total time you experience as a user watching the computer screen. It includes also time consumed by everything else running on your computer in the background. This could make a huge difference in case you have a lot of programs running on your workstation.
Proper approach is using java.lang.management package.
From http://nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarking website (archive link):
"User time" is the time spent running your application's own code.
"System time" is the time spent running OS code on behalf of your application (such as for I/O).
getCpuTime() method gives you sum of those:
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
public class CPUUtils {
/** Get CPU time in nanoseconds. */
public static long getCpuTime( ) {
ThreadMXBean bean = ManagementFactory.getThreadMXBean( );
return bean.isCurrentThreadCpuTimeSupported( ) ?
bean.getCurrentThreadCpuTime( ) : 0L;
}
/** Get user time in nanoseconds. */
public static long getUserTime( ) {
ThreadMXBean bean = ManagementFactory.getThreadMXBean( );
return bean.isCurrentThreadCpuTimeSupported( ) ?
bean.getCurrentThreadUserTime( ) : 0L;
}
/** Get system time in nanoseconds. */
public static long getSystemTime( ) {
ThreadMXBean bean = ManagementFactory.getThreadMXBean( );
return bean.isCurrentThreadCpuTimeSupported( ) ?
(bean.getCurrentThreadCpuTime( ) - bean.getCurrentThreadUserTime( )) : 0L;
}
}
This probably isn't what you wanted me to say, but this is a good use of AOP. Whip an proxy interceptor around your method, and do the timing in there.
The what, why and how of AOP is rather beyond the scope of this answer, sadly, but that's how I'd likely do it.
Edit: Here's a link to Spring AOP to get you started, if you're keen. This is the most accessible implementation of AOP that Iive come across for java.
Also, given everyone else's very simple suggestions, I should add that AOP is for when you don't want stuff like timing to invade your code. But in many cases, that sort of simple and easy approach is fine.
With Java 8 you can do also something like this with every normal methods:
Object returnValue = TimeIt.printTime(() -> methodeWithReturnValue());
//do stuff with your returnValue
with TimeIt like:
public class TimeIt {
public static <T> T printTime(Callable<T> task) {
T call = null;
try {
long startTime = System.currentTimeMillis();
call = task.call();
System.out.print((System.currentTimeMillis() - startTime) / 1000d + "s");
} catch (Exception e) {
//...
}
return call;
}
}
With this methode you can make easy time measurement anywhere in your code without breaking it. In this simple example i just print the time. May you add a Switch for TimeIt, e.g. to only print the time in DebugMode or something.
If you are working with Function you can do somthing like this:
Function<Integer, Integer> yourFunction= (n) -> {
return IntStream.range(0, n).reduce(0, (a, b) -> a + b);
};
Integer returnValue = TimeIt.printTime2(yourFunction).apply(10000);
//do stuff with your returnValue
public static <T, R> Function<T, R> printTime2(Function<T, R> task) {
return (t) -> {
long startTime = System.currentTimeMillis();
R apply = task.apply(t);
System.out.print((System.currentTimeMillis() - startTime) / 1000d
+ "s");
return apply;
};
}
Also We can use StopWatch class of Apache commons for measuring the time.
Sample code
org.apache.commons.lang.time.StopWatch sw = new org.apache.commons.lang.time.StopWatch();
System.out.println("getEventFilterTreeData :: Start Time : " + sw.getTime());
sw.start();
// Method execution code
sw.stop();
System.out.println("getEventFilterTreeData :: End Time : " + sw.getTime());
JEP 230: Microbenchmark Suite
FYI, JEP 230: Microbenchmark Suite is an OpenJDK project to:
Add a basic suite of microbenchmarks to the JDK source code, and make it easy for developers to run existing microbenchmarks and create new ones.
This feature arrived in Java 12.
Java Microbenchmark Harness (JMH)
For earlier versions of Java, take a look at the Java Microbenchmark Harness (JMH) project on which JEP 230 is based.
We are using AspectJ and Java annotations for this purpose. If we need to know to execution time for a method, we simple annotate it. A more advanced version could use an own log level that can enabled and disabled at runtime.
public #interface Trace {
boolean showParameters();
}
#Aspect
public class TraceAspect {
[...]
#Around("tracePointcut() && #annotation(trace) && !within(TraceAspect)")
public Object traceAdvice ( ProceedingJintPoint jP, Trace trace ) {
Object result;
// initilize timer
try {
result = jp.procced();
} finally {
// calculate execution time
}
return result;
}
[...]
}
Just a small twist, if you don't use tooling and want to time methods with low execution time: execute it many times, each time doubling the number of times it is executed until you reach a second, or so. Thus, the time of the Call to System.nanoTime and so forth, nor the accuracy of System.nanoTime does affect the result much.
int runs = 0, runsPerRound = 10;
long begin = System.nanoTime(), end;
do {
for (int i=0; i<runsPerRound; ++i) timedMethod();
end = System.nanoTime();
runs += runsPerRound;
runsPerRound *= 2;
} while (runs < Integer.MAX_VALUE / 2 && 1000000000L > end - begin);
System.out.println("Time for timedMethod() is " +
0.000000001 * (end-begin) / runs + " seconds");
Of course, the caveats about using the wall clock apply: influences of JIT-compilation, multiple threads / processes etc. Thus, you need to first execute the method a lot of times first, such that the JIT compiler does its work, and then repeat this test multiple times and take the lowest execution time.
Really good code.
http://www.rgagnon.com/javadetails/java-0585.html
import java.util.concurrent.TimeUnit;
long startTime = System.currentTimeMillis();
........
........
........
long finishTime = System.currentTimeMillis();
String diff = millisToShortDHMS(finishTime - startTime);
/**
* converts time (in milliseconds) to human-readable format
* "<dd:>hh:mm:ss"
*/
public static String millisToShortDHMS(long duration) {
String res = "";
long days = TimeUnit.MILLISECONDS.toDays(duration);
long hours = TimeUnit.MILLISECONDS.toHours(duration)
- TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(duration));
long minutes = TimeUnit.MILLISECONDS.toMinutes(duration)
- TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(duration));
long seconds = TimeUnit.MILLISECONDS.toSeconds(duration)
- TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration));
if (days == 0) {
res = String.format("%02d:%02d:%02d", hours, minutes, seconds);
}
else {
res = String.format("%dd%02d:%02d:%02d", days, hours, minutes, seconds);
}
return res;
}
Spring provides a utility class org.springframework.util.StopWatch, as per JavaDoc:
Simple stop watch, allowing for timing of a number of tasks, exposing
total running time and running time for each named task.
Usage:
StopWatch stopWatch = new StopWatch("Performance Test Result");
stopWatch.start("Method 1");
doSomething1();//method to test
stopWatch.stop();
stopWatch.start("Method 2");
doSomething2();//method to test
stopWatch.stop();
System.out.println(stopWatch.prettyPrint());
Output:
StopWatch 'Performance Test Result': running time (millis) = 12829
-----------------------------------------
ms % Task name
-----------------------------------------
11907 036% Method 1
00922 064% Method 2
With Aspects:
#Around("execution(* my.package..*.*(..))")
public Object logTime(ProceedingJoinPoint joinPoint) throws Throwable {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
Object retVal = joinPoint.proceed();
stopWatch.stop();
log.info(" execution time: " + stopWatch.getTotalTimeMillis() + " ms");
return retVal;
}
You can use Perf4j. Very cool utility. Usage is simple
String watchTag = "target.SomeMethod";
StopWatch stopWatch = new LoggingStopWatch(watchTag);
Result result = null; // Result is a type of a return value of a method
try {
result = target.SomeMethod();
stopWatch.stop(watchTag + ".success");
} catch (Exception e) {
stopWatch.stop(watchTag + ".fail", "Exception was " + e);
throw e;
}
More information can be found in Developer Guide
Edit: Project seems dead
I have written a method to print the method execution time in a much readable form.
For example, to calculate the factorial of 1 Million, it takes approximately 9 minutes. So the execution time get printed as:
Execution Time: 9 Minutes, 36 Seconds, 237 MicroSeconds, 806193 NanoSeconds
The code is here:
public class series
{
public static void main(String[] args)
{
long startTime = System.nanoTime();
long n = 10_00_000;
printFactorial(n);
long endTime = System.nanoTime();
printExecutionTime(startTime, endTime);
}
public static void printExecutionTime(long startTime, long endTime)
{
long time_ns = endTime - startTime;
long time_ms = TimeUnit.NANOSECONDS.toMillis(time_ns);
long time_sec = TimeUnit.NANOSECONDS.toSeconds(time_ns);
long time_min = TimeUnit.NANOSECONDS.toMinutes(time_ns);
long time_hour = TimeUnit.NANOSECONDS.toHours(time_ns);
System.out.print("\nExecution Time: ");
if(time_hour > 0)
System.out.print(time_hour + " Hours, ");
if(time_min > 0)
System.out.print(time_min % 60 + " Minutes, ");
if(time_sec > 0)
System.out.print(time_sec % 60 + " Seconds, ");
if(time_ms > 0)
System.out.print(time_ms % 1E+3 + " MicroSeconds, ");
if(time_ns > 0)
System.out.print(time_ns % 1E+6 + " NanoSeconds");
}
}
In Spring framework we have a call called StopWatch (org.springframework.util.StopWatch)
//measuring elapsed time using Spring StopWatch
StopWatch watch = new StopWatch();
watch.start();
for(int i=0; i< 1000; i++){
Object obj = new Object();
}
watch.stop();
System.out.println("Total execution time to create 1000 objects in Java using StopWatch in millis: "
+ watch.getTotalTimeMillis());
new Timer(""){{
// code to time
}}.timeMe();
public class Timer {
private final String timerName;
private long started;
public Timer(String timerName) {
this.timerName = timerName;
this.started = System.currentTimeMillis();
}
public void timeMe() {
System.out.println(
String.format("Execution of '%s' takes %dms.",
timerName,
started-System.currentTimeMillis()));
}
}
Using AOP/AspectJ and #Loggable annotation from jcabi-aspects you can do it easy and compact:
#Loggable(Loggable.DEBUG)
public String getSomeResult() {
// return some value
}
Every call to this method will be sent to SLF4J logging facility with DEBUG logging level. And every log message will include execution time.
You can use Metrics library which provides various measuring instruments. Add dependency:
<dependencies>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
<version>${metrics.version}</version>
</dependency>
</dependencies>
And configure it for your environment.
Methods can be annotated with #Timed:
#Timed
public void exampleMethod(){
// some code
}
or piece of code wrapped with Timer:
final Timer timer = metricsRegistry.timer("some_name");
final Timer.Context context = timer.time();
// timed code
context.stop();
Aggregated metrics can exported to console, JMX, CSV or other.
#Timed metrics output example:
com.example.ExampleService.exampleMethod
count = 2
mean rate = 3.11 calls/minute
1-minute rate = 0.96 calls/minute
5-minute rate = 0.20 calls/minute
15-minute rate = 0.07 calls/minute
min = 17.01 milliseconds
max = 1006.68 milliseconds
mean = 511.84 milliseconds
stddev = 699.80 milliseconds
median = 511.84 milliseconds
75% <= 1006.68 milliseconds
95% <= 1006.68 milliseconds
98% <= 1006.68 milliseconds
99% <= 1006.68 milliseconds
99.9% <= 1006.68 milliseconds
I basically do variations of this, but considering how hotspot compilation works, if you want to get accurate results you need to throw out the first few measurements and make sure you are using the method in a real world (read application specific) application.
If the JIT decides to compile it your numbers will vary heavily. so just be aware
There are a couple of ways to do that. I normally fall back to just using something like this:
long start = System.currentTimeMillis();
// ... do something ...
long end = System.currentTimeMillis();
or the same thing with System.nanoTime();
For something more on the benchmarking side of things there seems also to be this one: http://jetm.void.fm/ Never tried it though.
If you want wall-clock time
long start_time = System.currentTimeMillis();
object.method();
long end_time = System.currentTimeMillis();
long execution_time = end_time - start_time;
As "skaffman" said, use AOP OR you can use run time bytecode weaving, just like unit test method coverage tools use to transparently add timing info to methods invoked.
You can look at code used by open source tools tools like Emma (http://downloads.sourceforge.net/emma/emma-2.0.5312-src.zip?modtime=1118607545&big_mirror=0). The other opensource coverage tool is http://prdownloads.sourceforge.net/cobertura/cobertura-1.9-src.zip?download.
If you eventually manage to do what you set out for, pls. share it back with the community here with your ant task/jars.
long startTime = System.currentTimeMillis();
// code goes here
long finishTime = System.currentTimeMillis();
long elapsedTime = finishTime - startTime; // elapsed time in milliseconds
I modified the code from correct answer to get result in seconds:
long startTime = System.nanoTime();
methodCode ...
long endTime = System.nanoTime();
double duration = (double)(endTime - startTime) / (Math.pow(10, 9));
Log.v(TAG, "MethodName time (s) = " + duration);
Ok, this is a simple class to be used for simple simple timing of your functions. There is an example below it.
public class Stopwatch {
static long startTime;
static long splitTime;
static long endTime;
public Stopwatch() {
start();
}
public void start() {
startTime = System.currentTimeMillis();
splitTime = System.currentTimeMillis();
endTime = System.currentTimeMillis();
}
public void split() {
split("");
}
public void split(String tag) {
endTime = System.currentTimeMillis();
System.out.println("Split time for [" + tag + "]: " + (endTime - splitTime) + " ms");
splitTime = endTime;
}
public void end() {
end("");
}
public void end(String tag) {
endTime = System.currentTimeMillis();
System.out.println("Final time for [" + tag + "]: " + (endTime - startTime) + " ms");
}
}
Sample of use:
public static Schedule getSchedule(Activity activity_context) {
String scheduleJson = null;
Schedule schedule = null;
/*->*/ Stopwatch stopwatch = new Stopwatch();
InputStream scheduleJsonInputStream = activity_context.getResources().openRawResource(R.raw.skating_times);
/*->*/ stopwatch.split("open raw resource");
scheduleJson = FileToString.convertStreamToString(scheduleJsonInputStream);
/*->*/ stopwatch.split("file to string");
schedule = new Gson().fromJson(scheduleJson, Schedule.class);
/*->*/ stopwatch.split("parse Json");
/*->*/ stopwatch.end("Method getSchedule");
return schedule;
}
Sample of console output:
Split time for [file to string]: 672 ms
Split time for [parse Json]: 893 ms
Final time for [get Schedule]: 1565 ms
In Java 8 a new class named Instant is introduced. As per doc:
Instant represents the start of a nanosecond on the time line. This
class is useful for generating a time stamp to represent machine time.
The range of an instant requires the storage of a number larger than a
long. To achieve this, the class stores a long representing
epoch-seconds and an int representing nanosecond-of-second, which will
always be between 0 and 999,999,999. The epoch-seconds are measured
from the standard Java epoch of 1970-01-01T00:00:00Z where instants
after the epoch have positive values, and earlier instants have
negative values. For both the epoch-second and nanosecond parts, a
larger value is always later on the time-line than a smaller value.
This can be used as:
Instant start = Instant.now();
try {
Thread.sleep(7000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Instant end = Instant.now();
System.out.println(Duration.between(start, end));
It prints PT7.001S.
You can use stopwatch class from spring core project:
Code:
StopWatch stopWatch = new StopWatch()
stopWatch.start(); //start stopwatch
// write your function or line of code.
stopWatch.stop(); //stop stopwatch
stopWatch.getTotalTimeMillis() ; ///get total time
Documentation for Stopwatch:
Simple stop watch, allowing for timing of a number of tasks, exposing total running time and running time for each named task.
Conceals use of System.currentTimeMillis(), improving the readability of application code and reducing the likelihood of calculation errors.
Note that this object is not designed to be thread-safe and does not use synchronization.
This class is normally used to verify performance during proof-of-concepts and in development, rather than as part of production applications.

Categories