How to get histogram data in measuring the performance - java

I am trying to measure the performance of our service by putting the data in a HashMap like-
X number of calls came back in Y ms. Below is my code which is very simple. It will set the timer before hitting the service and after the response came back, it will measure the time.
private static void serviceCall() {
histogram = new HashMap<Long, Long>();
keys = histogram.keySet();
long total = 10;
long runs = total;
while (runs > 0) {
long start_time = System.currentTimeMillis();
// hitting the service
result = restTemplate
.getForObject("Some URL",String.class);
long difference = (System.currentTimeMillis() - start_time);
Long count = histogram.get(difference);
if (count != null) {
count++;
histogram.put(Long.valueOf(difference), count);
} else {
histogram.put(Long.valueOf(difference), Long.valueOf(1L));
}
runs--;
}
for (Long key : keys) {
Long value = histogram.get(key);
System.out.println("SERVICE MEASUREMENT, HG data, " + key + ":" + value);
}
}
Currently the output I am getting is something like this-
SERVICE MEASUREMENT, HG data, 166:1
SERVICE MEASUREMENT, HG data, 40:2
SERVICE MEASUREMENT, HG data, 41:4
SERVICE MEASUREMENT, HG data, 42:1
SERVICE MEASUREMENT, HG data, 43:1
SERVICE MEASUREMENT, HG data, 44:1
which means is 1 call came back in 166 ms, 2 calls came back in 40 ms and same with other outputs.
Problem Statement:-
What I am looking for now is something like this. I should have range setup like this-
X Number of calls came back in between 1 and 10 ms
Y Number of calls came back in between 11 and 20 ms
Z Number of calls came back in between 21 and 30 ms
P Number of calls came back in between 31 and 40 ms
T number of calls came back in between 41 and 50 ms
....
....
I number of calls came back in more than 100 ms
And any way to configure the range also. Suppose in future I need to tweak in the range, I should be able to do it. How can I achieve this thing in my current program? Any suggestions will be of great help.

A histogram is a set of data arranged into "bins" of equal size. You should convert your time measurement to a bin and use that bin as the map key. This can be done simply by dividing your time value by the bin size. For example: time / 10L.

Related

Always getting same speed from GPS location - Kotlin

I'm trying to get the user's speed 10 times in three seconds when a function is called, and then calculate the sum of all the gotten values. I have the global variable:
lateinit var fusedLocationProviderClient : FusedLocationProviderClient
Which I then initialize in the onCreate method like this:
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)
And then this is the code where I try to calculate the sum of the speeds:
val task = fusedLocationProviderClient.lastLocation
var sumSpeed = 0F
task.addOnSuccessListener {
if (it != null) {
for (i in 1..10) {
Thread.sleep(300)
sumSpeed += it.speed
}
}
current_gps_speed_tv.text = "Total is: $sumSpeed"
if (sumSpeed < 25) {
...
}
}
The result of sumSpeed always remains the same (34m/s), which is 10 times it.speed, which is also the same every time (3.4m/s).
I've searched for other answers (like this one) but what I'm using seems to be different. Why does this happen? Thank you.
This won't work for at least a few different reasons.
You're trying to poll it more than once per second. I think the fastest rate position is updated is at best once per second, and it's going to depend on device.
You are simply adding the same value to the sum 10 times and sleeping the thread pointlessly. Calling sleep pauses execution of your code. It does not magically change the value of it to some new value polled from the GPS.
Calling Thread.sleep on the main thread will freeze your app.
You are polling lastLocation, which is some location already known from the last time the GPS was used. It only reports a single value that comes from the past. It cannot report multiple new values. Your success listener is called only one time, because either the last location is available or it's not.
To get multiple locations over a period of time, you need to use requestLocationUpdates instead of lastLocation. See here for the documentation.
Edit, to expand on 2 based on your comment:
Imagine this code:
val x = 5
var sum = 0
for (i in 0..9) {
sum = sum + 5
}
println(sum)
This adds the value of x to sum 10 times, so the result will be 50.
Now consider this code:
val x = 5
var sum = 0
for (i in 0..9) {
Thread.sleep(100)
sum = sum + 5
}
println(sum)
This code has the exact same result. It just takes a lot longer to return because it keeps pausing to sleep. Sleeping has no effect on the value of x. x is always the same value. The same is true of it in your code. There is only ever one instance of it in your function.

