G
G
General-purpose2021-12-11 00:56:13
Java
General-purpose, 2021-12-11 00:56:13

How to force a program to use the CPU only as needed?

I'm trying to correctly implement a test program in Java, Windows 7.
Problem: when the program is running, its process consistently uses a certain % of the CPU, even if it's an empty loop.
61b3c35eba3b1641168586.png
This is bad, ugly, wrong.
Tell me how to fix this, give the code or something to read on the topic.

I understand that in any program, if it is not a one-time script, there is at least one cycle. But I have something with an empty one, that with a full cycle, the processor is loaded by 8%. But, for example, a screw calculator does not create a visible load at all, but it reacts to user actions. How does he, for example, know if a button is pressed? To do this, you need to execute the loop as often as possible, but there is almost no load on the processor. Some kind of mystic.

Here is the specific code, Hello World LWJGL
import org.lwjgl.*;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.*;

import java.nio.*;

import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryStack.*;
import static org.lwjgl.system.MemoryUtil.*;

public class HelloWorld {

  // The window handle
  private long window;

  public void run() {
    System.out.println("Hello LWJGL " + Version.getVersion() + "!");

    init();
    loop();

    // Free the window callbacks and destroy the window
    glfwFreeCallbacks(window);
    glfwDestroyWindow(window);

    // Terminate GLFW and free the error callback
    glfwTerminate();
    glfwSetErrorCallback(null).free();
  }

  private void init() {
    // Setup an error callback. The default implementation
    // will print the error message in System.err.
    GLFWErrorCallback.createPrint(System.err).set();

    // Initialize GLFW. Most GLFW functions will not work before doing this.
    if ( !glfwInit() )
      throw new IllegalStateException("Unable to initialize GLFW");

    // Configure GLFW
    glfwDefaultWindowHints(); // optional, the current window hints are already the default
    glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation
    glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable

    // Create the window
    window = glfwCreateWindow(300, 300, "Hello World!", NULL, NULL);
    if ( window == NULL )
      throw new RuntimeException("Failed to create the GLFW window");

    // Setup a key callback. It will be called every time a key is pressed, repeated or released.
    glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
      if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE )
        glfwSetWindowShouldClose(window, true); // We will detect this in the rendering loop
    });

    // Get the thread stack and push a new frame
    try ( MemoryStack stack = stackPush() ) {
      IntBuffer pWidth = stack.mallocInt(1); // int*
      IntBuffer pHeight = stack.mallocInt(1); // int*

      // Get the window size passed to glfwCreateWindow
      glfwGetWindowSize(window, pWidth, pHeight);

      // Get the resolution of the primary monitor
      GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());

      // Center the window
      glfwSetWindowPos(
        window,
        (vidmode.width() - pWidth.get(0)) / 2,
        (vidmode.height() - pHeight.get(0)) / 2
      );
    } // the stack frame is popped automatically

    // Make the OpenGL context current
    glfwMakeContextCurrent(window);
    // Enable v-sync
    glfwSwapInterval(1);

    // Make the window visible
    glfwShowWindow(window);
  }

  private void loop() {
    // This line is critical for LWJGL's interoperation with GLFW's
    // OpenGL context, or any context that is managed externally.
    // LWJGL detects the context that is current in the current thread,
    // creates the GLCapabilities instance and makes the OpenGL
    // bindings available for use.
    GL.createCapabilities();

    // Set the clear color
    glClearColor(1.0f, 0.0f, 0.0f, 0.0f);

    // Run the rendering loop until the user has attempted to close
    // the window or has pressed the ESCAPE key.
    while ( !glfwWindowShouldClose(window) ) {
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer

      glfwSwapBuffers(window); // swap the color buffers

      // Poll for window events. The key callback above will only be
      // invoked during this call.
      glfwPollEvents();
    }
  }

  public static void main(String[] args) {
    new HelloWorld().run();
  }

}

Releasing ESCAPE terminates the process.

Answer the question

In order to leave comments, you need to log in

5 answer(s)
H
hint000, 2021-12-11
@General-purpose

How does he, for example, know if a button is pressed? To do this, you need to cycle as often as possible.
How do you know in the morning to wake up and go to work or school? To do this, you need to look at the clock as often as possible all night. :)
Or you can just "tell" the alarm clock (or relatives) to wake up at the right time. This is how the program trusts the operating system to wake it up when someone presses the button. In the meantime, no one clicked, the program sleeps and does not waste resources.
The operating system in any case knows about all button presses and all mouse movements, it decides which program to transfer these presses or movements, i.e. which program to wake up now. As soon as the program handles the event, it will sleep again if there is nothing else to handle.

V
Vasily Bannikov, 2021-12-11
@vabka

Well, remove this empty loop.
From the point of view of a computer, an empty cycle is also a cycle, and it must be carried out responsibly.

This is bad, ugly, wrong.

This is a given.
If you tell me why you need an empty cycle - mb someone will tell you how to fix it.

A
AlexVWill, 2021-12-11
@AlexVWill

What is the program here? JAVA is an interpreted language, cross-platform, and it uses a virtual machine, so it loads the processor when it executes the program, and not the program itself. In addition to the program itself, a bunch of libraries are loaded there, like I / O, working with memory, and a bunch of everything. Unlike a vinyl calculator, which is most likely written in C ++ and compiled for a specific OS type of processor.

S
SagePtr, 2021-12-11
@SagePtr

The simplest option is to sleep for a few milliseconds at the end of each iteration of the loop if the program has nothing to do. Or wait until some event occurs (for example, if you have a socket waiting for incoming connections).

A
Anton Shamanov, 2021-12-11
@SilenceOfWinter

read about code profiling, I remember idea / eclipse had a built-in profiler

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question