abt
abt

Reputation: 11

How to set priority of a process(that gets inherited by OS threads) in golang for mac?

How to set priority of a process(that gets inherited by OS threads) in golang for mac? syscall.SetPriority with syscall.PRGRP flag sets priority of a process and gets inherited by threads on ubuntu. Is there a similar way for mac? How can we access apple qos from golang?

Program worked on ubuntu but didn't work on mac

package main

import (
    "fmt"
    "os"
    "runtime"
    "sync"
    "syscall"
    "time"
)

func main() {
    // runtime.GOMAXPROCS(5)
    // Get the current process ID
    pid := os.Getpid()
    fmt.Printf("Current Process ID: %d\n", pid)

    // Set process priority to the lowest
    setProcessPriority(pid, syscall.PRIO_PGRP, 10)

    // Number of goroutines to spawn
    numGoroutines := 100

    // Use a wait group to wait for all goroutines to finish
    var wg sync.WaitGroup
    wg.Add(numGoroutines)
    start := time.Now()
    // Spawn goroutines
    for i := 0; i < numGoroutines; i++ {
        go func(id int) {
            defer wg.Done()
            fmt.Printf("Goroutine %d started.\n", id)
            cpuIntensiveWork()
            fmt.Printf("Goroutine %d completed.\n", id)
        }(i)
    }

    // Wait for all goroutines to finish
    wg.Wait()
    elapsed := time.Since(start)
    fmt.Printf("All goroutines completed in %f\n.", elapsed.Seconds())
}

func setProcessPriority(pid int, which int, priority int) {
    if runtime.GOOS == "windows" {
        fmt.Println("Setting process priority is not supported on Windows.")
        return
    }

    // Set process priority for Unix-like systems
    err := syscall.Setpriority(which, pid, priority)
    if err != nil {
        fmt.Println("Error setting process priority:", err)
    }
}

    func cpuIntensiveWork() {
        // Simulate CPU-intensive work
        for i := 0; i < 100000; i++ {
            for j := 0; j < 10000; j++ {
                _ = j * j
            }
            _ = i * i
        }
    }

Upvotes: 1

Views: 309

Answers (1)

Kurtis Rader
Kurtis Rader

Reputation: 7469

Your program fails for me on Linux and macOS. The problem is your use of syscall.PRIO_PGRP where you should be using syscall.PRIO_PROCESS. I simplified your program to the following and it works as expected on Linux and macOS.

package main

import (
    "fmt"
    "os"
    "syscall"
)

func main() {
    pid := os.Getpid()
    fmt.Printf("Current Process ID: %d\n", pid)

    prio, err := syscall.Getpriority(syscall.PRIO_PROCESS, pid)
    if err != nil {
        fmt.Println("Error getting process priority:", err)
    }
    fmt.Println("Original priority:", prio)
    if err := syscall.Setpriority(syscall.PRIO_PROCESS, pid, 10); err != nil {
        fmt.Println("Error setting process priority:", err)
    }
    prio, err = syscall.Getpriority(syscall.PRIO_PROCESS, pid)
    if err != nil {
        fmt.Println("Error getting process priority:", err)
    }
    fmt.Println("New priority:", prio)
}

On macOS:

$ go run x.go
Current Process ID: 27436
Original priority: 0
New priority: 10

On Linux:

$ go run x.go
Current Process ID: 117032
Original priority: 20
New priority: 10

If you change the syscall.PRIO_PROCESS to syscall.PRIO_PGRP you'll see errors like the following on both platforms:

Current Process ID: 113604
Error getting process priority: no such process
Original priority: -1
Error setting process priority: no such process
Error getting process priority: no such process
New priority: -1

Upvotes: 0

Related Questions