useHardwareConcurrency
Get the number of logical CPU cores to auto-scale thread pools or lower graphics settings for low-end devices.
Installation
npx shadcn@latest add https://r.fiberui.com/r/hooks/use-hardware-concurrency.jsonA React hook that returns the number of logical processors available to run threads on the user's computer. This is useful for scaling worker pools, deciding on graphics fidelity, or adjusting application workload based on device capabilities.
Fallback Value
Returns 1 if the navigator.hardwareConcurrency property is not supported
by the browser or during Server-Side Rendering (SSR).
Features
- Device Scaling - Adjust your app's performance based on available cores
- Type Safe - Fully typed for TypeScript
- SSR Safe - Returns a safe fallback during server-side rendering
Basic Usage
Logical Cores Detected
Logical Cores Detected
Your device's processing capacity
"use client";
import { useHardwareConcurrency } from "@repo/hooks/performance/use-hardware-concurrency";
import { Card } from "@repo/ui/components/card";
import { Cpu } from "lucide-react";
export function Example1() {
const cores = useHardwareConcurrency();
return (
<Card className="mx-auto flex max-w-sm flex-col items-center justify-center gap-4 p-8">
<div className="bg-primary/10 text-primary flex items-center justify-center rounded-full p-4">
<Cpu className="h-12 w-12" />
</div>
<div className="text-center">
<h3 className="text-xl font-bold">Logical Cores Detected</h3>
<p className="text-muted-foreground mt-1 text-sm">
Your device's processing capacity
</p>
</div>
<div className="text-primary text-6xl font-black tabular-nums tracking-tighter">
{cores}
</div>
</Card>
);
}
Auto-Tuning Quality
Auto-Tuning Quality
Device features adjusted based on 1 logical core.
"use client";
import { useHardwareConcurrency } from "@repo/hooks/performance/use-hardware-concurrency";
import { useState, useEffect } from "react";
import { Card } from "@repo/ui/components/card";
const Progress = ({
value,
className,
}: {
value: number;
className: string;
}) => (
<div className={`bg-secondary overflow-hidden rounded-full ${className}`}>
<div
className="bg-primary h-full transition-all duration-300"
style={{ width: `${value}%` }}
/>
</div>
);
export function Example2() {
const cores = useHardwareConcurrency();
const [quality, setQuality] = useState("");
const [details, setDetails] = useState("");
useEffect(() => {
// Automatically determine graphics or app feature quality based on cores
if (cores >= 8) {
setQuality("High");
setDetails(
"All animations, high-res textures, and background processing enabled.",
);
} else if (cores >= 4) {
setQuality("Medium");
setDetails(
"Standard animations, optimized textures, balanced processing.",
);
} else {
setQuality("Low");
setDetails(
"Reduced animations, low-res textures, strictly essential processing.",
);
}
}, [cores]);
return (
<div className="mx-auto flex w-full max-w-md flex-col gap-6">
<div className="text-center">
<h3 className="text-lg font-medium">Auto-Tuning Quality</h3>
<p className="text-muted-foreground text-sm">
Device features adjusted based on {cores} logical{" "}
{cores === 1 ? "core" : "cores"}.
</p>
</div>
<Card className="flex flex-col gap-4 p-6">
<div className="flex items-center justify-between">
<span className="font-medium">Applied Setting:</span>
<span
className={`rounded-md px-2 py-1 text-sm font-bold ${
quality === "High"
? "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400"
: quality === "Medium"
? "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400"
: "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400"
}`}
>
{quality} Quality
</span>
</div>
<div className="space-y-4">
<div className="space-y-1">
<div className="flex justify-between text-sm">
<span>Texture Resolution</span>
<span>
{quality === "Low"
? "512px"
: quality === "Medium"
? "1024px"
: "4096px"}
</span>
</div>
<Progress
value={
quality === "Low"
? 33
: quality === "Medium"
? 66
: 100
}
className="h-2"
/>
</div>
<div className="space-y-1">
<div className="flex justify-between text-sm">
<span>Background Tasks</span>
<span>
{quality === "Low"
? "1 Thread"
: quality === "Medium"
? "2 Threads"
: "4 Threads"}
</span>
</div>
<Progress
value={
quality === "Low"
? 25
: quality === "Medium"
? 50
: 100
}
className="h-2"
/>
</div>
</div>
<p className="text-muted-foreground mt-2 border-t pt-4 text-xs">
{details}
</p>
</Card>
</div>
);
}
Auto-Scaled Thread Pool
Auto-Scaled Thread Pool
Simulating a background worker pool scaled to max 1 background threads.
"use client";
import { useHardwareConcurrency } from "@repo/hooks/performance/use-hardware-concurrency";
import { useState, useEffect } from "react";
import { Button } from "@repo/ui/components/button";
import { Loader2 } from "lucide-react";
export function Example3() {
const cores = useHardwareConcurrency();
const [workers, setWorkers] = useState<{ id: number; status: string }[]>(
[],
);
const [isSimulating, setIsSimulating] = useState(false);
useEffect(() => {
// Initialize pool based on available cores (leaving 1 for main thread if possible)
const poolSize = Math.max(1, cores - 1);
const initialPool = Array.from({ length: poolSize }).map((_, i) => ({
id: i + 1,
status: "Idle",
}));
setWorkers(initialPool);
}, [cores]);
const simulateWork = () => {
setIsSimulating(true);
// Randomly assign work to the available scaled threads
const updatedWorkers = workers.map((w) => ({
...w,
status: "Working...",
}));
setWorkers(updatedWorkers);
// Simulate finishing work at random times
updatedWorkers.forEach((w) => {
setTimeout(
() => {
setWorkers((current) =>
current.map((cw) =>
cw.id === w.id ? { ...cw, status: "Done" } : cw,
),
);
},
1000 + Math.random() * 2000,
);
});
// Reset overall simulation state
setTimeout(() => setIsSimulating(false), 3500);
};
return (
<div className="mx-auto flex w-full max-w-lg flex-col gap-6">
<div className="text-center">
<h3 className="text-lg font-medium">Auto-Scaled Thread Pool</h3>
<p className="text-muted-foreground text-sm">
Simulating a background worker pool scaled to max{" "}
{Math.max(1, cores - 1)} background threads.
</p>
</div>
<div className="grid grid-cols-2 gap-3 sm:grid-cols-3">
{workers.map((worker) => (
<div
key={worker.id}
className={`flex flex-col items-center justify-center rounded-xl border p-3 text-sm transition-all duration-500 ${
worker.status === "Working..."
? "border-primary/50 bg-primary/10 text-primary"
: worker.status === "Done"
? "border-green-500/50 bg-green-500/10 text-green-600 dark:text-green-400"
: "border-zinc-200 bg-zinc-50 dark:border-zinc-800 dark:bg-zinc-900/50"
}`}
>
<span className="mb-1 font-bold">
Worker {worker.id}
</span>
<div className="flex items-center gap-2">
{worker.status === "Working..." && (
<Loader2 className="h-3 w-3 animate-spin" />
)}
<span className="text-xs">{worker.status}</span>
</div>
</div>
))}
</div>
<Button
onClick={simulateWork}
isDisabled={isSimulating}
className="w-full self-center sm:w-auto"
>
{isSimulating
? "Processing Dataset..."
: "Start Heavy Processing"}
</Button>
</div>
);
}
Dynamic Layout Scaling
Dynamic Layout Scaling
Rendering complexity (6 nodes across 2 columns) adjusted for 1 cores.
"use client";
import { useHardwareConcurrency } from "@repo/hooks/performance/use-hardware-concurrency";
import { Card } from "@repo/ui/components/card";
export function Example4() {
const cores = useHardwareConcurrency();
// Determine grid columns dynamically based on cores
const columns = cores >= 16 ? 8 : cores >= 8 ? 6 : cores >= 4 ? 4 : 2;
// Generate items based on dynamic columns
const items = Array.from({ length: columns * 3 });
return (
<div className="mx-auto flex w-full max-w-2xl flex-col gap-6">
<div className="text-center">
<h3 className="text-lg font-medium">Dynamic Layout Scaling</h3>
<p className="text-muted-foreground text-sm">
Rendering complexity ({items.length} nodes across {columns}{" "}
columns) adjusted for {cores} cores.
</p>
</div>
<div
className="grid gap-2"
style={{
gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,
}}
>
{items.map((_, i) => (
<Card
key={i}
className="flex aspect-square flex-col items-center justify-center bg-zinc-50 p-2 text-xs transition-colors hover:bg-zinc-100 dark:bg-zinc-900/50 dark:hover:bg-zinc-800"
>
<span className="font-mono opacity-50">Node</span>
<span className="font-bold">{i + 1}</span>
</Card>
))}
</div>
<div className="text-muted-foreground bg-muted/50 rounded-lg p-4 text-center text-xs">
Devices with fewer cores will render a smaller, simpler grid
structure to maintain 60 FPS, while powerful workstations will
render denser data visualization.
</div>
</div>
);
}
API Reference
Hook Signature
function useHardwareConcurrency(): number;Return Value
Returns a number representing the number of logical CPU cores available on the user's device (e.g., 4, 8, 16).
Hook Source Code
import { useState, useEffect } from "react";
/**
* Get the number of logical CPU cores (navigator.hardwareConcurrency).
* Useful for auto-scaling thread pools or adjusting graphics settings.
* Returns a fallback of 1 if not supported or during SSR.
*/
export function useHardwareConcurrency() {
const [concurrency, setConcurrency] = useState<number>(1);
useEffect(() => {
if (
typeof navigator !== "undefined" &&
"hardwareConcurrency" in navigator
) {
setConcurrency(navigator.hardwareConcurrency);
}
}, []);
return concurrency;
}