0

For some reason, my method "bishops" runs much faster when called from the main method than from the static initialization block. Is this normal, or a bug?

public class Magic
{
    public static void main(String[] args)
    {
        bishops();
    }

    public static void bishops()
    {
        //PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("bishops.txt")));
        BISHOP_SHIFTS = new int[64];
        BISHOP_COMBOS = new long[64][];
        for (int square = 0; square < 64; square++) {System.out.println("bbb " + square);
            int NUMBER = bitCount(BISHOP_ATTACKS[square]);
            BISHOP_SHIFTS[square] = 64 - NUMBER;
            long x = BISHOP_ATTACKS[square];
            long[] MAPS = new long[NUMBER];
            for (int n = 0; n < NUMBER; n++) {
                int i = bitScan(x);
                MAPS[n] = (1L << i);
                x -= MAPS[n];
            }
            int C = 1 << NUMBER;
            BISHOP_COMBOS[square] = new long[C];
            for (int i = 0; i < C; i++) {
                BISHOP_COMBOS[square][i] = 0;
                int j = i;
                for (int n = 0; n < NUMBER; n++) {
                    if ((j & 1) == 1)
                        BISHOP_COMBOS[square][i] |= MAPS[n];
                    j >>>= 1;
                }
                //out.println("SQUARE " + square);
                //out.println(toBitboardString(BISHOP_COMBOS[square][i]));
                //out.println();
            }
        }
        //out.close();

        bishopMagics();
    }

    public static void bishopMagics()
    {
        BISHOP_MAGICS = new long[64];
        Random r = new Random();

        for (int square = 0; square < 64; square++) {System.out.println("asdffff " + square);
            int i;
            int LENGTH = BISHOP_COMBOS[square].length;
            long magic;
            do {
                magic = r.nextLong() & r.nextLong() & r.nextLong();
                //final int COUNT = bitCount(BISHOP_MASKS[square]);
                boolean[] used = new boolean[LENGTH];
                for (int j = 0; j < used.length; j++)
                    used[j] = false;
                for (i = 0; i < LENGTH; i++) {
                    int index = (int) ((BISHOP_COMBOS[square][i] * magic) >>> BISHOP_SHIFTS[square]);
                    if (used[index])
                        break;
                    else
                        used[index] = true;
                }
            } while (i < LENGTH);
            BISHOP_MAGICS[square] = magic;
            System.out.println(magic);
        }

        //bishopTable();
    }

    /*
     * Lots of stuff omitted
     */

    static
    {
        //bishops();
    }
}
nhahtdh
  • 55,989
  • 15
  • 126
  • 162
functionptr
  • 317
  • 4
  • 10

1 Answers1

6

It will run much faster the second time than the first as the JVM warms up (loads class es and compiles code). The static block is always called first.

Try running it twice from the main() or the static block and see how long it takes each time

BTW: I would take out any logging to the console as this can slow down the code dramatically.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Although it will only show the differences caused by the JIT compiler, you can disable it using the flag `-Djava.compiler=NONE` when you invoke `java`. – Thomas Owens Jun 27 '12 at 15:10
  • @ThomasOwens It still has to load classes and methods the first time which it doesn't have to do the second time. – Peter Lawrey Jun 27 '12 at 15:12
  • @Peter you're right; I tried calling bishops twice in the static initialization block; the first call was slow, the second call was superfast. I'll accept the answer in 5 minutes – functionptr Jun 27 '12 at 15:13
  • However, is there anyway to solve this problem? I need bishops to be called in static init block... – functionptr Jun 27 '12 at 15:15
  • You have already proven it makes no difference whether its called in the static block or not. The problem is the time it takes the JVM to warm up. The only way to fix this is to have the JVM running all the time and use it as a service. i.e. don't keep restarting it. – Peter Lawrey Jun 27 '12 at 15:17
  • but it runs superfast in main while the jvm is warming up...., it's only slow in static; I actually used the code "bishops(); bishops();"; didn't run program twice in a row – functionptr Jun 27 '12 at 15:26
  • In some JVMs, the static block is never optimised, but since you are calling a method, this shouldn't matter. Why do you need it called in a static block and not in main()? – Peter Lawrey Jun 27 '12 at 15:31
  • another class is going to use the array, but I need it initialized only once, and I'm never going to call the main method of the other class because my chess engine starts in yet another class...maybe I need to think of another design – functionptr Jun 27 '12 at 15:41
  • When you call the second class you can pass it the results. i.e. use a "function" ;) – Peter Lawrey Jun 27 '12 at 15:55