Standard library · System and tools

os/platform

Identifying the system the program is running on: the operating system, the processor, the core count and the memory.

import os.platform

The os.platform package says at run time what system the program is on: the operating system, the processor family, the number of cores and the amount of memory. Use it for reports and logs, for automatic settings such as a worker count or a cache size, and for small per-system differences such as a file extension. For code that only compiles on one system, use the constants such as SALAM_OS_WINDOWS and conditional compilation instead. For the user and their home folder see os.user; for environment variables, env.

The Is... functions, OS and Arch are fixed when the program is compiled, so they cost nothing to call. The hardware questions are asked of the running system, and how they are answered differs:

FunctionLinuxmacOS and BSDWindows
CpuCountsysconf, instantruns sysctlthe NUMBER_OF_PROCESSORS variable
TotalMemory/proc/meminforuns sysctlruns PowerShell, often a second or more
AvailableMemory/proc/meminfonot known, -1runs PowerShell

What people get wrong: calling the memory functions in a loop (on Windows each call starts PowerShell, so ask once and keep the number), forgetting that every hardware function returns -1 when it cannot find out, and treating CpuCount as physical cores. It counts the logical processors online, hyper-threads included, and inside a container it counts the whole machine.

The programs below print whether a rule held rather than the raw numbers, so their output is the same on any machine.

Choose how many workers to run

Work that splits into independent pieces, such as resizing images, goes faster with one thread or process per core. CpuCount gives the number of cores; keep the result between one and a limit of your own, because a machine with 128 cores does not mean your job wants 128 threads.

os-platform-guide-workers.salam
import os.platform

func worker_count(limit: int): int:
    cores := platform.CpuCount()
    if cores < 1:
        ret 1
    end
    if cores > limit:
        ret limit
    end
    ret cores
end

func main:
    workers := worker_count(8)
    println "workers between 1 and 8:", workers >= 1 and workers <= 8
    println "never more than the cores:", workers <= platform.CpuCount()
    one := worker_count(1)
    println "with a limit of one:", one
end
Outputworkers between 1 and 8: true never more than the cores: true with a limit of one: 1

Inside a container the count is the whole machine's, not the share the container may use. If the program runs under Docker or Kubernetes, let a flag or an environment variable override it.

Size a cache from the system memory

TotalMemory and AvailableMemory return bytes as an i64. A cache can take a fraction of the total memory, kept between a floor and a ceiling, and never more than half of what is free right now. AvailableMemory returns minus one on systems where it is not known, so check for that before using it.

os-platform-guide-memory.salam
import os.platform

const MB := 1048576 as i64

func cache_bytes(): i64:
    mut size := platform.TotalMemory() / 16
    if size < 64 * MB:
        size = 64 * MB
    end
    if size > 1024 * MB:
        size = 1024 * MB
    end
    free := platform.AvailableMemory()
    if free > 0 and size > free / 2:
        size = free / 2
    end
    ret size
end

func main:
    size := cache_bytes()
    println "cache is at most 1 GB:", size <= 1024 * MB
    println "cache is positive:", size > 0
    free := platform.AvailableMemory()
    println "cache fits in free memory:", free < 0 or size <= free
end
Outputcache is at most 1 GB: true cache is positive: true cache fits in free memory: true

Small differences between systems

Most differences between systems are small: Windows programs end in .exe, and each desktop opens a file with a different command. A function that asks IsWindows or IsMac and returns the right piece keeps the rest of the program free of such checks.

os-platform-guide-dispatch.salam
import os.platform

func executable(name: str): str:
    if platform.IsWindows():
        ret name + ".exe"
    end
    ret name
end

func open_command(): str:
    if platform.IsWindows(): ret "start" end
    if platform.IsMac(): ret "open" end
    ret "xdg-open"
end

func main:
    mut matched := 0
    if platform.IsLinux(): matched += 1 end
    if platform.IsWindows(): matched += 1 end
    if platform.IsMac(): matched += 1 end
    if platform.IsFreeBSD(): matched += 1 end
    if platform.IsWasm(): matched += 1 end
    println "at most one system matched:", matched <= 1
    println "binary name built:", executable("salam").starts_with("salam")
    println "open command chosen:", open_command().len() > 0
end
Outputat most one system matched: true binary name built: true open command chosen: true

