JVM whats running on the background - java

I have some code I made.
It's not multithreaded, but when I run it
I can see that all 4 of my processors are running at 80% instead of 15%.
Can someone explain how can a non multithreaded program run on all processors.
I found some answers that say that it's a garbage collector.
Is there something more that running on the back ground ?
You can try this code (I know its not the best way to write this):
String ans = "";
for (int i = 0; i < 1000000; i++) {
String s = "aba";
ans += s;
if(i % 1000 == 0)
System.out.println(i);
}
}

It seems as if the GC and other housekeeping is really causing this behavior (you instantiate lots of string objects by concatenation). To be absolutely sure what's going on, i would recommend you to check out the VisualVM Tool.
https://visualvm.java.net/
It will display a list of all running threads and also inform you of GC activity.

ans += s; create a new string and assigns it back to ans so it could be the garbage collector.

Related

Why is for (int i = 0; i + 9 < s.length(); i++) much faster than for (int i = 0; i < s.length()-9; i++) { [duplicate]

This question already has answers here:
How do I write a correct micro-benchmark in Java?
(11 answers)
Closed 2 years ago.
s is a string with a length of up to 100000 characters.
When I run the first loop:
for (int i = 0; i + 9 < s.length(); i++)
I get a runtime of 14ms for a test set.
When I run the second loop instead of the first:
for (int i = 0; i < s.length() - 9; i++)
it consistently takes about 2 times more (28ms) than the first loop for the same test set.
Does the structure of the first loop allow for some kind of optimization?
First of all, there is a strong possibility that what you think you are seeing is actually due to a badly written benchmark. I strongly advise you to carefully read following Q&A and follow the advice therein:
How do I write a correct micro-benchmark in Java?
Secondly, what you are saying doesn't correspond to my intuition. However, if the effect is real, one would need to do an in-depth analysis of the native code produced by the JIT compiler to understand the reason for the difference.
Finally, this smells of "premature optimization". As a general rule, the JIT compiler can do a better (more consistent, more reliable) job of optimizing than a human can. If there are simple optimizations like the one that you are trying, the JIT compiler will find them. Micro-optimization like this is generally a waste of (your) time.
So if you are going to try optimize, then you need to do it Scientifically.
Get the application / library working first.
Write a realistic benchmark for the code. One that matches how the code is likely to be used for real.
Set yourself some measurable performance goals. ("As fast as possible" is not measurable).
Run the benchmark to see if you already meet the goals. If yes, don't waste any further time on optimizing.
Now run the benchmark using a performance profiler to identify the performance hot spots; i.e. the methods, etc that the application spends most of its time executing.
Pick one hotspot, and look for possible ways to make it faster. Implement on possible optimization ... and run the benchmarks again to see if it improved things.
Repeat steps 4 through 6 until you either meet the performance goal or run out of hotspots that can be optimized.
I do not think that the preformance problem with this for...loop definition. To check it, you have to provide the full compilable code; to check every aspects.
But you can easily check the answer moving all calculatio to the beginning:
for (int = 0, total = s.length() - 9; i < total; i++) {
// ...
}
P.S. for (A; B; C) where A is calculated only once at the beginning of the loop; B and C are calculated on each loop iteration.

Is the Java method "Arrays.deepToString()" the most efficient way to print a 2D array?

I've found similar questions like so:
Java - Best way to print 2D array?
But they don't answer the question of- Is it more efficient?
I'm writing a basic little console game in C# that requires repeatedly clearing and writing to the console in order to refresh the game state. In searching for a more efficient way to do this than my current attempt, iterating through the array with a nested for loop and printing it that way, I found this in Java:
Arrays.deepToString(arrayName);
which does what I'm trying to achieve.
Is this more efficient than using nested loops in Java like so?:
String[][] map = new String[10][10];
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
map[i][j] = "=";
}
}
boolean firstRun = true;
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
if (j == 0 && firstRun == false)
{
System.out.print("\n");
}
System.out.print(map[i][j]);
firstRun = false;
}
}
If it is more efficient, is there a C# library equivalent? I can't seem to find one or even someone asking about one anywhere.
You are looking at this from the wrong angle:
your code is dealing with almost no data (10x10 is nothing in 2019)
your code is doing console output
Rest assured: printing to stdout like this is many times more expensive than processing a close-to-nothing array in memory (see here for some example data).
Thus, the real answer is: you can safely ignore performance aspects here.
Instead invest your time into writing code that is easy to read, understand, and maintain. Coming from there, that single call to Arrays.deepToString(arrayName); is very much to be preferred over writing custom loops doing the same.
Keep in mind: in the java world, runtime performance doesn't come out of writing "clever" source code. It comes out of the JIT deciding "this code is used so often, I should translate it to machine code". If the JIT thinks "not worth optimising" then it is not worth optimising. If it is worth optimising, make that easy for the JIT. By writing simple and easy code.
Long story short: it is a nice exercise to implement that functionality, but now that you achieved that, throw it away and use the library call that works for you.

