Returns the number of physical or logical CPU cores in the system.
Function Signatures
func Counts(logical bool) (int, error)
func CountsWithContext(ctx context.Context, logical bool) (int, error)
Parameters
If true, returns the number of logical CPUs (including hyperthreading). If false, returns the number of physical CPU cores.
Context for cancellation and timeout control (WithContext variant only).
Return Value
The number of CPU cores. Returns the logical count if logical is true, physical count if false.
Error if the CPU count could not be determined, nil on success.
Examples
Get Logical and Physical Core Counts
package main
import (
"fmt"
"github.com/shirou/gopsutil/v4/cpu"
)
func main() {
logical, err := cpu.Counts(true)
if err != nil {
panic(err)
}
physical, err := cpu.Counts(false)
if err != nil {
panic(err)
}
fmt.Printf("Logical CPUs: %d\n", logical)
fmt.Printf("Physical CPUs: %d\n", physical)
if logical > physical {
fmt.Printf("Hyperthreading: enabled (%d threads per core)\n",
logical/physical)
} else {
fmt.Println("Hyperthreading: disabled or not supported")
}
}
Check CPU Resources
package main
import (
"fmt"
"runtime"
"github.com/shirou/gopsutil/v4/cpu"
)
func main() {
logical, _ := cpu.Counts(true)
gomaxprocs := runtime.GOMAXPROCS(0)
fmt.Printf("Available CPUs: %d\n", logical)
fmt.Printf("GOMAXPROCS: %d\n", gomaxprocs)
if gomaxprocs < logical {
fmt.Println("Warning: Go is not using all available CPUs")
}
}
Using Context with Timeout
package main
import (
"context"
"fmt"
"time"
"github.com/shirou/gopsutil/v4/cpu"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
count, err := cpu.CountsWithContext(ctx, true)
if err != nil {
if ctx.Err() == context.DeadlineExceeded {
fmt.Println("Operation timed out")
} else {
panic(err)
}
return
}
fmt.Printf("CPU count: %d\n", count)
}
Calculate Optimal Worker Pool Size
package main
import (
"fmt"
"github.com/shirou/gopsutil/v4/cpu"
)
func main() {
logical, err := cpu.Counts(true)
if err != nil {
panic(err)
}
// Common pattern: use 2x CPU count for I/O-bound tasks
ioWorkers := logical * 2
fmt.Printf("Recommended I/O workers: %d\n", ioWorkers)
// Use CPU count for CPU-bound tasks
cpuWorkers := logical
fmt.Printf("Recommended CPU workers: %d\n", cpuWorkers)
}
Compare with runtime.NumCPU
package main
import (
"fmt"
"runtime"
"github.com/shirou/gopsutil/v4/cpu"
)
func main() {
gopsutilCount, _ := cpu.Counts(true)
runtimeCount := runtime.NumCPU()
fmt.Printf("gopsutil logical CPUs: %d\n", gopsutilCount)
fmt.Printf("runtime.NumCPU(): %d\n", runtimeCount)
// These should typically be the same
if gopsutilCount == runtimeCount {
fmt.Println("Counts match")
} else {
fmt.Println("Warning: Counts differ")
}
}
package main
import (
"fmt"
"github.com/shirou/gopsutil/v4/cpu"
)
func main() {
logical, err := cpu.Counts(true)
if err != nil {
panic(err)
}
physical, err := cpu.Counts(false)
if err != nil {
panic(err)
}
info, err := cpu.Info()
if err != nil {
panic(err)
}
fmt.Println("=== CPU Information ===")
if len(info) > 0 {
fmt.Printf("Model: %s\n", info[0].ModelName)
fmt.Printf("Vendor: %s\n", info[0].VendorID)
}
fmt.Printf("Physical Cores: %d\n", physical)
fmt.Printf("Logical Cores: %d\n", logical)
fmt.Printf("Threads per Core: %d\n", logical/physical)
}
Notes
- The
Counts() function is a convenience wrapper that calls CountsWithContext() with context.Background()
- Logical count includes hyperthreading/SMT threads
- On Intel CPUs with hyperthreading: logical = physical × 2
- On AMD CPUs with SMT: logical = physical × 2
- On CPUs without hyperthreading: logical = physical
- The logical count is equivalent to
runtime.NumCPU() in Go
- Physical count represents actual CPU cores, not including hyperthreading
- On some platforms (Plan 9, older systems), both logical and physical may return the same value
- This is useful for determining optimal parallelism for CPU-bound tasks