A web application queries an external server. If more than 80% of the requests to the server send within the past 'n' minutes fails, then the web applicatoin should back out from querying the server and perform other logic. I could think of an atomic integer being incremented by the failed requests. But i dont think atomic integer supports any action to be executed if the value of the atomic integer reaches a particular value. Is there any smarter way to do this in java?
Well, after updating your atomic integer, you could check its value and if the 80% is met, then you could take action (like flagging that server as 'weak responding or so'). If you are working in a multi-threaded environment, there is nothing wrong with your solution.
Another solution is to have the threads call a synchronized method to increase a non-atomic integer and perform the check. That integer would have to be an attribute of the class to which this method belongs.
If you want to monitor events in the last 'N' minutes you need more than just an integer. You need to know what was happening 'N' minutes ago so you can keep your success level estimate correct.
Here is one way to do it:
import java.util.LinkedList;
/**
* Class that monitors outcomes for until the proportion of successes in a
* specified time window falls below a trigger level, at which point an action
* is invoked.
*
* #author Simon
*/
public class SuccessMonitor {
/** An outcome */
static class Outcome {
/** Time of outcome */
final long eventTime = System.currentTimeMillis();
/** True for success, false for failure */
boolean outcome;
}
/** The action to invoke when there are two few successes */
private final Runnable action_;
/** The history of outcomes in the time window */
private final LinkedList<Outcome> events_ = new LinkedList<Outcome>();
/** Number of successes in the time window */
private int goodCount_ = 0;
/** Synchronization lock */
private final Object lock_ = new Object();
/** Length of the time window in milliseconds */
private final long trackTime_;
/** The success proportion at which to invoke the action */
private final double triggerLevel_;
/**
* New monitor
*
* #param trackTime
* number of milliseconds to retain history for
* #param triggerLevel
* the level at which to invoke the action
* #param action
* the action
*/
public SuccessMonitor(long trackTime, double triggerLevel, Runnable action) {
trackTime_ = trackTime;
triggerLevel_ = triggerLevel;
action_ = action;
}
private void check(boolean result) {
// create a new outcome
Outcome out = new Outcome();
out.outcome = result;
double level;
synchronized (lock_) {
// add the new outcome
goodCount_ += (result) ? 1 : 0;
events_.addLast(out);
// remove expired outcomes
long expire = System.currentTimeMillis() - trackTime_;
while( (!events_.isEmpty())
&& (events_.getFirst().eventTime < expire) ) {
out = events_.removeFirst();
goodCount_ -= (out.outcome) ? 1 : 0;
}
// Calculate the success level.
if (events_.isEmpty()) {
// if empty assume ok
level = 1.0;
} else {
// calculate success level
level = (double) goodCount_ / events_.size();
}
}
// if level has fallen too low, invoke action
if (level < triggerLevel_) action_.run();
}
/**
* Notify this monitor of a failure.
*/
public void fail() {
check(false);
}
/**
* Reset this monitor, causing it to discard all currently stored history.
*/
public void reset() {
synchronized (lock_) {
events_.clear();
goodCount_ = 0;
}
}
/**
* Notify this monitor of a success.
*/
public void success() {
check(true);
}
}
Related
Q: Given a log file with API names, start and end timestamps, write a program that prints the average latency for each API call.
It was asked in google interview, my solution got rejected. So, want to know how can this be solved in optimized way.
$ cat log
get_foo start 2222222100
get_foo end 2222222150
get_bar start 2222222200
get_foo start 2222222220
get_bar end 2222222230
get_foo end 2222222250
solution :
$ cat log | myprog
get_foo: average = 40
get_bar: average = 30
I suggest you to breakdown the process to simplify the complexity of your problem.
Here could be a good starting point about how to define the process :
Done in Java, it could lead to this :
public class Program {
// The HashMap which contains api keys and object wrappers associated to it.
private Map<String, ApiCall> hashMap = new HashMap<>();
/**
* getHashMap
* Setter of the hashMap which contains api keys and object wrappers
* associated to it.
* #return
*/
public Map<String, ApiCall> getHashMap() {
return hashMap;
}
/**
* setHashMap
* Getter of the hashMap which contains api keys and object wrappers
* associated to it.
* #param hashMap
*/
public void setHashMap(Map<String, ApiCall> hashMap) {
this.hashMap = hashMap;
}
/**
* getNewApiCall
* #return a new ApiCall wrapper object
*/
public ApiCall getNewApiCall() {
return new ApiCall();
}
/**
* main
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException {
Program app = new Program();
// Arbitrary path to test with my environment
String path = args.length > 1 ? args[0] : "/home/user/test";
// Read all lines from your log file
List<Object> lines = Arrays.asList(
Files.lines(
Paths.get(new File(path).getPath())
).toArray()
);
for (Object o:lines) {
String s = o.toString().trim();
// If it's not and empty line
if (!s.isEmpty()) {
/*
* Split the lines into array with
* [0] = api_name, [1] start or end, [2] timestamp
*/
String[] values = s.split(" ");
// Add the API call to a hashmap without any value
app.getHashMap().put(values[0], null);
// Here you have all name of calls of your API
/*
* Now for each api call, wrap it into an object that will
* handle the average computation, the array of start
* timestamps and the array of end timestamps
*/
ApiCall apiCall = app.getHashMap().get(values[0]);
// Create and object for wrapping starting and ending timestamps
if (apiCall == null) {
apiCall = app.getNewApiCall();
}
/*
* If the line is a start then parse the last value to a long
* and add it to the object wrapper to further compute for the
* average
*/
if (values[1].equals("start")) {
apiCall.addStart(Long.parseLong(values[2]));
}
/*
* Else it is a end timestamp then parse the last value of the
* line to a long and add it to the object wrapper to further
* compute for the average
*/
else {
apiCall.addEnd(Long.parseLong(values[2]));
}
// Add the new incremented object wrapper to the API key
app.getHashMap().put(values[0], apiCall);
}
}
/*
* Stream hashmap entries (API keys) and print the key and the average
* value for each
*/
app.getHashMap().entrySet().forEach(
ks -> System.out.println(
ks.getKey()+" average="+ks.getValue().getAverage()
)
);
}
}
The class leading to object to wrap starting and ending timestamps for a specific API call for further computation.
/**
* ApiCall
* Class allowing to collect starting timestamps and ending timestamp for
* an API call. Compute the average on each addition.
* #author user
* #since 12 sept. 2019
*/
public class ApiCall {
private List<Long> start;
private List<Long> end;
private double average;
public ApiCall() {
start = new ArrayList<>();
end = new ArrayList<>();
}
public void addStart(Long l) {
start.add(l);
setAverage(computeAverage());
}
public void addEnd(Long l) {
end.add(l);
setAverage(computeAverage());
}
public double getAverage() {
return this.average;
}
private void setAverage(Double average) {
this.average = average;
}
private double computeAverage() {
return
(
end.stream().mapToLong(Long::longValue).average().orElse(0.0)
- start.stream().mapToLong(Long::longValue).average().orElse(0.0)
);
}
}
I just did this to give you a starting point about how to do. Don't copy/paste because the code is badly written and there is surely errors about the average computation as you can see in the output :
get_bar average=2.22222223E9
get_foo average=2.22222225E9
Hope it helps.
Scenario:
I've two reports: Main Report (let's call it, A) and sub-report (let's call it, B).
Report A contains sub-report B at the detail band, so sub-report B is displayed for each element at the Report A datasource. Sub-report B also returns a variable to the Main report A.
What I want is to sum those return values from sub-report B and totalize them at the Main report summary.
To do that, I have tried to create a new report variable that sum those returns values... Something like this:
However, I've found that such variables expression are always evaluated before the band detail is rendered, so I always miss the first sub-report return value...
Sadly, the evaluation time (as this link says) cannot be changed on those kind of variables, so I'm stuck...
After been struggling with this for some hours... and searching the internet for a solution... I came with a Workaround (the enlightening forums were these ones: one and two).
First, you need to define a java Class Helper that allows you calculate some arithmetic operation, in my case a Sum operation. I defined these classes:
package reports.utils;
import java.util.Map;
/**
* Utility that allows you to sum Integer values.
*/
public class SumCalculator {
/**
* Stores a map of {#code SumCalculator} instances (A Map instance per thread).
*/
private static final ThreadLocalMap<String, SumCalculator> calculatorsIndex = new ThreadLocalMap<>();
/**
* The sum total.
*/
private int total = 0;
/**
* No arguments class constructor.
*/
private SumCalculator() {
super();
}
/**
* Instance a new {#code SumCalculator} with the given ID.
*
* #param id {#code SumCalculator}'s ID
* #return the new {#code SumCalculator} instance
*/
public static SumCalculator get(String id) {
Map<String, SumCalculator> map = calculatorsIndex.get();
SumCalculator calculator = map.get(id);
if (calculator == null) {
calculator = new SumCalculator();
map.put(id, calculator);
}
return calculator;
}
/**
* Destroy the {#code SumCalculator} associated to the given ID.
*
* #param id {#code SumCalculator}'s ID
* #return {#code null}
*/
public static String destroy(String id) {
Map<String, SumCalculator> map;
map = calculatorsIndex.get();
map.remove(id);
if (map.isEmpty()) {
calculatorsIndex.remove();
}
return null;
}
/**
* Resets the {#code SumCalculator} total.
*
* #return {#code null}
*/
public String reset() {
total = 0;
return null;
}
/**
* Adds the given integer value to the accumulated total.
*
* #param i an integer value (can be null)
* #return {#code null}
*/
public String add(Integer i) {
this.total += (i != null) ? i.intValue() : 0;
return null;
}
/**
* Return the accumulated total.
*
* #return an Integer value (won't be null, never!)
*/
public Integer getTotal() {
return this.total;
}
}
package reports.utils;
import java.util.HashMap;
import java.util.Map;
/**
* Thread Local variable that holds a {#code java.util.Map}.
*/
class ThreadLocalMap<K, V> extends ThreadLocal<Map<K, V>> {
/**
* Class Constructor.
*/
public ThreadLocalMap() {
super();
}
/* (non-Javadoc)
* #see java.lang.ThreadLocal#initialValue()
*/
#Override
protected Map<K, V> initialValue() {
return new HashMap<>();
}
}
Second, at your jasper report, you need to define four text fields:
1) A text field that iniatializes your calculator; it should be (ideally) at the title section of the report and should have an expression like this: SumCalculator.get("$V{SUB_REPORT_RETURN_VALUE}").reset(). This text field should have the evaluation time: NOW.
2) A text field that calls the increment function (i.e. SumCalculator.get("$V{SUB_REPORT_RETURN_VALUE}").add($V{SUB_REPORT_RETURN_VALUE}). This text field will reside at your detail band, after the subreport element; and it should have the evaluation time: BAND (this is very important!!)
3) A text field that prints the calculator total. This text field will reside at your summary band, it will evaluate to NOW. Its expression will be: SumCalculator.get("$V{SUB_REPORT_RETURN_VALUE}").getTotal()
4) A text field that destroy the calculator. This text field will also reside at your summary band and must appear after the text field 3. The text field should have an expression like: SumCalculator.destroy("$V{SUB_REPORT_RETURN_VALUE}"). This text field should have the evaluation time: NOW.
Also, the text fields: 1, 2, and 4, should have the attribute "Blank when Null", so they will never be printed (that's why those java operations always return null).
And That's it. Then, your report can look something like this:
if i understand the problem, you can not summarize the amount returned by the sub report in the main report, i had the same problem and i solved in this way.
1.- Create a class which extends from net.sf.jasperreports.engine.JRDefaultScriptlet. and override the method beforeReportInit()
this is the code from this class.
package com.mem.utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import net.sf.jasperreports.engine.JRDefaultScriptlet;
public class SumarizacionSubtotales extends JRDefaultScriptlet {
private final Log log = LogFactory.getLog(getClass());
private Double total;
public Double getTotal() {
return total;
}
public Double add(Double cantidad) {
if(log.isDebugEnabled())log.debug("AGREGANDO LA CANTIDAD : " + cantidad);
this.total += cantidad;
return cantidad;
}
#Override
public void beforeReportInit() throws JRScriptletException {
if(log.isDebugEnabled())log.debug("beforeReportInit");
total = 0.0D;
}
}
2.- add your project's jar in your ireport's classpath.
3.- Replace the class of the REPORT scriptlet.
in the properties with your class.
3.- add in the group footer where you want to print the value returned by the sub-report a textfield with the following expression.
$P{REPORT_SCRIPTLET}.add( $V{sum_detalles} )
In this case $V{sum_detalles} is a variable in the main report which contains the value returned by the sub-report.
4.- Add in the Last page footer another textfield with the following expression.
$P{REPORT_SCRIPTLET}.getTotal()
I would like to be able to run two methods at the same time that rely on the same global variable. The first method periodically updates the shared variable, but never finishes running. The second method keeps track of time. When time runs out, the second method returns the last result of the shared variable from the first method. Below is what I have so far, with commented out pseduocode in the places where I need help.
package learning;
public class testmath{
public static void main(String[] args){
long finishBy = 10000;
int currentresult = 0;
/*
* run eversquare(0) in a seperate thread /in parallel
*/
int finalresult = manager(finishBy);
System.out.println(finalresult);
}
public static int square(int x){
return x * x;
}
public static void eversquare(int x){
int newresult;
while(2 == 2){
x += 1;
newresult = square(x);
/*
* Store newresult as a global called currentresult
*/
}
}
public static int manager(long finishBy){
while(System.currentTimeMillis() + 1000 < finishBy){
Thread.sleep(100);
}
/*
* Access global called currentresult and create a local called currentresult
*/
return currentresult;
}
}
You only need to run one additional thread:
public class Main {
/**
* Delay in milliseconds until finished.
*/
private static final long FINISH_BY = 10000;
/**
* Start with this number.
*/
private static final int START_WITH = 1;
/**
* Delay between eversquare passes in milliseconds.
*/
private static final long DELAY_BETWEEN_PASSES = 50;
/**
* Holds the current result. The "volatile" keyword tells the JVM that the
* value could be changed by another thread, so don't cache it. Marking a
* variable as volatile incurs a *serious* performance hit so don't use it
* unless really necessary.
*/
private static volatile int currentResult = 0;
public static void main(String[] args) {
// create a Thread to run "eversquare" in parallel
Thread eversquareThread = new Thread(new Runnable() {
#Override public void run() {
eversquare(START_WITH, DELAY_BETWEEN_PASSES);
}
});
// make the eversquare thread shut down when the "main" method exits
// (otherwise the program would never finish, since the "eversquare" thread
// would run forever due to its "while" loop)
eversquareThread.setDaemon(true);
// start the eversquare thread
eversquareThread.start();
// wait until the specified delay is up
long currentTime = System.currentTimeMillis();
final long stopTime = currentTime + FINISH_BY;
while (currentTime < stopTime) {
final long sleepTime = stopTime - currentTime;
try {
Thread.sleep(sleepTime);
} catch (InterruptedException ex) {
// in the unlikely event of an InterruptedException, do nothing since
// the "while" loop will continue until done anyway
}
currentTime = System.currentTimeMillis();
}
System.out.println(currentResult);
}
/**
* Increment the value and compute its square. Runs forever if left to its own
* devices.
*
* #param startValue
* The value to start with.
*
* #param delay
* If you were to try to run this without any delay between passes, it would
* max out the CPU and starve any other threads. This value is the wait time
* between passes.
*/
private static void eversquare(final int startValue, final long delay) {
int currentValue = startValue;
while (true) { // run forever (just use "true"; "2==2" looks silly)
currentResult = square(currentValue); // store in the global "currentResult"
currentValue++; // even shorter than "x += 1"
if (delay > 0) {
try { // need to handle the exception that "Thread.sleep()" can throw
Thread.sleep(delay);
} catch (InterruptedException ex) { // "Thread.sleep()" can throw this
// just print to the console in the unlikely event of an
// InterruptedException--things will continue fine
ex.printStackTrace();
}
}
}
}
private static int square(int x) {
return x * x;
}
}
I should also mention that the "volatile" keyword works for (most) primitives, since any JVM you'll see these days guarantees they will be modified atomically. This is not the case for objects, and you will need to use synchronized blocks and locks to ensure they are always "seen" in a consistent state.
Most people will also mention that you really should not use the synchronized keyword on the method itself, and instead synchronize on a specific "lock" object. And generally this lock object should not be visible outside your code. This helps prevent people from using your code incorrectly, getting themselves into trouble, and then trying to blame you. :)
I have been trying to figure out how to add runner information into an array of runner information. It should contain at most 100 runners.
This is part of a larger project that must fulfill these requirements:
Operations (methods):
• A constructor that takes in a race name and distance.
• Getters and setters for both the name and distance instance variables.
• Method to return the count of the number of RunnerResult objects added to the array.
• Method to add a RunnerResult to the array (given an instance of Runner and the runner’s finishing time).
• Methods to get a RunnerResult object; one that takes in the position in which the RunnerResult was added (to directly access the object from the array) and one that takes in a runner name (to use to search for the matching runner). The first runner’s index is 0, the second is 1, etc.
• A method with conditional logic to give a count of all runners for a certain category (youth, adult, senior, male, female, all) triggered by a flag passed in as a whole number (1, 2, 3, 4, 5, 6, respectively, implemented as public constants). A similar method provides the average race result (time to finish race) for each potential category.
• A method with conditional logic finds runners with a race time less than the specified minutes per mile. For example, find all runners who finished the race with a time of less than 8 minutes per mile.
• A toString method that simply gives the race name, race distance, a count of total runners in the race, and the average time of all runners in the race.
So far, this is what I have:
public class Race
{
// instance variables
private String name;
private double distance;
private int nextPos;
private RunnerResult [] results;
// public constants
/**
* Flag to signify YOUTH.
*/
public static final int YOUTH = 1;
/**
* Flag to signify ADULT.
*/
public static final int ADULT = 2;
/**
* Flag to signify SENIOR.
*/
public static final int SENIOR = 3;
/**
* Flag to signify MALE.
*/
public static final int MALE = 4;
/**
* Flag to signify FEMALE.
*/
public static final int FEMALE = 5;
/**
* Flag to signify ALL.
*/
public static final int ALL = 6;
/**
* Array limit.
*/
public static final int MAX_COUNT = 100;
/**
* Constructor for objects of class Race.
*
* #param inName the race name.
* #param inDist the distance of the race.
*
*/
public Race(String inName, double inDist)
{
// initialize the instance variables and
// empty array of results, initalize nextPos
this.name = inName;
this.distance = inDist;
RunnerResult[] results = new RunnerResult[100];
}
/**
* Set the race Name.
*
* #param inName the race name.
*
*/
public void setName(String inName)
{
this.name = inName;
}
/**
* Get the race Name.
*
* #return String The race name.
*
*/
public String getName()
{
return this.name;
}
/**
* Set the race distance.
*
* #param inDist the distance of the Race.
*
*/
public void setDist(double inDist)
{
this.distance = inDist;
}
/**
* Get the race distance.
*
* #return double the distance of the race.
*
*/
public double getDist()
{
return this.distance;
}
/**
* Add a runner to the results
* (runners are NOT entered in order of finish).
*
* #param inChip the runner's chip id.
* #param inRunner a Runner object.
* #param inStart the start time for the runner.
* #param inEnd the end time for the runner.
*
*/
public void addRunner(String inChip, Runner inRunner, Time inStart, Time inEnd)
{
if (this.nextPos < MAX_COUNT)
{
// set the instance field element to a "copy" of passed-in object
// add to array, increment counter
for(int i = 0; i < results.length; i++);
{
RunnerResult[] results = { copyinChip, copyinRunner, copyinStart,
copyinEnd };
i++;
}
}
}
}
I just cannot figure out how to get these values into the array. (I get an incompatible type error. Any input would be greatly appreciated.
two things here.
1.) when you re-declare results, you are not referencing the same object that you declare as a field, but an entirely new object that then has no purpose, because it only lives within addRunner.
2.) When you assign results = { ---, ---, ---, ---}; You aren't adding a new runner to the array. Rather, you are reassigning the entire array every single time you do that loop. You would want to create a new RunnerResult object, add the necessary data to it, and then put that at results[];
An example here:
public void addRunner(String inChip, Runner inRunner, Time inStart, Time inEnd)
{
if (this.nextPos < MAX_COUNT)
{
// set the instance field element to a "copy" of passed-in object
// add to array, increment counter
for(int i = 0; i < results.length; i++);
{
results[i] = new RunnerResult(<your params>);
}
}
}
This question already has answers here:
What is profiling all about and how can I profile my Java program?
(4 answers)
Closed 10 years ago.
This may be a silly question for some pro java coders but I am going mad right now, so I am still asking. Please guide me in right direction someone.
How do I analyze which method/partOfMethod is consuming more time in my java program?
(I am using Eclipse and Junit)
Use jvisualvm. It is bundled in with the JDK nowadays, but a standalone version exists as well, which is more up to date.
Typically, when you start it you can pick which running java process to connect to (this may well be our running unit test). You can specify which qualified class name filters you need to track. Normally, some class instrumentation will ensue, and you will be able to track the processing time allocated to each method (cumulative time as well).
You need to get a Java profiler. Some of them integrate well in Eclipse.
Other than that, you're left with using a custom profiler class (if you don't have a lot of profiling to do and if you already suspect some bottlenecks).
Here is a simple class to do that:
/**
* Small helper class to profile the code, take timing, ...
*
* To use this, simply call the start method with an identifier. When you want to measure the time, call the stop method
* with the same identifier. To output statistics, simply call the toString method or the toCsv method to create a CSV
* file with the profiler information.
*
* #author Vincent Prat # MarvinLabs
*/
public class Profiler {
private static final int THEORETICAL_MAX_NAME_LENGTH = 50;
private static Profiler singletonInstance = null;
private Map<String, Profile> profiles; // Fast access to profiles by name
private List<Profile> profilesStack; // Profiles as created chronologically
/**
* Get access to the singleton instance (create it if necessary)
*/
public static Profiler getInstance() {
if (singletonInstance == null) {
singletonInstance = new Profiler();
}
return singletonInstance;
}
/**
* Protected constructor for singleton
*/
protected Profiler() {
profiles = new HashMap<String, Profiler.Profile>();
profilesStack = new ArrayList<Profile>();
}
/**
* Start a profile. If the profile does not exist, it will be created. If it exists, a new round of measure is
* taken.
*
* #param name
* The name of the profile. If possible, less than Profiler.THEORETICAL_MAX_NAME_LENGTH characters
*
* #see Profiler.THEORETICAL_MAX_NAME_LENGTH
*/
public void start(String name) {
Profile p = profiles.get(name);
if (p == null) {
p = new Profile(name);
profiles.put(name, p);
profilesStack.add(p);
}
p.start();
}
/**
* Stop a profile and compute some statistics about it.
*
* #param name
* The name of the profile as declared in the corresponding start method
*/
public void stop(String name) {
Profile p = profiles.get(name);
if (p == null) {
throw new RuntimeException("The profile " + name + " has not been created by a call to the start() method!");
}
p.stop();
}
/**
* Clear all the current measures. Not to be called within any start/stop pair.
*/
public void reset() {
profiles.clear();
}
/**
* Build a string containing all the information about the measures we have taken so far.
*/
#Override
public String toString() {
final StringBuffer sb = new StringBuffer();
for (Profile p : profilesStack) {
sb.append(p.toString());
sb.append("\n");
}
return sb.toString();
}
/**
* Output the measures to an output string
*/
public void toCsvFile(OutputStream os) throws IOException {
Profile.writeCsvHeader(os);
for (Profile p : profilesStack) {
p.writeCsvLine(os);
}
}
/**
* Profile information. It stores statistics per named profile.
*
* #author Vincent Prat # MarvinLabs
*/
private static class Profile {
private static final String CSV_HEADERS = "Name, Call Count, Total Time (ms), Average Time (ms), Min Time (ms), Max Time (ms), Delta Time (ms), Delta Ratio (%)\n";
private static final String FORMAT_STRING = "%-" + THEORETICAL_MAX_NAME_LENGTH + "."
+ THEORETICAL_MAX_NAME_LENGTH
+ "s: %3d calls, total %5d ms, avg %5d ms, min %5d ms, max %5d ms, delta %5d ms (%d%%)";
private static final String CSV_FORMAT_STRING = "%s,%d,%d,%d,%d,%d,%d,%d\n";
private String name;
private long startTime;
private long callCount;
private long totalTime;
private long minTime;
private long maxTime;
public Profile(String name) {
this.name = name;
this.callCount = 0;
this.totalTime = 0;
this.startTime = 0;
this.minTime = Long.MAX_VALUE;
this.maxTime = Long.MIN_VALUE;
}
public void start() {
startTime = System.currentTimeMillis();
}
public void stop() {
final long elapsed = (System.currentTimeMillis() - startTime);
if (elapsed < minTime) minTime = elapsed;
if (elapsed > maxTime) maxTime = elapsed;
totalTime += elapsed;
callCount++;
}
private String getFormattedStats(String format) {
final long avgTime = callCount == 0 ? 0 : (long) totalTime / callCount;
final long delta = maxTime - minTime;
final double deltaRatio = avgTime == 0 ? 0 : 100.0 * ((double) 0.5 * delta / (double) avgTime);
return String
.format(format, name, callCount, totalTime, avgTime, minTime, maxTime, delta, (int) deltaRatio);
}
#Override
public String toString() {
return getFormattedStats(FORMAT_STRING);
}
public static void writeCsvHeader(OutputStream os) throws IOException {
os.write(CSV_HEADERS.getBytes());
}
public void writeCsvLine(OutputStream os) throws IOException {
os.write(getFormattedStats(CSV_FORMAT_STRING).getBytes());
}
}
}
And sample usage:
Profiler.getInstance().start("marker1");
// Do something...
Profiler.getInstance().start("marker2");
// Something else...
Profiler.getInstance().stop("marker2");
// And some more...
Profiler.getInstance().stop("marker1");
// Output the profiling result
System.out.println(Profiler.getInstance().toString());
Call me old fashioned, but this is the simplest approach in my opinion:
long a, b, c, d;
a = System.currentTimeMillis();
// some code 1
b = System.currentTimeMillis();
// some code 2
c = System.currentTimeMillis();
// some code 3
d = System.currentTimeMillis();
System.out.println("Some code 1 took "+(b-a)+"mil to execute. ("+((b-a)/1000)+" seconds)");
System.out.println("Some code 2 took "+(c-b)+"mil to execute. ("+((c-b)/1000)+" seconds)");
System.out.println("Some code 3 took "+(d-c)+"mil to execute. ("+((d-c)/1000)+" seconds)");
Hope this helps :)
You could take a look at Yourkit (commercial software), which can monitor memory, CPU and many more. It has special view that show how much time was spent in methods (for example you can see that 40% of the execution time was spent in method xyz()).
The process of measuring which part of a programming takes how much runtime is called "profiling".
There are many profiling plugins for eclipse. One is described here.
there are some online tools like IdeOne which gives you the time taken for the block of code to execute. Give it a try!