Run time or compile time

The functions of this package are answered when the program runs, so both branches of an if are compiled on every system. That fails when one branch calls a function that only exists on one system, such as a Windows API. Then use the constant itself: a plain if SALAM_OS_WINDOWS: is decided while compiling and the other branch is left out. See compile-time code for the full list of constants.

os-platform-guide-compile.salam
import os.platform

func linux_when_compiled(): bool:
    if SALAM_OS_LINUX:
        ret true
    else:
        ret false
    end
end

func main:
    println "compile time and run time agree:", linux_when_compiled() == platform.IsLinux()
    if SALAM_OS_WINDOWS:
        println "this line is only compiled on Windows"
    else:
        println "this line is compiled everywhere else"
    end
end
Outputcompile time and run time agree: true this line is compiled everywhere else
NeedUse
Show the system in a report or a logOS, Arch
Pick a value that differs by systemIsWindows, IsMac, IsLinux
Call code that only compiles on one systemif SALAM_OS_WINDOWS: and the other constants
Decide how much work to do at onceCpuCount
Decide how much memory to useTotalMemory, AvailableMemory

Functions

IsLinux

func IsLinux(): bool
True on Linux.
os-platform-OS.salam
import os.platform

func main:
    known := platform.IsLinux() or platform.IsWindows() or platform.IsMac() or platform.IsFreeBSD() or platform.IsBSD() or platform.IsAndroid() or platform.IsWasm()
    println known, platform.OS().len() > 0
    arch := platform.IsX64() or platform.IsArm64() or platform.IsX86() or platform.IsArm()
    println arch, platform.Arch().len() > 0
    println platform.CpuCount() >= 1
    println platform.TotalMemory() > 0, platform.AvailableMemory() <= platform.TotalMemory()
end
Outputtrue true true true true true true

IsWindows

func IsWindows(): bool
True on Windows.

The example for this item is shown with the ones above: os-platform-OS.salam

IsMac

func IsMac(): bool
True on macOS.

The example for this item is shown with the ones above: os-platform-OS.salam

IsBSD

func IsBSD(): bool
True on the BSD family.

The example for this item is shown with the ones above: os-platform-OS.salam

IsFreeBSD

func IsFreeBSD(): bool
True on FreeBSD.

The example for this item is shown with the ones above: os-platform-OS.salam

IsAndroid

func IsAndroid(): bool
True on Android.

The example for this item is shown with the ones above: os-platform-OS.salam

IsWasm

func IsWasm(): bool
True when the program was compiled to WebAssembly.

The example for this item is shown with the ones above: os-platform-OS.salam

OS

func OS(): str
The name of the operating system: linux, mac, windows, freebsd, android, wasm or unknown. Fixed at compile time.

The example for this item is shown with the ones above: os-platform-OS.salam

IsX64

func IsX64(): bool
True on a 64-bit Intel or AMD processor.

The example for this item is shown with the ones above: os-platform-OS.salam

IsArm64

func IsArm64(): bool
True on a 64-bit ARM processor, such as Apple silicon.

The example for this item is shown with the ones above: os-platform-OS.salam

IsX86

func IsX86(): bool
True on a 32-bit Intel processor.

The example for this item is shown with the ones above: os-platform-OS.salam

IsArm

func IsArm(): bool
True on a 32-bit ARM processor.

The example for this item is shown with the ones above: os-platform-OS.salam

Arch

func Arch(): str
The name of the processor architecture: x64, arm64, x86, arm, wasm or unknown.

The example for this item is shown with the ones above: os-platform-OS.salam

CpuCount

func CpuCount(): int
The number of logical processors online (hyper-threads count), for deciding how many things to do at once; -1 when it cannot be found. In a container it is the whole machine's count.

The example for this item is shown with the ones above: os-platform-OS.salam

TotalMemory

func TotalMemory(): i64
The system's total memory in bytes, or -1 when unknown. On Windows each call runs PowerShell, so call it once.

The example for this item is shown with the ones above: os-platform-OS.salam

AvailableMemory

func AvailableMemory(): i64
The memory available to new programs in bytes (MemAvailable on Linux). Supported on Linux and Windows only; elsewhere it returns minus one. On Windows each call runs PowerShell.

The example for this item is shown with the ones above: os-platform-OS.salam