3

So my goal is simple: I want to create a high-priority thread in Java without using RTSJ (Real-Time Java VM) or some other proprietary JVM. Let's assume you never create any garbage so GC will not be the culprit. Let's assume that I have 4 processors. Is it doable? If not, is it possible to count how many times my thread was preempted?

@Gray: I want as much real-time response with as little latency as possible without having to go to RTSJ and special OSs

@sarnold: You are very right. If you accomplish that in the JVM level but not your JVM is preempted by the OS you have the same problem in a lower level. Let's assume that it is possible to hack and/or use a linux distribution tuned not to do that.

@StephenC: I already know it can't be done. That's why I want to do it. :) If I at least can detect preemption I will have a way to measure my progress.

JohnPristine
  • 3,485
  • 5
  • 30
  • 49
  • 3
    This smacks a lot like premature optimization to me. You are asking for things that a normal JVM does not provide. Can you edit your question and explain _why_ you need to do this? – Gray Mar 28 '12 at 23:00
  • Are you only interested in JVM-level pre-emption or are you also interested in OS-level pre-emption? – sarnold Mar 28 '12 at 23:00
  • @sarnold - If you are talking about HotSpot, there's no distinction between the two. All HotSpot Java thread scheduling and preemption is performed by the OS. – Stephen C Mar 29 '12 at 00:26
  • @StephenC: cool. When I last really _did_ Java, GreenThreads seemed the Wave Of The Future. – sarnold Mar 29 '12 at 00:27

3 Answers3

3

No. Standard Java doesn't support this.

I want as much real-time response with as little latency as possible without having to go to RTSJ and special OSs

"As little latency as possible" is not a quantifiable requirement.

However, as I and others have said in response to your many questions in this area, JavaSE is not designed for this kind of thing, and doesn't / cannot provide any guarantees of latency. Indeed, many aspects of the generic Java core libraries are specified to make it clear that there are no performance-related guarantees on the standard Java platforms.

In respect to this particular question, the Java threading specs say that thread priorities are advisory only. There are no guarantees that a high priority thread won't be preempted by a lower priority thread. Actual thread scheduling and switching policies are implemented by the host operating system and are beyond Java's control.

Let's assume that it is possible to hack and/or use a linux distribution tuned not to do that.

If you are making that assumption, you may as well just hack the operating system to make the thread scheduler, etc behave how you want ... assuming that that it is technically feasible. But also beware that hackery at that level can result in unanticipated problems for applications (like the JVM) that are not designed to cope with (for example) non-preemptable threads preventing the GC from running.

If I at least can detect preemption I will have a way to measure my progress.

A Java thread can't detect that it has been preempted, or that another Java thread has been preempted. I don't think that the OS-level native thread APIs that the JVM uses support this.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • 1
    This can be done and have been done before. Nothing is impossible. :) – TraderJoeChicago Mar 28 '12 at 23:55
  • @SergioOliveiraJr. I didn't say it was impossible. Anything is possible (in theory) if you have the time and skills to modify JVMs / operating systems to behave how you want them to. – Stephen C Mar 29 '12 at 00:01
  • Please explain the downvote. If it was you @JohnPristine, just say so and I'll stop answering your questions. – Stephen C Mar 29 '12 at 00:06
  • Incidentally, `sched_setscheduler(2)` can be used to place processes in `SCHED_FIFO` or `SCHED_RR` priority classes -- they can only be pre-empted by higher-priority realtime-scheduled processes. (So run an `ssh` and `bash` at higher-priority while getting it to work, so you can fix problems. :) – sarnold Mar 29 '12 at 00:32
  • @sarnold - yea, but you won't be able to get Java to do that without modifying the JVM. And that point, it ain't really Java anymore. – Stephen C Mar 29 '12 at 01:00
  • This can be done on Linux easily. The JVM supports it. The only catch if that you must run the JVM as root. This is enforced by the OS, not by the JVM. – TraderJoeChicago Mar 29 '12 at 02:28
  • 2
    @StephenC: oh, it's easier than that; the `sched_setscheduler(2)` call takes a pid as a parameter, so it can be called on other processes. `schedtool(8)` is an easy mechanism to set the scheduling class on another process (similar to `renice(1)`) in case you're not interested in writing your own wrapper. If you do want to write a wrapper, it ought to be simple JNI, no JVM fiddling needed. – sarnold Mar 29 '12 at 22:26
  • @sarnold You are the best sarnold !!! Now check here: http://stackoverflow.com/questions/9934517/how-to-find-a-java-thread-running-on-linux-with-ps-axl – JohnPristine Mar 29 '12 at 22:32
  • @John: Don't overlook the meat of Stephen's answer; he knows Java and the JVM _way_ better than I do. I just know a mechanism you can use at the OS level to run a process at a real-time priority. What goes on inside the JVM is as important. – sarnold Mar 29 '12 at 22:52
  • @JohnPristine - well there you go. Off you go and code it up. I think that finding out what the TID of a thread is going to be a significant hurdle. And then you've got to write the JNI code etc ... and deal with any JVM stability problems caused by freezing out the GC thread(s). And I certainly wouldn't knowingly use any application that resorted to this kind of stuff. – Stephen C Mar 30 '12 at 06:02
