Java Mutable BigInteger Class - java

I am doing calculations with BigIntegers that uses a loop that calls multiply() about 100 billion times, and the new object creation from the BigInteger is making it very slow. I was hoping somebody had written or found a MutableBigInteger class. I found the MutableBigInteger in the java.math package, but it is private and when I copy the code into a new class, many errors come up, most of which I don't know how to fix.
What implementations exist of a Java class like MutableBigInteger that allows modifying the value in place?

Is their any particular reason you cannot use reflection to gain access to the class?
I was able to do so without any problems, here is the code:
public static void main(String[] args) throws Exception {
Constructor<?> constructor = Class.forName("java.math.MutableBigInteger").getDeclaredConstructor(int.class);
constructor.setAccessible(true);
Object x = constructor.newInstance(new Integer(17));
Object y = constructor.newInstance(new Integer(19));
Constructor<?> constructor2 = Class.forName("java.math.MutableBigInteger").getDeclaredConstructor(x.getClass());
constructor2.setAccessible(true);
Object z = constructor.newInstance(new Integer(0));
Object w = constructor.newInstance(new Integer(0));
Method m = x.getClass().getDeclaredMethod("multiply", new Class[] { x.getClass(), x.getClass()});
Method m2 = x.getClass().getDeclaredMethod("mul", new Class[] { int.class, x.getClass()});
m.setAccessible(true);
m2.setAccessible(true);
// Slightly faster than BigInteger
for (int i = 0; i < 200000; i++) {
m.invoke(x, y, z);
w = z;
z = x;
x = w;
}
// Significantly faster than BigInteger and the above loop
for (int i = 0; i < 200000; i++) {
m2.invoke(x, 19, x);
}
BigInteger n17 = new BigInteger("17");
BigInteger n19 = new BigInteger("19");
BigInteger bigX = n17;
// Slowest
for (int i = 0; i < 200000; i++) {
bigX = bigX.multiply(n19);
}
}
Edit:
I decided to play around with a bit more, it does appear that java.math.MutableBigInteger doesn't behave exactly as you would expect.
It operates differently when you multiply and it will throw a nice exception when it has to increase the size of the internal array when assigning to itself. Something I guess is fairly expected. Instead I have to swap around the objects so that it is always placing the result into a different MutableBigInteger. After a couple thousand calculations the overhead from reflection becomes negligible. MutableBigInteger does end up pulling ahead and offers increasingly better performance as the number of operations increases. If you use the 'mul' function with an integer primitive as the value to multiply with, the MutableBigInteger runs almost 10 times faster than using BigInteger. I guess it really boils down to what value you need to multiply with. Either way if you ran this calculation "100 billion times" using reflection with MutableBigInteger, it would run faster than BigInteger because there would be "less" memory allocation and it would cache the reflective operations, removing overhead from reflection.

JScience has a class call LargeInteger, which is also immutable, but which they claim has significantly improved perfomance compared to BigInteger.
http://jscience.org/
APFloat's Apint might be worth checking out too. http://www.apfloat.org/apfloat_java/

I copied MutableBigInteger, then commented out some methods' bodies I dind't need, adding a nice
throw new UnsupportedOperationException("...");
when invoked.
here is how it looks.
In Revisions you can see what's changed from the original java.math.MutableBigInteger.
I also added some convenience methods,
public void init(long val) {};
public MutableBigInteger(long val) {};
// To save previous value before modifying.
public void addAndBackup(MutableBigInteger addend) {}
// To restore previous value after modifying.
public void restoreBackup() {}
Here is how I used it:
private BigInteger traverseToFactor(BigInteger offset, BigInteger toFactorize, boolean forward) {
MutableBigInteger mbiOffset = new MutableBigInteger(offset);
MutableBigInteger mbiToFactorize = new MutableBigInteger(toFactorize);
MutableBigInteger blockSize = new MutableBigInteger(list.size);
if (! MutableBigInteger.ZERO.equals(mbiOffset.remainder(blockSize))) {
throw new ArithmeticException("Offset not multiple of blockSize");
}
LongBigArrayBigList pattern = (LongBigArrayBigList) list.getPattern();
while (true) {
MutableBigInteger divisor = new MutableBigInteger(mbiOffset);
for (long i = 0; i < pattern.size64(); i++) {
long testOperand = pattern.getLong(i);
MutableBigInteger.UNSAFE_AUX_VALUE.init(testOperand);
divisor.addAndBackup(MutableBigInteger.UNSAFE_AUX_VALUE);
if (MutableBigInteger.ZERO.equals(mbiToFactorize.remainder(divisor))) {
return divisor.toBigInteger();
}
divisor.restoreBackup();
}
if (forward) {
mbiOffset.add(blockSize);
} else {
mbiOffset.subtract(blockSize);
}
System.out.println(mbiOffset);
}
}