springdata crudRepository become very slow

At the beginning the loop go very well and fast, after few hour, become slow, and average takes 10 seconds for a single incremental.
I created a ArrayList to save it all after processed data.
Also tried batch_size but not a significant improvement.
I am using mysql5.7, innodb, utf8mb4, and i insert directly in db are much faster.
Controller.java
// call 4000 times
Observable.fromArray(postTodayHolding).subscribe(System.out::println);
dmkm
public #ResponseBody String postTodayHolding() throws IOException, ParseException {
List<AccountHolding> cshdlist = new ArrayList<AccountHolding>();
// pnlResultNormal size about 400
for (Integer q = 0; q < pnlResultNormal.size(); q += 2) {
AccountHolding cshd = new AccountHolding();
cshd.setIdDri(fk);
String partID = pnlResultNormal.get(q).text().replace("\u00a0", "");
String holding = pnlResultNormal.get(q+1).text().replace("\u00a0", "");
CcassParticipants results = pplist.stream().filter(itm -> partID.equals(itm.getPartId())).findAny().orElse(null);
cshd.setPartId(results.getId());
cshd.setHolding(getBDformatValue(holding));
cshdlist.add(cshd);
}
AccountHoldingRepository.save(cshdlist);
... another code
i think i found the problem, when i 'top' in the terminal, it show about 100% cpu all the time and almost ate all my ram after few hour of the cron job.
java 99.6 01:51:12 42/1 1 122 3627M 0B 219M 93688 72225 running *0[1] 0.00000 0.00000 501 1926111 467

how to get the speed of the process in android

I know the API "long getUidRxBytes (int uid)",but this interface could not get the network speed with each process. Is there someone who konws a simple way to get the speed of the prcocess.
my english is not very well.
Basically, to measure speed of anything, you need 2 parameters: time and amount.
Here, I assume you are calculating byte/s, you need to measure how many bytes transfered every second.
Almost time, you will need a algorithm such as
totalTimeSpent = 0
bytesSent = 0
do
beforeSendingTime = getCurrentMilisecond
send n bytes to desination via network
bytesSent = bytesSent + n
afterSendingTime = getCurrentMilisecond
timeSpent = afterSendingTime - beforeSendingTime
totalTimeSpent = totalTimeSpent + timeSpent
say: currentSpeed = n/timeSpent
say: averageSpeed = bytesSent/totalTimeSpent
loop until no data remaining to send
Hope it help, you need to implement that algorithm in your own development language

I can't identify the issue with my parallel run timer

I have a program that applies a median filter to an array of over 2 million values.
I'm trying to compare run times for sequential vs parallel on the same dataset. So when I execute the program, it does 20 runs, every run is timed, and an average of the 20 times is outputted to the console.
ArrayList<Double> times = new ArrayList<>(20);//to calculate average run time
for (int run = 1; run < 21; run++) //algorithm will run 20 times
{
long startTime = System.nanoTime();
switch (method)
{
case 1: //Sequential
filt.seqFilter();
break;
case 2: //ForkJoin Framework
pool.invoke(filt); //pool is ForkJoin
break;
}
Double timeElapsed = (System.nanoTime() - startTime) / 1000000.0;
times.add(run - 1, timeElapsed);
System.out.println("Run " + run + ": " + timeElapsed + " milliseconds.");
}
times.remove(Collections.max(times)); //there's always a slow outlier
double timesSum = 0;
for (Double e : times)
{
timesSum += e;
}
double average = timesSum / 19;
System.out.println("Runtime: " + average);
filt is of type FilterObject which extends RecursiveAction. My overridden compute() method in FilterObject looks like this:
public void compute()
{
if (hi - lo <= SEQUENTIAL_THRESHOLD)
{
seqFilter();
}
else
{
FilterObject left = new FilterObject(lo, (hi + lo) / 2);
FilterObject right = new FilterObject((hi + lo) / 2, hi);
left.fork();
right.compute();
left.join();
}
}
seqFilter() processes the values between the lo and hi indices in the starting array and adds the processed values to a final array in the same positions. That's why there is no merging of arrays after left.join().
My run times for this are insanely fast for parallel - so fast that I think there must be something wrong with my timer OR with my left.join() statement. I'm getting average times of around 170 milliseconds for sequential with a filtering window of size 3 and 0.004 milliseconds for parallel. Why am I getting these values? I'm especially concerned that my join() is in the wrong place.
If you'd like to see my entire code, with all the classes and some input files, follow this link.
After some testing of your code I found the reason. It turned out that the ForkJoinPool runs one task instance only once. Subsequent invoke() calls with the same task instance will return immediately. So you have to reinstantiate the task for every run.
Another problem is with the parallel (standard threads) run. You are starting the threads but never waiting for them to finish before measuring the time. I think You could use the CyclicBarrier here.
With the mentioned fixes I get roughly the same time for ForkJoin and standard threads. And it's three times faster than sequential. Seems reasonable.
P.S. You are doing a micro-benchmark. It may be useful to read answers to that question to improve your benchmark accuracy: How do I write a correct micro-benchmark in Java?