1

I believe you're looking for this: http://en.wikipedia.org/wiki/Real_time_Java Regular Java doesn't provide such an ability.

Eugene Retunsky
  • 13,009
  • 4
  • 52
  • 55
0

Yes it is possible! But isolating a cpu core so it is not preempted by any user or kernel process is a OS configuration unrelated to your application. After you do that you can use a thread affinity library such as CoralThreads to pin your thread to the isolated cpu core. This greatly reduces variance. Below a simple code example so you get the idea:

import com.coralblocks.coralthreads.Affinity;

public class Basics {

    public static void main(String[] args) throws Exception {

        Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {

                // must be the first thing inside the run method
                Affinity.bind();

                try {

                    while(true) {

                        // do whatever you want here...
                    }

                } finally {

                    // must be the last thing inside the run method
                    Affinity.unbind(); 
                }
            }
        }, "MyPinnedThread");

        System.out.println();
        Affinity.printSituation(); // nothing done yet...

        // assign thread to processor:
        int procToBind = Integer.parseInt(args[0]);
        Affinity.assignToProcessor(procToBind, thread);

        Affinity.printSituation(); // now you see it there...

        // start the thread!
        thread.start();

        Affinity.printSituation(); // now it is running with a pid...
    }
}

Output:

$ java -cp coralthreads-all.jar com.coralblocks.coralthreads.sample.Basics 2

CpuInfo: [nChips=1, nCoresPerChip=4, hyper-threading=true, nProcessors=8, procIds=0,1,2,3,4,5,6,7]

Chip-0:
    Core-0:
        Processor-0: free
        Processor-4: free
    Core-1:
        Processor-1: free
        Processor-5: free
    Core-2:
        Processor-2: free
        Processor-6: free
    Core-3:
        Processor-3: free
        Processor-7: free

CpuInfo: [nChips=1, nCoresPerChip=4, hyper-threading=true, nProcessors=8, procIds=0,1,2,3,4,5,6,7]

Chip-0:
    Core-0:
        Processor-0: free
        Processor-4: free
    Core-1:
        Processor-1: free
        Processor-5: free
    Core-2:
        Processor-2: assigned to MyPinnedThread (not-started)
        Processor-6: free
    Core-3:
        Processor-3: free
        Processor-7: free

CpuInfo: [nChips=1, nCoresPerChip=4, hyper-threading=true, nProcessors=8, procIds=0,1,2,3,4,5,6,7]

Chip-0:
    Core-0:
        Processor-0: free
        Processor-4: free
    Core-1:
        Processor-1: free
        Processor-5: free
    Core-2:
        Processor-2: bound to MyPinnedThread (running pid=2180)
        Processor-6: free
    Core-3:
        Processor-3: free
        Processor-7: free
rdalmeida
  • 1,806
  • 12
  • 16