Related

Coding RSA Algorithm Java

So, I am attempting to create an RSA algorithm from scratch.
So far, I have successfully created the ability to select two primes (which I have as 11 and 13 in my current example. Then, I calculate N by doing p x q. Which gets me 143.
Then, I move on to my public BigInteger findZ() method which calculates ϕ which is (p-1)(q-1).
Using this newly calculated ϕ, I want to find a number, or rather create an e variable that follows 1<(e)<ϕ, or simple gcd(e,ϕ) = 1 Thus, I initially set temp to equal my constant ONE (which is equal to one) + 1 to satisfy the range. However, after continuous debugging attempts, the loop never finds a value that has a GCD that is equal to one, which i've created a constant to represent since I am required to use BigInteger. Is there a reason for this?
Here is my code.
import java.math.BigInteger;
public class RSA
{
//Intialize the variables.
private BigInteger p;
private BigInteger q;
private BigInteger n;
private BigInteger z;
final private BigInteger ONE = BigInteger.valueOf(1);
public BigInteger getP()
{
return p;
}
public BigInteger getQ()
{
return q;
}
//Computes N, which is just p*q.
public BigInteger findN()
{
n = p.multiply(q);
return p.multiply(q);
}
public BigInteger findZ()
{
long pMinusOne = p.intValue() - 1;
long qMinusOne = q.intValue() - 1;
z = BigInteger.valueOf(pMinusOne * qMinusOne);
return z;
}
public BigInteger getE()
{
int temp = ONE.intValue() + 1;
BigInteger GCD = BigInteger.valueOf(temp);
while (GCD.gcd(z).compareTo(ONE) != 0)
{
temp++;
}
e = BigInteger.valueOf(temp);
return e;
}
}
Any help is greatly appreciated.
Thanks!
Since you asked for any help, I'll answer your question and give other tips.
How to get e
One tip is to use equals() instead of compareTo() when you're just checking for equality. Sometimes that can reduce the amount of work being done, and it's easier to read as well.
The biggest error in your code is that temp is used to set the original value of GCD, but that doesn't link temp to GCD. They stay disconnected. If you change temp later, GCD won't know about it and won't change. You need to add one to GCD directly. Here's some example code:
BigInteger e = BigInteger.valueOf(3);
while (! phi.gcd(e).equals(BigInteger.ONE)) {
e = e.add(BigInteger.ONE);
}
Look over BigInteger's methods
Get a sense of what you can easily do with BigInteger's by using your favorite search engine and searching for BigInteger 8 API. The 8 is for the version of Java you're using, so that might change. The API is for a list of methods.
Early on in the search results, you should find this API page. BigInteger has a lot of nice and convenient methods, so check them out. It even has a constructor that'll give you a BigInteger of whatever size you want that's very likely to be a prime, which is nice for generating the primes for a new random RSA key.
Use BigInteger's built-in constants
Don't recreate the following constants (which show up in the API page above):
BigInteger.ZERO
BigInteger.ONE
BigInteger.TEN
Never convert BigInteger to long unless you're sure it'll fit
You're converting BigIntegers to long, which is a bad idea, since there are a lot of BigIntegers that won't fit in a long, giving you incorrect results. For correctness (which is more important than speed), do arithmetic directly with BigIntegers.
You also use intValue() a lot when you're getting a long. Use longValueExact(). For that matter, use intValueExact() when you're getting an int.
So, to calculate ϕ:
BigInteger pMinusOne = p.subtract(BigInteger.ONE);
BigInteger qMinusOne = q.subtract(BigInteger.ONE);
BigInteger phi = pMinusOne.multiply(qMinusOne);
Now you know that it will give correct results, even for larger BigIntegers. It's also not that hard to read, which is good for maintaining the code later.
What to store
You should also store just n and e (and d but only if it's a private key) Never store p, q, or ϕ with RSA because those allow you to easily figure out the private key from the public key.
In general, don't calculate in getZZZ methods
You should figure out n and e (and d but only if it's a private key) in the constructor method(s) and store only those in instance variables. Then, you can have a getN() and getE() method to get the precomputed instance variables. For example (and you don't have to use this code, it's just to give an idea):
public class RSA {
private final BigInteger n;
private final BigInteger e;
private final BigInteger d;
public RSA(final BigInteger p, final BigInteger q) {
this.n = p.multiply(q);
// Calculate phi
final BigInteger pMinusOne = p.subtract(BigInteger.ONE);
final BigInteger qMinusOne = q.subtract(BigInteger.ONE);
final BigInteger phi = pMinusOne.multiply(qMinusOne);
// Calculate e
BigInteger e = BigInteger.valueOf(3L);
while (! phi.gcd(e).equals(BigInteger.ONE)) {
e = e.add(BigInteger.ONE);
}
this.e = e;
// Calculate d
this.d = e.modInverse(phi);
}
public BigInteger getN() {
return n;
}
public BigInteger getE() {
return e;
}
public BigInteger getD() {
return d;
}
}

The performance of the HashMap in JAVA8

I had a question when I learned the HashMap source code in java8。
Source code is so complicated, how much efficiency?
So I wrote a code about the hash conflict。
public class Test {
final int i;
public Test(int i) {
this.i = i;
}
public static void main(String[] args) {
java.util.HashMap<Test, Test> set = new java.util.HashMap<Test, Test>();
long time;
Test last;
Random random = new Random(0);
int i = 0;
for (int max = 1; max < 200000; max <<= 1) {
long c1 = 0, c2 = 0;
int t = 0;
for (; i < max; i++, t++) {
last = new Test(random.nextInt());
time = System.nanoTime();
set.put(last, last);
c1 += (System.nanoTime() - time);
last = new Test(random.nextInt());
time = System.nanoTime();
set.get(last);
c2 += (System.nanoTime() - time);
}
System.out.format("%d\t%d\t%d\n", max, (c1 / t), (c2 / t));
}
}
public int hashCode() {
return 0;
}
public boolean equals(Object obj) {
if (obj == null)
return false;
if (!(obj instanceof Test))
return false;
Test t = (Test) obj;
return t.i == this.i;
}
}
I show the results in Excel。
enter image description here
I am using java6u45 java7u80 java8u131。
I do not understand why the performance of java8 will be so bad
I'm trying to write my own HashMap.
I would like to learn HashMap in java8 which is better, but I did not find it.
Your test scenario is non-optimal for Java 8 HashMap. HashMap in Java 8 optimizes collisions by using binary trees for any hash chains longer than a given threshold. However, this only works if the key type is comparable. If it isn't then the overhead of testing to see if the optimization is possible actually makes Java 8 HashMap slower. (The slow-down is more than I expected ... but that's another topic.)
Change your Test class to implement Comparable<Test> ... and you should see that Java 8 performs better than the others when the proportion of hash collisions is large enough.
Note that the tree optimization should be considered as a defensive measure for the case where the hash function doesn't perform. The optimization turns O(N) worst-case performance to O(logN) worst-case.
If you want your HashMap instances to have O(1) lookup, you should make sure that you use a good hash function for the key type. If the probability of collision is minimized, the optimization is moot.
Source code is so complicated, how much efficiency?
It is explained in the comments in the source code. And probably other places that Google can find for you :-)

What's the fastest way to initialize a large list of integers?

I need to pre-populate a List with a large number of integer values.
Is there are faster way to do this other than iteration?
Current Code:
class VlanManager {
Queue<Integer> queue = Lists.newLinkedList();
public VlanManager(){
for (int i = 1; i < 4094; i++) {
queue.add(i);
}
}
This code is in the constructor of a class that is created pretty frequently so I'd like this to be as efficient (read:performance not lines of code) as possible
4094 isnt to many items to loop but if it is getting called very frequently you might look at doing something with a static variable.
private static Integer[] theList;
static {
theList = new Integer[4094];
for (int i = 1; i < 4094; i++) {
theList[i-1] = i;
}
}
then make that list a List
Queue<Integer> intQue = new LinkedList(Arrays.asList(theList));
There is a danger of using this method if you have a list of mutable objects. Heres an example of what can happen. Integers are immutable so this doesnt actually apply to your question as it stands
class MyMutableObject {
public int theValue;
}
class Test {
private static MyMutableObject[] theList;
static {
theList = new MyMutableObject[4094];
for (int i = 1; i <= 4094; i++) {
theList[i-1] = new MyMutableObject();
theList[i-1].theValue = i;
}
}
public static void main(String [] args) {
Queue<MyMutableObject> que = new LinkedList(Arrays.asList(theList));
System.out.println(que.peek().theValue); // 1
// your actually modifing the same object as the one in your static list
que.peek().theValue = -100;
Queue<MyMutableObject> que2 = new LinkedList(Arrays.asList(theList));
System.out.println(que2.peek().theValue); // -100
}
}
#Bohemian Has some good points on using a static List instead of an array, while the performance gains are very small they are none the less performance gains. Also because the 'array' is actually only ever being used as a List not an array it should be declared as such.
private static List<Integer> theList;
static {
theList = new ArrayList(4094);
for (Integer i = 0; i < 4094; i++) {
theList.add(i+1);
}
}
The fastest way would be to create a reference list (initialized using an instance block - neatly wrapping it all up in one statement):
private static final List<Integer> LIST = new ArrayList<Integer>(4094) {{
for (int i = 1; i < 4094; i++)
LIST.add(i);
}};
Then in your constructor, initialize the queue using the copy constructor:
Queue<Integer> queue;
public VlanManager(){
queue = new LinkedList<Integer>(LIST);
}
You will not write a faster implementation than what's in the JDK.
I realize this question has already been answered. But I think one important answer is missing: The fastest way to initialize a LinkedList with the values 0..4093 is .. DON'T DO IT AT ALL. Especially if speed is an issue.
What you basically are doing is creating a structure consisting of 4093 Node elements each consiting of two pointers to prev/next element and one pointer to an Integer object. Each of this Nodes must be created (and free). In addition nearly each contained Integer must be created (and freed). 'Nearly' because Java uses a cache for Integer but normally (you can change this with system properties) in the range of -127..127.
This is a lot to do in order to get a simple list of integer and if used intensively gives the GC a lot to do afterwards.
That being said there are numerous possible ways of doing this in a more efficient way. But they depend on what your concrete usage pattern is. Just to name a few:
Use an Array: boolean [] inUse' and set the taken vlan-id totrue` if it's taken
Even better use a BitSet instead of the array
Don't store which vlan is free, but which vlan is taken. I think they tend to be free and so there are much more free as there are taken ones. (this means much less to keep track of).
If you insist on using a LinkedList don't initialize it with your class but have it already initialized. This depends on how much of them you would need. You could keep a pool of them. Or perhaps your codes allows reusage of old lists. (yes, you could sort them after usage.)
Surely there are more...
All of this methods require you to build your own 'Queue' interface. But perhaps this has not to be as rich as Java's. And it really isn't that difficult. If you really use this intensively you could reach perfomance improvement factor 10x-1000x++.
A possible implementation using BitSet with an instantiation cost of nearly nothing could be:
import java.util.BitSet;
import org.testng.annotations.Test;
public class BitSetQueue {
// Represents the values 0..size-1
private final BitSet bitset;
private final int size;
private int current = 0;
private int taken = 0;
public BitSetQueue( int size ){
this.bitset = new BitSet( size );
this.size = size;
this.current = size-1;
}
public int poll(){
// prevent endless loop
if( taken == size ) return -1;
// seek for next free value.
// can be changed according to policy
while( true ){
current = (current+1)%size;
if( ! bitset.get( current ) ){
bitset.set( current );
taken++;
return current;
}
}
}
public boolean free( int num ){
if( bitset.get( num ) ){
bitset.clear( num );
taken--;
return true;
}
return false;
}
#Test
public static void usage(){
BitSetQueue q = new BitSetQueue( 4094 );
for( int i = 0; i < 4094; i++ ){
assertEquals( q.poll(), i );
}
assertEquals( q.poll(), -1 ); // No more available
assertTrue( q.free( 20 ) );
assertTrue( q.free( 51 ) );
assertEquals( q.poll(), 20 );
assertEquals( q.poll(), 51 );
}
}

Java multi-thread scalability issue

more updates
As is explained in the selected answer, the problem is in JVM's garbage collection algorithm.
JVM uses card marking algorithm to keep track of modified references in object fields. For each reference assignment to a field, it marks an associated bit in the card to be true -- this causes a false-sharing hence blocks scaling. The details are well described in this article: https://blogs.oracle.com/dave/entry/false_sharing_induced_by_card
The option -XX:+UseCondCardMark (in Java 1.7u40 and up) mitigates the problem, and makes it scale almost perfectly.
updates
I found out (hinted from Park Eung-ju) that assigning an object into a field variable makes the difference. If I remove the assignment, it scales perfectly.
I think probably it has something to do with Java memory model -- such as, an object reference must point to a valid address before it gets visible, but I am not completely sure. Both double and Object reference (likely) have 8 bytes size on 64 bit machine, so it seems to me that assigning a double value and an Object reference should be the same in terms of synchronization.
Anyone has a reasonable explanation?
Here I have a weird Java multi-threading scalability problem.
My code simply iterates over an array (using the visitor pattern) to compute simple floating-point operations and assign the result to another array. There is no data dependency, nor synchronization, so it should scale linearly (2x faster with 2 threads, 4x faster with 4 threads).
When primitive (double) array is used, it scales very well. When object type (e.g. String) array is used, it doesn't scale at all (even though the value of the String array is not used at all...)
Here's the entire source code:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.CyclicBarrier;
class Table1 {
public static final int SIZE1=200000000;
public static final boolean OBJ_PARAM;
static {
String type=System.getProperty("arg.type");
if ("double".equalsIgnoreCase(type)) {
System.out.println("Using primitive (double) type arg");
OBJ_PARAM = false;
} else {
System.out.println("Using object type arg");
OBJ_PARAM = true;
}
}
byte[] filled;
int[] ivals;
String[] strs;
Table1(int size) {
filled = new byte[size];
ivals = new int[size];
strs = new String[size];
Arrays.fill(filled, (byte)1);
Arrays.fill(ivals, 42);
Arrays.fill(strs, "Strs");
}
public boolean iterate_range(int from, int to, MyVisitor v) {
for (int i=from; i<to; i++) {
if (filled[i]==1) {
// XXX: Here we are passing double or String argument
if (OBJ_PARAM) v.visit_obj(i, strs[i]);
else v.visit(i, ivals[i]);
}
}
return true;
}
}
class HeadTable {
byte[] filled;
double[] dvals;
boolean isEmpty;
HeadTable(int size) {
filled = new byte[size];
dvals = new double[size];
Arrays.fill(filled, (byte)0);
isEmpty = true;
}
public boolean contains(int i, double d) {
if (filled[i]==0) return false;
if (dvals[i]==d) return true;
return false;
}
public boolean contains(int i) {
if (filled[i]==0) return false;
return true;
}
public double groupby(int i) {
assert filled[i]==1;
return dvals[i];
}
public boolean insert(int i, double d) {
if (filled[i]==1 && contains(i,d)) return false;
if (isEmpty) isEmpty=false;
filled[i]=1;
dvals[i] = d;
return true;
}
public boolean update(int i, double d) {
assert filled[i]==1;
dvals[i]=d;
return true;
}
}
class MyVisitor {
public static final int NUM=128;
int[] range = new int[2];
Table1 table1;
HeadTable head;
double diff=0;
int i;
int iv;
String sv;
MyVisitor(Table1 _table1, HeadTable _head, int id) {
table1 = _table1;
head = _head;
int elems=Table1.SIZE1/NUM;
range[0] = elems*id;
range[1] = elems*(id+1);
}
public void run() {
table1.iterate_range(range[0], range[1], this);
}
//YYY 1: with double argument, this function is called
public boolean visit(int _i, int _v) {
i = _i;
iv = _v;
insertDiff();
return true;
}
//YYY 2: with String argument, this function is called
public boolean visit_obj(int _i, Object _v) {
i = _i;
iv = 42;
sv = (String)_v;
insertDiff();
return true;
}
public boolean insertDiff() {
if (!head.contains(i)) {
head.insert(i, diff);
return true;
}
double old = head.groupby(i);
double newval=Math.min(old, diff);
head.update(i, newval);
head.insert(i, diff);
return true;
}
}
public class ParTest1 {
public static int THREAD_NUM=4;
public static void main(String[] args) throws Exception {
if (args.length>0) {
THREAD_NUM = Integer.parseInt(args[0]);
System.out.println("Setting THREAD_NUM:"+THREAD_NUM);
}
Table1 table1 = new Table1(Table1.SIZE1);
HeadTable head = new HeadTable(Table1.SIZE1);
MyVisitor[] visitors = new MyVisitor[MyVisitor.NUM];
for (int i=0; i<visitors.length; i++) {
visitors[i] = new MyVisitor(table1, head, i);
}
int taskPerThread = visitors.length / THREAD_NUM;
MyThread[] threads = new MyThread[THREAD_NUM];
CyclicBarrier barrier = new CyclicBarrier(THREAD_NUM+1);
for (int i=0; i<THREAD_NUM; i++) {
threads[i] = new MyThread(barrier);
for (int j=taskPerThread*i; j<taskPerThread*(i+1); j++) {
if (j>=visitors.length) break;
threads[i].addVisitors(visitors[j]);
}
}
Runtime r=Runtime.getRuntime();
System.out.println("Force running gc");
r.gc(); // running GC here (excluding GC effect)
System.out.println("Running gc done");
// not measuring 1st run (excluding JIT compilation effect)
for (int i=0; i<THREAD_NUM; i++) {
threads[i].start();
}
barrier.await();
for (int i=0; i<10; i++) {
MyThread.start = true;
long s=System.currentTimeMillis();
barrier.await();
long e=System.currentTimeMillis();
System.out.println("Iter "+i+" Exec time:"+(e-s)/1000.0+"s");
}
}
}
class MyThread extends Thread {
static volatile boolean start=true;
static int tid=0;
int id=0;
ArrayList<MyVisitor> tasks;
CyclicBarrier barrier;
public MyThread(CyclicBarrier _barrier) {
super("MyThread"+(tid++));
barrier = _barrier;
id=tid;
tasks = new ArrayList(256);
}
void addVisitors(MyVisitor v) {
tasks.add(v);
}
public void run() {
while (true) {
while (!start) { ; }
for (int i=0; i<tasks.size(); i++) {
MyVisitor v=tasks.get(i);
v.run();
}
start = false;
try { barrier.await();}
catch (InterruptedException e) { break; }
catch (Exception e) { throw new RuntimeException(e); }
}
}
}
The Java code can be compiled with no dependency, and you can run it with the following command:
java -Darg.type=double -server ParTest1 2
You pass the number of worker threads as an argument (the above uses 2 threads).
After setting up the arrays (that is excluded from the measured time), it does a same operation for 10 times, printing out the execution time at each iteration.
With the above option, it uses double array, and it scales very well with 1,2,4 threads (i.e. the execution time reduces to 1/2, and 1/4), but
java -Darg.type=Object -server ParTest1 2
With this option, it uses Object (String) array, and it doesn't scale at all!
I measured the GC time, but it was insignificant (and I also forced running GC before measuring times). I have tested with Java 6 (updates 43) and Java 7 (updates 51), but it's the same.
The code has comments with XXX and YYY describing the difference when arg.type=double or arg.type=Object option is used.
Can you figure out what is going on with the String-type argument passing here?
HotSpot VM generates following assemblies for reference type putfield bytecode.
mov ref, OFFSET_OF_THE_FIELD(this) <- this puts the new value for field.
mov this, REGISTER_A
shr 0x9, REGISTER_A
movabs OFFSET_X, REGISTER_B
mov %r12b, (REGISTER_A, REGISTER_B, 1)
putfield operation is completed in 1 instruction.
but there are more instructions following.
They are "Card Marking" instructions. (http://www.ibm.com/developerworks/library/j-jtp11253/)
Writing reference field to every objects in a card (512 bytes), will store a value in a same memory address.
And I guess, store to same memory address from multiple cores mess up with cache and pipelines.
just add
byte[] garbage = new byte[600];
to MyVisitor definition.
then every MyVisitor instances will be spaced enough not to share card marking bit, you will see the program scales.
This is not a complete answer but may provide a hint for you.
I have changed your code
Table1(int size) {
filled = new byte[size];
ivals = new int[size];
strs = new String[size];
Arrays.fill(filled, (byte)1);
Arrays.fill(ivals, 42);
Arrays.fill(strs, "Strs");
}
to
Table1(int size) {
filled = new byte[size];
ivals = new int[size];
strs = new String[size];
Arrays.fill(filled, (byte)1);
Arrays.fill(ivals, 42);
Arrays.fill(strs, new String("Strs"));
}
after this change, the running time with 4 threads with object type array reduced.
According to http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.7
For the purposes of the Java programming language memory model, a single write to a non-volatile long or double value is treated as two separate writes: one to each 32-bit half. This can result in a situation where a thread sees the first 32 bits of a 64-bit value from one write, and the second 32 bits from another write.
Writes and reads of volatile long and double values are always atomic.
Writes to and reads of references are always atomic, regardless of whether they are implemented as 32-bit or 64-bit values.
Assigning references are always atomic,
and double is not atomic except when it is defined as volatile.
The problem is sv can be seen by other threads and its assignment is atomic.
Therefore, wrapping visitor's member variables (i, iv, sv) using ThreadLocal will solve the problem.
"sv = (String)_v;" makes the difference. I also confirmed that the type casting is not the factor. Just accessing _v can't make the difference. Assigning some value to sv field makes the difference. But I can't explain why.

Good practice in using properties and local variables

Is it a good practice to use properties as local variable. In cases where there are many methods which uses some variables, In each method the variable value changes. This avoids many times creating new variables and the code increases. Any suggestion?
private void method1(){
int totalLength = length1 + 10;
int totalBreath = (breath1 + breath2) + 20;
int size = (totalLength * totalLength);
System.out.println(size);
}
private void method2(){
int totalLength = length1 + 20;
int totalBreath = (breath1 + breath2) + 30;
int size = (totalLength * totalLength);
System.out.println(size);
}
private void method3(){
int totalLength = length1 + 60;
int totalBreath = (breath1 + breath2) + 10;
int size = (totalLength * totalLength);
System.out.println(size);
}
As you can see, totalLength, totalBreath, size is repeated in every method. Can i make them as fields of the class? So, i need not declare it in every method.
private void method1(){
totalLength = length1 + 10;
totalBreath = (breath1 + breath2) + 20;
size = (totalLength * totalLength);
System.out.println(size);
}
I read your question as, "When should a local variable be promoted to be a field of the class?"
The best answer is "it depends" but then again, its accuracy is quickly eclipsed by its lack of usefullness.
Fields should have a relationship to the class itself, as in is the field an attribute of the class? I include an example below to illustrate the syntax difference, but I agree with this post that it should be avoided if it pollutes the meaning of the class.
Usually you only need to have a field when you need the value of the field to be maintained between calls to different methods for a given instance of the class, with the option of making it static when the value should be maintained between method calls for all instances of the class. It will depend on several factors like shop convensions, performance goals, existing codebase, etc. so there is no single right answer without specific code. This question seems to include similar points. If you find yourself using the approach below, you might consider other approaches like refactor the behavior into a help class.
Another question asks the same question but from the perspective of a programming student.
Examples:
public class VariableScope {
int field1 = 3;
void foo() {
int a = 2;
// variable passing in width
bar1(1);
bar2(1);
// variable passing in depth
bar3(a);
// uses a field to reduce variable passing
baz1();
baz2();
}
void bar1(int param) {
System.out.println("param=" + param);
}
void bar2(int param) {
System.out.println("param=" + param);
}
void bar3(int param)
{
System.out.println("Passing param to bar4");
bar4(param);
}
void bar4(int param){
System.out.println("param=" + param);
}
void baz1() {
System.out.print("field1=" + field1);
}
void baz2() {
System.out.print("field1=" + field1);
}
}
From what it sounds like, if you're using the variable for multiple methods you're should declare the variable as a global variable. But yes, If no other method needs that variable , and you don't want to be writing a bunch of return statements you can use local variables
I suppose you mean a field by property which usually has accessor and mutator (get,set-methods).
In common you should keep the scope of a variable as small as possible. An example if you use many for loops like:
for ( int i = 0 ; i < 10 ; i++ ) {
}
and replace this by
int i;
method1() {
for ( i = 0 ; i < 10 ; i++ ) {
// some code;
}
}
method2() {
for ( i = 0 ; i < 10 ; i++ ) {
// some code;
}
}
If one thread calls method1() and another one method2() you would face a race condititon.
You can easily introduce hard to find bugs in your code.
I assume you mean something like this:
Class foo() {
int x;
public bar() {
for(x = 0; x <100; ++x) ...
} }
No, it's not good practice.
One place where it can even be harmful is in the synchronization/concurrency/multi-threaded case: if you are working with class members, they are going to need be synchronized which will eat into performance. Otherwise you risk multiple threads overwriting the value of the field and that can lead to errors in your program (likely hard to debug).

Categories