StackOverflowError in Math.Random in a randomly recursive method

This is the context of my program.
A function has 50% chance to do nothing, 50% to call itself twice.
What is the probability that the program will finish?
I wrote this piece of code, and it works great apparently. The answer which may not be obvious to everyone is that this program has 100% chance to finish. But there is a StackOverflowError (how convenient ;) ) when I run this program, occuring in Math.Random(). Could someone point to me where does it come from, and tell me if maybe my code is wrong?
static int bestDepth =0;
static int numberOfPrograms =0;
#Test
public void testProba(){
for(int i = 0; i <1000; i++){
long time = System.currentTimeMillis();
bestDepth = 0;
numberOfPrograms = 0;
loop(0);
LOGGER.info("Best depth:"+ bestDepth +" in "+(System.currentTimeMillis()-time)+"ms");
}
}
public boolean loop(int depth){
numberOfPrograms++;
if(depth> bestDepth){
bestDepth = depth;
}
if(proba()){
return true;
}
else{
return loop(depth + 1) && loop(depth + 1);
}
}
public boolean proba(){
return Math.random()>0.5;
}
.
java.lang.StackOverflowError
at java.util.Random.nextDouble(Random.java:394)
at java.lang.Math.random(Math.java:695)
.
I suspect the stack and the amount of function in it is limited, but I don't really see the problem here.
Any advice or clue are obviously welcome.
Fabien
EDIT: Thanks for your answers, I ran it with java -Xss4m and it worked great.
Whenever a function is called or a non-static variable is created, the stack is used to place and reserve space for it.
Now, it seems that you are recursively calling the loop function. This places the arguments in the stack, along with the code segment and the return address. This means that a lot of information is being placed on the stack.
However, the stack is limited. The CPU has built-in mechanics that protect against issues where data is pushed into the stack, and eventually override the code itself (as the stack grows down). This is called a General Protection Fault. When that general protection fault happens, the OS notifies the currently running task. Thus, originating the Stackoverflow.
This seems to be happening in Math.random().
In order to handle your problem, I suggest you to increase the stack size using the -Xss option of Java.
As you said, the loop function recursively calls itself. Now, tail recursive calls can be rewritten to loops by the compiler, and not occupy any stack space (this is called the tail call optimization, TCO). Unfortunately, java compiler does not do that. And also your loop is not tail-recursive. Your options here are:
Increase the stack size, as suggested by the other answers. Note that this will just defer the problem further in time: no matter how large your stack is, its size is still finite. You just need a longer chain of recursive calls to break out of the space limit.
Rewrite the function in terms of loops
Use a language, which has a compiler that performs TCO
You will still need to rewrite the function to be tail-recursive
Or rewrite it with trampolines (only minor changes are needed). A good paper, explaining trampolines and generalizing them further is called "Stackless Scala with Free Monads".
To illustrate the point in 3.2, here's how the rewritten function would look like:
def loop(depth: Int): Trampoline[Boolean] = {
numberOfPrograms = numberOfPrograms + 1
if(depth > bestDepth) {
bestDepth = depth
}
if(proba()) done(true)
else for {
r1 <- loop(depth + 1)
r2 <- loop(depth + 1)
} yield r1 && r2
}
And initial call would be loop(0).run.
Increasing the stack-size is a nice temporary fix. However, as proved by this post, though the loop() function is guaranteed to return eventually, the average stack-depth required by loop() is infinite. Thus, no matter how much you increase the stack by, your program will eventually run out of memory and crash.
There is nothing we can do to prevent this for certain; we always need to encode the stack in memory somehow, and we'll never have infinite memory. However, there is a way to reduce the amount of memory you're using by about 2 orders of magnitude. This should give your program a significantly higher chance of returning, rather than crashing.
We can do this by noticing that, at each layer in the stack, there's really only one piece of information we need to run your program: the piece that tells us if we need to call loop() again or not after returning. Thus, we can emulate the recursion using a stack of bits. Each emulated stack-frame will require only one bit of memory (right now it requires 64-96 times that, depending on whether you're running in 32- or 64-bit).
The code would look something like this (though I don't have a Java compiler right now so I can't test it):
static int bestDepth = 0;
static int numLoopCalls = 0;
public void emulateLoop() {
//Our fake stack. We'll push a 1 when this point on the stack needs a second call to loop() made yet, a 0 if it doesn't
BitSet fakeStack = new BitSet();
long currentDepth = 0;
numLoopCalls = 0;
while(currentDepth >= 0)
{
numLoopCalls++;
if(proba()) {
//"return" from the current function, going up the callstack until we hit a point that we need to "call loop()"" a second time
fakeStack.clear(currentDepth);
while(!fakeStack.get(currentDepth))
{
currentDepth--;
if(currentDepth < 0)
{
return;
}
}
//At this point, we've hit a point where loop() needs to be called a second time.
//Mark it as called, and call it
fakeStack.clear(currentDepth);
currentDepth++;
}
else {
//Need to call loop() twice, so we push a 1 and continue the while-loop
fakeStack.set(currentDepth);
currentDepth++;
if(currentDepth > bestDepth)
{
bestDepth = currentDepth;
}
}
}
}
This will probably be slightly slower, but it will use about 1/100th the memory. Note that the BitSet is stored on the heap, so there is no longer any need to increase the stack-size to run this. If anything, you'll want to increase the heap-size.
The downside of recursion is that it starts filling up your stack which will eventually cause a stack overflow if your recursion is too deep. If you want to ensure that the test ends you can increase your stack size using the answers given in the follow Stackoverflow thread:
How to increase to Java stack size?

How to collect AMD CPU Cache Hit Ratio with Java?

I'm writing a program in Java
In this program I'm reading and changing an array of data. This is an example of the code:
public double computation() {
char c = 0;
char target = 'a';
int x = 0, y = 1;
for (int i = 0; i < data.length; i++) {
// Read Data
c = data[index[i]];
if (c == target)
x++;
else
y++;
//Change Value
if (Character.isUpperCase(c))
Character.toLowerCase(c);
else
Character.toUpperCase(c);
//Write Data
data[index[i]] = c;
}
return (double) x / (double) y;
}
BTW, the INDEX array contains DATA array's indexes in random order to prevent prefetching. I'm forcing all of my cache accesses to be missed by using random indexes in INDEX array.
Now I want to check what is the behavior of the CPU cache by collecting information about its hit ratio.
Is there any developed tool for this purpose? If not is there any technique?
On Linux it is possible to collect such information via OProfile. Each CPU has performance event counters. See here for the list of the AMD K15 family events: http://oprofile.sourceforge.net/docs/amd-family15h-events.php
OProfile regularly samples the event counter(s) and together with the program counter. After a program run you can analyze how many events happen and at (statistically) what program position.
OProfile has build in Java support. It interacts with the Java JIT and creates a synthetic symbol table to look up the Java method name for a peace of generated JIT code.
The initial setup is not quite easy. If interested, I can guide you through or write a little more about it.
I don't think you can reach such low level information from Java but someone might know better. You could write the same program with no cache misses and check the difference. This is what I suggested in this other post for example.

How to find memory used by a function in java

I am calling a function from my code (written in java) and I want to know how much memory that function is using, and do keep in mind that I cannot add any code to the function(which I am calling).
for eg-
//my code starts
.
.
.
.
myfunc();
//print memory used by myfunc() here
.
.
// my code ends
How to do this?
What you're trying to do is basically pointless. There is no such thing as memory used by a function. Your idea of comparing the total memory usage "before" and "after" function call does not have any sense: the function may change global state (which may decrease or increase total memory usage, and in some cases (e.g. cache filling) you probably won't want to consider the increase to count as "memory used by a function), or the garbage collector may run while you're inside of myfunc and decrease the total used memory.
The good question often contains the large part of an answer. What you should do is to correctly ask the question.
I was successful with this code (it's not guaranteed to work, but try it and there's a good chance it'll give you what you need):
final Runtime rt = Runtime.getRuntime();
for (int i = 0; i < 3; i++) rt.gc();
final long startSize = rt.totalMemory()-rt.freeMemory();
myFunc();
for (int i = 0; i < 3; i++) rt.gc();
System.out.println("Used memory increased by " +
rt.totalMemory()-rt.freeMemory()-startSize);
But its wrong, because ideally it should always be zero after subraction.
Actually its right because normally each thread has a TLAB (Thread Local Allocation Buffer) which means it allocates in blocks (so each thread can allocate concurrently)
Turn this off with -XX:-UseTLAB and you will see ever byte allocated.
You should run this multiple times because other things could be running when you use this function.

Categories

Resources