[HN Gopher] Continuous delivery makes JVM JIT an anti-pattern
       ___________________________________________________________________
        
       Continuous delivery makes JVM JIT an anti-pattern
        
       Author : foxgrover
       Score  : 20 points
       Date   : 2021-02-01 17:11 UTC (5 hours ago)
        
 (HTM) web link (blog.astradot.com)
 (TXT) w3m dump (blog.astradot.com)
        
       | lazide wrote:
       | Every serious Java based Web App I've ever worked on had a
       | prewarm step or continuous probing setup for exactly these
       | issues. It isn't unique to Java either - lots of languages have
       | lazy library or dependency loading, or runtime caching of
       | external files or the like that you want to do before you start
       | serving requests.
        
         | kimi wrote:
         | Or a cache to be loaded. In related news, "Continuous delivery
         | makes caching an anti-pattern".
        
           | p2t2p wrote:
           | Not really. You move cache off-heap in Java terms and it
           | persists it between restarts. One Russian social network has
           | about 60 gigabytes of stuff cached that way
        
       | ncmncm wrote:
       | This is about runtime binding vs static binding, not static
       | objects or static members. There is still a "this", but the code
       | that will run is known up front -- "ahead of time".
       | 
       | C++ went through this 25+ years ago: runtime binding, what in C++
       | is virtual functions, is a _niche technique_. Most C++ programs
       | don 't use it at all, or use it in only one or two spots. When it
       | is the right thing, it makes the work convenient, but it really
       | is just a dance with function pointers. In C++, templates do the
       | heavy lifting.
       | 
       | Java never offered any other support for organizing programs, so
       | inheritance and virtual functions have been your go-to for
       | everything, no matter how bad the fit. In a static call there is
       | only one bit of code to run, and it never changes over the life
       | of the program. Just like _almost everything_ , really, except
       | here your runtime knows up front.
       | 
       | It was always a dumb choice to make member functions default to
       | virtual semantics, when they almost always don't need it, and it
       | just costs performance to no purpose. That is what comes out of
       | treating language design as a marketing exercise: Java's
       | designers really (and openly) cared less than nothing about
       | object-oriented programming. They thought people really ought to
       | be coding Lisp. Forcing runtime binding was a way to sneak in
       | something a little bit lispy, and maybe get people used to
       | production code running no faster than Lisp.
        
         | tom_mellior wrote:
         | > It was always a dumb choice to make member functions default
         | to virtual semantics, when they almost always don't need it,
         | and it just costs performance to no purpose.
         | 
         | If you _actually_ don 't need it (i. e., your hot methods are
         | never overridden), then the JIT will trivially compile those
         | "virtual" method calls as non-virtual ones. It has all the
         | information it needs, since it knows what classes are loaded.
         | It can invalidate its code if necessary, if you load more
         | classes that do add overrides. So no, it does not cost
         | performance at the call site. It does cause the compiler to do
         | work, but nothing fancy.
        
         | astrange wrote:
         | Java is based on Objective-C, which is based on Smalltalk. In
         | both of those all method calls are messages, which are even
         | more abstract than virtual functions but a lot more useful.
         | 
         | Java simplified things for performance but ended up with a much
         | weaker and less expressive system, and probably didn't go hard
         | enough for static performance either. Still, it's less of a
         | performance issue than the lack of value types.
        
       | filereaper wrote:
       | >Molding a 25 year old runtime ecosystem to adapt to AOT
       | compilation feels like putting lipstick on a pig.
       | 
       | Other JVMs like J9 have had AOT support for decades now, its not
       | "lipstick on a pig". There's plenty of material from previous
       | JVMLS meetups about AOT.
        
       | olliej wrote:
       | Others have raised good points, but seriously something is wrong
       | if you're pushing updates that require restarts every hour.
       | 
       | I get the idea of "continuous deployment", but this is sounding
       | like restart-per-commit. At that point I question how much
       | qualification and validation is happening. No one say unit tests,
       | they aren't sufficient, and I've worked on multiple projects
       | where the pre-commit test suite runs alone can take more than an
       | hour. Even with those tests there are semi-regular breakages.
        
       | winrid wrote:
       | Bad deployment system. You should do an A/B deployment and warm
       | up the services/caches before the switch, so that the
       | architecture handles the problem and not the programming
       | language/VM.
       | 
       | At FastComments we run our E2E tests on the new instance to JIT
       | the app. Before the Jit API calls can take 100ms, and after
       | 10-30ms. Still, that is fast enough that most people wouldn't
       | notice...
       | 
       | Also, the problem is not Java. Your application probably has way
       | too many abstractions for a simple login page.
        
       | commandlinefan wrote:
       | > Go and Rust encourage use of static method calls
       | 
       | Not having worked in Go or Rust but having done a lot of work in
       | Java and C/C++, I'm curious how this works out in practice. My
       | experience with developers who default to static method calls
       | rather than objects in Java or C++ is that they also default to
       | static (and therefore global) data as well. Of course, you don't
       | have to do that: you can pass pre-transaction data structures to
       | the static functions and let them operate on them, but that's
       | what object-oriented programming is for in the first place.
        
         | remram wrote:
         | Rust is not object-oriented.
         | 
         | You can make "virtual method" calls in Rust (dynamic dispatch
         | through a "trait object", a vtable). This is explicit though,
         | the type will look like `Box<dyn MyInterface>` where Java says
         | `MyInterface` (box = object allocate on heap, dyn = virtual
         | method calls).
         | 
         | I think you might be misunderstanding what "static method call"
         | means: in this context, it means a method which is not
         | "virtual" (in C++ parlance), not a method which is "static" (in
         | C++ parlance, e.g. not called on an object).
        
           | commandlinefan wrote:
           | You're correct, I was assuming that "static" in Rust & Go
           | meant the same thing it meant in Java (which is different
           | than what it means in C, of course). Thank you for
           | clarifying.
        
       | philipkglass wrote:
       | The article's "container lifespan" chart shows that 21% of
       | containers live less than _10 seconds_ and 54% live  <= 5
       | minutes. If the base data set has that many very-short-lived
       | containers, it's probably not representative of containerized
       | persistent services. How many services get CD updates every 10
       | seconds?
       | 
       | Indeed, the original Sysdig report that the chart comes from
       | makes this case:
       | 
       | https://sysdig.com/blog/sysdig-2019-container-usage-report/
       | 
       | "Many containers need to only live long enough to execute a
       | function and then terminate when it's complete. Seconds may seem
       | short, but for some processes, it's all that is required. We
       | believe the increased use of Kubernetes Jobs that run finite
       | tasks like batch jobs contributed to this growth. In fact, we
       | expect short lifespans to increase, especially on serverless
       | platforms that are well-suited to running short term tasks."
        
       | tom_mellior wrote:
       | > Production Java apps also typically run with APM tracing agents
       | that rely on runtime bytecode instrumentation. [...] It is easier
       | to start afresh with modern compiled languages like Go and Rust.
       | 
       | I wonder how they instrument their Go and Rust programs. If they
       | decide not to, maybe it's not that important for the Java version
       | of the same code either.
        
       | hctaw wrote:
       | > 74% of containers have lifespans <= 1 hour
       | 
       | This sounds like a design flaw in the architecture. You don't
       | tear down a house to replace a lightbulb.
        
         | Hallucinaut wrote:
         | Nor do you spent 10 hours with a magnifying glass and tweezers
         | to attempt to change the filament on a burnt out light.
         | 
         | Which analogy you consider spurious likely depends on what kind
         | of theatres of IT war you've been in.
        
       ___________________________________________________________________
       (page generated 2021-02-01 23:03 UTC)