Frequency from binary input

Background: I have a IOIO which I am using to measure the output from an photodiode, this is the converted into a digital output. I need to find the frequency at which the signal changes between 1 and 0. Everything I have tryed so far has hanged my test app, any suggestions?
current code:
if(diode == 1 && frequencyFound == false){
startTime = System.currentTimeMillis();
while((frequencyFound == false)){
if(diode == 0){
while(frequencyFound == false){
if(diode == 1){
double endTime = System.currentTimeMillis();
time = endTime - startTime;
frequency = (long) (1.0 / time);
frequencyFound = true;
}
Thread.sleep(100);
}
}
Thread.sleep(100);
}
}
There are a couple of issues here.
First, Android is a multi-tasking system, and you could find your timing thread put to sleep long enough to miss some signal transitions. Is there no way to be notified of a leading (or trailing) edge transition rather than sampling the input in a loop?
What sort of frequency are you looking at? Will a 100 ms sampling interval be fine enough?
Don't count on Thread.sleep() to sleep for exactly the time you specify. If the interval is too short, the system might decide to return immediately or it might round the sleep time up to a larger amount.
Your timing loop won't record the time to any precision better than 100ms (at best), so your estimate for the frequency will be very poor.
Zapl is right, you MUST run this from a separate thread from your UI thread.
Watching for a single transition will give you a very imprecise estimate of the frequency. Try something like this instead:
// Find frequency to the nearest hz (+/- 10%)
// It's assumed that some other process is responsible for updating the "diode"
// variable. "diode" must be declared volatile.
long duration = 1000; // 1 second
final int interval = 100; // sampling inteval = .1 second
int oldState = diode;
int count = 0;
final long startTime = System.currentTimeMillis();
final long endtime = startTime + duration;
while (System.currentTimeMillis() < endtime) {
// count all transitions, both leading and trailing
if (diode != oldState) {
++count;
oldState = diode;
}
Thread.sleep(interval);
}
// find the actual duration
duration = System.currentTimeMillis() - startTime;
// Compute frequency. The 0.5 term is because we were counting both leading and
// trailing edges.
float frequency = 0.5 * count / (duration/1000);
Two more extreme suggestions for working around some of the timing accuracy concerns Edward raised:
Do the measurement of interval times on the IOIO board under interrupts, where you can presumably accomplish (at least near-) real time operations. Report these time measurements to the Android device.
Skip the ioio board and build something simple to route the signal into the headset connector as a tone that turns on or off. Record audio using the built-in timing guarantees of the audio system, and then analyze the audio buffers (real time no longer required) to determine the intervals from the number of intervening audio samples times in units of the (relatively reliable compared to anything you could do in an android app) audio sample rate. You can also get an analog input easily by using the light sensor to vary the frequency of an audio oscillator.

Categories

Resources