Is there some way to get reasonable (not noticeable) starting times for Java, thus making it suitable for writing command line scripts (not long-lived apps)?
For a demonstation of the issue, take a simple Hello World program in Java and JavaScript (run w/ node.js) on my Macbook Pro:
$ time java T
Hello world!
real 0m0.352s
user 0m0.301s
sys 0m0.053s
$ time node T.js
Hello world!
real 0m0.098s
user 0m0.079s
sys 0m0.013s
There is a noticeable lag with the Java version, not so with Node. This makes command line tools seem unresponsive. (This is especially true if they rely on more than one class, unlike the simple T.java above.
Not likely, only thing you might be able to try is a different implementation of the JVM, but that probably won't change. Most Java apps are (relatively) long lived though and possibly interactive, which means the JVM startup time becomes lost in the noise of normal uses.
Have you actually tried timing a Java command-line app called repeatedly, though? I would expect after the first incarnation for the start-up time to be alleviated somewhat by the library classes being in the file system cache.
That said, yes, the Java platform is not one of the simplest and in any case you're not going to compete with a small native executable.
Edit: as you say that the timings above are for "warmed up" calls, then a possible workaround could be:
write the gubbins of your commands in Java
write a simple local continually running "server" that takes commands and passes them to the relevant Java routines
write a simple native command-line wrapper (or write it in something that's fast to start up) whose sole raison d'être is to pass commands on to the Java server and spit out the result.
This ain't nice, but it could allow you to write the gubbins of your routines in Java (which I assume is essentially what you want) while still keeping the command line model of invocation.
As others have said, the plain answer is just "not really". You can possibly make minor performance improvements, but you're never going to get away from the fact that the VM is going to take a while to start up and get going.
Make sure you haven't got the server VM selected for apps like this - that's one thing that really will increase the start up time.
The only real way round it is to compile Java to native code, which you can do with GCJ - so if you must write these apps in Java and you must have them faster, that might be a route to look down. Bear in mind though it's not that up-to-date and maintenance on it largely seems to be dying out too.
Haven't tried it yet but might be worth looking at nailgun. It will run your Java programs in the same JVM, so after "warming up" should be pretty fast. A "hello world" example goes from taking 0.132s to taking 0.004s
http://www.martiansoftware.com/nailgun/background.html
You can get a small speed-up with class data sharing https://rmannibucau.metawerx.net/post/java-class-data-sharing-docker-startup
A much bigger speedup should come from doing ahead-of-time compilation to a static binary using GraalVM native-image, although it's still tricky to use. A lot of libraries haven't been made compatible.
Related
Can Java run directly on hardware (assuming there's enough memory to include the necessary JRE/JVM? If it can, how does System.out.println work? I'd think there's nowhere for that output to go if it's all just on a cpu.
Directly on hardware? I am assuming you mean to ask if Java can run on a micro-controller? The answer is yes. The JVM is a virtual machine which is essentially its own operating system. The JVM was designed to do exactly what your wondering about. The JVM's two primary functions are to allow Java programs to run on any device or operating system, "Write once, run anywhere" and to optimize memory solutions.
To answer your second question. In order to visually see the output of a System.out.println() call one would simply need to provide the micro-controller with a screen. However, in theory the code would still execute without you seeing it being displayed. So one could write a Java applet that prints "hello world" and then load it onto a micro-controller and run it but that's just silly.
EDIT: I assumed you were not asking: "Can you program a micro-controller with Java" Silly of me, the answer is yes you certainly can; however, you wouldn't want too because the JVM is rather large and it would take up a lot of space. That being said, if you are interested take a look at: the STM32 Java-ready micro-controllers or the Renesas RX. Also, you could run a gutted JVM using uJ or NonvoVM.
The short answer is no, due to the JVM and write once run anywhere feature in java, the code is not ran directly on the hardware but within the JVM... THE JVM essentially acts as a middle man between different hardware/OS...if you look to accomplish this then take a look at C++
I am doing a project that requires me to repeatedly run a java function in python (it's like designing a learning algorithm in python but the value function was provided in java)
So what would be the practice for this scenario? Shall I use subprocess.run() to call the java function every time or shall I use the things like Py4J, Jython or JPype? What's the difference between using subprocess.run() and the others?
The efficiency should be the top concern since I need to run the same java function repeatedly.
Using subprocess has two problems. If neither one is relevant, it'll work fine.
If you're sending large amounts of data back and forth, you have to serialize it in some format to pass in via files and command-line arguments, or pipes or sockets, which can be slow.
If you're calling a whole lot of short functions instead of one occasional huge one, you'll be spending more time setting up and tearing down the JVM (and warming up the JIT) than doing actual work.
Jython has two problems. Again, if neither one affects you, it'll work fine.
It can't use many popular third-party libraries because they're built in C, for CPython.
It's out of date. The latest version implements Python 2.7, which is less than 2 years away from going out of support.
JPype has one problem, but it's a doozy. If the current fork does what you need and has no bugs blocking you, maybe it's ok anyway.
It's a vaporware project abandoned over a decade ago. It was picked up and knocked into shape by someone else a few years ago, and the current maintainer is keeping it running, and occasionally gets patches for things like working in 64-bit cygwin or updating to OS X 10.9, but it's not exactly a vibrant project with major support behind it.
Py4J has two problems.
It's incomplete. Not unusuable, and not completely moribund, but there hasn't been any visible work on it in over a year, and nobody seems interested in anything but the minimal functionality needed for Apache Spark.
It's doing the same kind of serialization you'd do with subprocess behind your back, and more beyond that for every call you make, and the FAQ justifies this by saying performance is not a priority. (Spark just ignores all of that and uses its own channels for everything.)
For more minimal use—just starting up a JVM and setting up a socket to it—it may be better than subprocess because you don't have to keep starting and tearing down a JVM, but writing a socket protocol on both sides is a little bit more work than storing files and passing filenames on the command line. (Not a huge hurdle, but a problem if you've never done this kind of thing before.)
You may also want to look at transpilers. I don't know much about any of them, but I've talked to people who are using BeeWare to compile Python 3.4 code to Java source code that they then build together with their native Java code. I'm pretty sure this won't work if you're using any C extension, but if that's not a problem for you, it might be worth considering.
I'm a front end developer that's looking to get into some other languages such as Java or C++. I have an idea for a program and was just looking for an answer to something. What I would like to do is build a program and boot directly to that program. For example I have an old computer and I wipe the hard drive clean. So they is nothing currently on it. Not even an OS. I want to build a program that I can install to the hard drive that will boot straight into the program once started. Would this be considered an OS?
No you don't. Unless you want to spend many years, writing drivers for your graphics card, harddisk controller, usb controller, dma controller and all the other hardware your computer have.
What you want is a minimal operation system, which include just the kernel, and a runtime library and which start your program and nothing else on startup. A minimal Linux such as linux from scratch or bsd would be a good starting point.
First of all you need to decide your your program needs what. I mean should operate in Protected mode or the routine you have is tiny, so it is enough to run before entering protected mode (i.e. in real mode).
Here you can do three things
Modify bootloader to jump the execution to your code . Then Your code can resume normal os initialization.
Modify your os kernel early initialization code So that it executes your code before entering protected mode
I think your code will not be harmed if a bit of os portion is running. So you can write your routine before full kernel initialization.
Now note that for the later two point you need to modify your kernel, which is not easy (not even always possible)
Now the problem in first approach: Nothing will be ready for you, not even a regular c library or divice drivers , so you have to write every raw bit of code by hand which is crude.
This is off course not possible in java. Because the jvm will not be ready for you.
Now practically: there are lot of tiny os available, use one of them and modify as per your need. use this link to get a complete list of what is available for you.
First, Java is right out. You cannot possibly do this in Java without enormous amounts of tool-building. Java is not suited for this task at all.
You can do it in C++ or C. The search terms you are looking for is operating system development. This would probably not technically be considered developing an Operating System since it wouldn't run other programs, but the information about how to get through the boot-up procedure and establish a minimal environment are going to be most easily found in the category of operating system development. Some reasonable starting resources for that can be found at the OS Dev Wiki.
Alternately, you could take an existing small open-source OS and modify what it does after the boot-up sequence completes. If your program is intending to do anything more than just use the keyboard and the screen in text mode, there need to be device drivers. Thus, depending on the project, changing an existing OS may be the easiest route because you won't need to write your own device drivers for any devices you want to use.
Java can't run without Environment. If you want to run you program on you machine without OS, Java is a wrong choice.
C++ program can run without OS, but it's difficult to write a bootable program in C++.
If you want to write your own bootable program, you should use assembly for boot and load function, with some knowledge to use hardware in low level.
You have to have an operating system, so your program would be the operating system (or you would have to use another one and write it for that). It's certainly possible in C++, but it's not really possible to write an operating system in java.
Unless you want write something in (for example) Open Firmware and Forth or say a ROM BASIC. You'll probably qualify as a boot loader. Your application may qualify as an operating system. In my opinion, and a modern context, it entirely depends on how much functionality it provides to hosted applications. I'm not sure that something like FreeDOS would be considered an operating system (no pre-emptive task scheduling or GUI for example) given modern computers (I don't care to argue the point either way).
I'm trying to figure out what is more efficient in terms of server load which is pretty big at the moment, additional overload wouldn't be a great idea. Here is what I need to do :
I have a log file which changes, sometimes every second other times every few minutes or so which is not really relevant to this question. I'm trying to find out whether it is more efficient to start up java file with a cron job or to write shell script which will be executed by cron also, this is all under linux. Which is the better idea?
Checking log files are mostly I/O anyway so the actual CPU time in both cases are negligeable here. So what matters is the startup time, and spawning a shell script in Linux is magnitudes faster than starting up the JVM.
As Peter said, it's dependent on what the program is supposed to do.
Generally, starting a Java program has quite a bit of overhead in comparison to a shell script. If some complex operations have to be done, however, java may well be your best bet.
I personally would choose Python for scripts for which shell is not really suited and for which Java may be overkill :)
Als be aware that system administrators can often read and understand shell scripts quite well, but Java is a different matter. That may be a problem, or maybe not.
In general Perl is considered to be best for text parsing, but since all you need to do is print the changes to console you should simply do a tail -f rather than cron jobs etc.
there are many tools in *nix that parses files efficiently. eg grep,tail. These tools are coded in C with very efficient algorithms for parsing files. Definitely go for these shell tools. No Java please. Firstly, starting it up is slow. You can't compare it with running a C program like grep. Secondly, you will find it troublesome (in terms of compilation) to troubleshoot your script if anything goes wrong.
If you have to spawn n^2 processes for n lines of log files, you have to optimize even beyond bash. If you want to spawn only a sinlge process, language will not make a difference, imho.
I would rather check out in which language I/O and text processing is better for your needs. If a simple text processing in Java is too much on a "server", doing the same in assembly will be too much as well.
I've a bash script that sequentially calls a java program. That's a bit tricky but mainly what i do is to have a loop and executes about 1500 times the same java program with different arguments.
My question is, when using java 1.5 (the sun VM), each time I'm calling the java program a new instance of the jvm is created ? (I'm not sure that's the right vocabulary...)
Should I avoid this situation by introducing a level of indirection, i.e building a list of all the parameters and then executing one java program which takes these parameters and executes what was previously my entry point ?
Or can I deal with the problem by configuring the JVM as resident or something like that and dynamically invokes my program....
hope this is clear....
thx...
You could save the parameters into a file and use the Java program to process it without constant restart. You could also pipe in the parameters into the running Java app through the console, similarly as for example ls | grep java
Edit: And for the first question. I doubt the java runtime would stay deliberately in memory. Probably most JRE files would remain in the disk cache anyway. On Windows there is a Java Quick Start service which keeps the JRE files around to reduce the startup time for a java program. Don't know whether there is a similar thing for *nix.
Obviously having all the parameters beforehand and running the program once after that would be the best solution. If you cannot do that for any reason i have a very dirty solution to this. Have your program register a port and listen to it for input. Then simply pass the arguments to that port and have your program handle them as a new instance.
JVM startup is notoriously slow, and it certainly not intended to be done in a loop like that. Unfortunately the only way to avoid this if you are passing command line parameters to the java program is to modify the java program itself in some way to have alternative forms of interaction (either from the console, or a port, or a read a file). Java Quick Start is the only (closest thing to a) solution if the java program cannot be changed.
The real solution is to change the Java program. The most obvious change would be to have your loop write to a file, and then start the java program that would read the file one line at a time. That works if the loop doesn't care about the results from the java program for the next set of parameters.
If it does, then it would really be necessary to understand that relationship to advise on an appropriate solution. The socket solution suggested by Savvas is certain a general purpose solution, but there may be better options, depending on what you need to accomplish.
You can use a launcher like in the answer to
Simultaneously run java programs run on same JVM? to read input line by line and start your program's main() method.