Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

Hey folks,

I'm set to leave grad school this term and I've accepted a position at Amazon, where I'm given to understand that I'll be doing most of my development in Java. I've not touched the language since my undergraduate days (the last two or so years have been spent living in C and Python), and this was the era of Java 1.5, so I've not touched generics and whatever other goodies Java 6 and 7 have provided.

Does anyone have a recommendation for a book that'll get me up to speed? All the books I thumbed through in my department's reading room seem to be geared towards newbie programmers or are just flat-out outdated.

Thanks!

Adbot
ADBOT LOVES YOU

Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

I'm starting a job next month that will primarily have me be writing Java, so I'm going through Effective Java as per the recommendations in this thread. I've got a question about how method dispatch works when you start calling super(). Consider Item 16 in Effective Java, 2nd Ed.:

code:
public class BrokenEncapsulationTest {

  @Test
  public void testAddCount() {
    InstrumentedHashSet<String> set = new InstrumentedHashSet<String>();

    set.addAll(Arrays.asList("Snap", "Crackle", "Pop"));

    assertEquals(3, set.addCount);
  }

  public static class InstrumentedHashSet<E> extends HashSet<E> {

    public int addCount = 0;

    @Override
    public boolean add(E a) {
      addCount += 1;
      return super.add(a);
    };

    @Override
    public boolean addAll(Collection<? extends E> c) {
      addCount += c.size();
      return super.addAll(c);
    }
  }
}
The assertion fails with 6 instead of 3, I read, because HashSet::addAll() calls HashSet::add() under the hood, so addCount gets incremented more times than it should be.

The progression of calls I was expecting was InstrumentedHashSet::addAll -> HashSet::addAll -> HashSet::add() x 3. That is, I was under the impression that super() kind of acts like a superclass cast, where once you call super() the HashSet object has no notion that it's not at the end of the class hierarchy. What's the right way to think about this?

Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

Right, that makes sense. Thanks, fellas.

Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

The official Java documentation's tutorials are surprisingly good. If you can get through the "Essential Java Classes" module, you'll be laughin' for any first-year Java class.

Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

Why don't you try it in your language of choice and see? :confused:

code:
[ntaylor@Alessan ~]\$ python              
Python 2.7.1 (r271:86832, Aug  5 2011, 03:30:24) 
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> -13 % 2
1
>>> ^D
[ntaylor@Alessan ~]\$ irb
>> -13 % 2
=> 1
>> ^D%                                                                          
[ntaylor@Alessan ~]\$ scala    
Welcome to Scala version 2.9.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_35).
Type in expressions to have them evaluated.
Type :help for more information.

scala> -13 % 2
res0: Int = -1
scala>

Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

Kilson posted:

Unfortunately, the machine with the problems is not a machine I have access to, so I can't play around with it. I've looked at a couple VMs with similar allocations and haven't seen the problem there.
Can you get a GC log? If you're not already, run with


-XX:+PrintGC
-XX:+PrintGCDetails
-verbose:gc
-Xloggc:gc.log


and see how far it gets.

My prediction is that this is somehow happening in a full GC (which is O(size of the whole heap) as opposed to O(size of the live set), hence why you're seeing it happen when you increase the heap size), but it's not clear to me either why it's happening.

Dijkstracula fucked around with this message at 17:23 on Aug 4, 2014

Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

Safe and Secure! posted:

I want to know how the JVM works, especially garbage collection. I've been going through the JVM spec, but it looks like the way garbage collection works depends on the specific implementation. So is there a single implementation I can take to be mostly canonical? Like, if I learn how Oracle's implementation works, and then maybe how the JVM used by Android works, then that's enough? What would I even want to Google here to find specific information on both of those implementations work?
Depending on how much language runtime knowledge you have, you might want to work up to OpenJDK-specific stuff by starting with the JRockit book, which does a great job of covering the fundamentals of stuff like JIT compilers, generational GCs, etc.

Sadly, there used to be a lot of great Sun blogs about OpenJDK internals but the Oracle rebranding means most URLs are dead ends. :( After the above, I'd actually recommend Charlie Hunt's Java performance book, as it's pretty tightly coupled to OpenJDK and gives a pretty solid informal description of the major GCs (the Parallel collector, CMS, and G1).

After that, frankly, the source is pretty readable and that's where I'd point you to next (modulo C2, the server compiler, which is straight-up :pcgaming:)

edit: forgot to mention that if you're interested in a denser, GC-specific read that isn't tied to any particular runtime, you can't go better than The Garbage Collection Handbook.

Was there anything in particular you were interested in? Up until recently I was paid to hack on OpenJDK so I can probably point you in the right direction if you can't find what you're after.

Dijkstracula fucked around with this message at 05:05 on Aug 11, 2014

Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

I mean there's nothing stopping you from keeping a backing store of "interned" objects, but I can't imagine the performance gains would outweigh just allocating the objects as need be, and it'll certainly be more costly w.r.t. your program's memory usage. Also, if your intent is that the elements in the view are immediately transformed again, then those allocated objects won't be long-lived - allocation is cheap but object tenuring is expensive, so I can't see trying to have a behind-the-scenes cache yielding you any benefit.

Of course, benchmark, benchmark, benchmark and prove me wrong :v:

Adbot
ADBOT LOVES YOU

Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

Ornedan posted:

Are these some optimisation flags Eclipse enables by default that could cause the difference?

e: oh wtf, whichever is the first one I measure time for is as fast in the javac-compiled bytecode as in Eclipse-compiled. So the javac results change if I reorder the speed tests.
sounds to me like you're starting to see interference from the profile-guided JIT; it's possible that you're reordering the tests across some internal boundary/threshold where recompilation and optimization takes place. HotSpot (being the JVM implementation you're most likely using) actually has three wayds to execute Java code: a stack interpreter, the Client Compiler (called "c1" internally) and the Server Compiler ("c2"). Both compilers are used at runtime to generate native assembly with the so-called "tiered compilation" approach: C1 is optimised for compilation speed and C2 is optimised for code quality, so C2 is used for hot code (for some internally determined definition of "hot"); infrequently-called code may not ever hit the server compiler (though this is configurable of course).

For microbenchmarks like this, you may wish to force HotSpot to always use the server compiler, under the assumption that your code in a real setting would trigger the optimizing compiler threshold anyway (which, by the sound of things, is indeed plausible). There's a HotSpot flag that will let you disable tiered compilation, and another that will set the C2 hot code threshold low enough to be triggered early.

e: beaten massively, this is what I get for leaving an old tab open :shobon:

Objective Action posted:

Generally I would recommend that you use something like the Java Microbenchmarking Harness and also that you put the code into a loop, let it execute a few times, and then run it for a few thousand iterations and aggregate the results. That will let the JVM have time to warm up and do its runtime optimizations so your numbers are more likely to be honest to real world performance.
oh, yes, I didn't think of this but if you're not already using jmh then strongly advise you to do so too.

Dijkstracula fucked around with this message at 15:35 on Jul 10, 2023

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply