+1
.gitignore
+1
.gitignore
···
1
+
/target
+331
Cargo.lock
+331
Cargo.lock
···
1
+
# This file is automatically @generated by Cargo.
2
+
# It is not intended for manual editing.
3
+
version = 4
4
+
5
+
[[package]]
6
+
name = "anstream"
7
+
version = "0.6.21"
8
+
source = "registry+https://github.com/rust-lang/crates.io-index"
9
+
checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
10
+
dependencies = [
11
+
"anstyle",
12
+
"anstyle-parse",
13
+
"anstyle-query",
14
+
"anstyle-wincon",
15
+
"colorchoice",
16
+
"is_terminal_polyfill",
17
+
"utf8parse",
18
+
]
19
+
20
+
[[package]]
21
+
name = "anstyle"
22
+
version = "1.0.13"
23
+
source = "registry+https://github.com/rust-lang/crates.io-index"
24
+
checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
25
+
26
+
[[package]]
27
+
name = "anstyle-parse"
28
+
version = "0.2.7"
29
+
source = "registry+https://github.com/rust-lang/crates.io-index"
30
+
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
31
+
dependencies = [
32
+
"utf8parse",
33
+
]
34
+
35
+
[[package]]
36
+
name = "anstyle-query"
37
+
version = "1.1.4"
38
+
source = "registry+https://github.com/rust-lang/crates.io-index"
39
+
checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2"
40
+
dependencies = [
41
+
"windows-sys 0.60.2",
42
+
]
43
+
44
+
[[package]]
45
+
name = "anstyle-wincon"
46
+
version = "3.0.10"
47
+
source = "registry+https://github.com/rust-lang/crates.io-index"
48
+
checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a"
49
+
dependencies = [
50
+
"anstyle",
51
+
"once_cell_polyfill",
52
+
"windows-sys 0.60.2",
53
+
]
54
+
55
+
[[package]]
56
+
name = "bitflags"
57
+
version = "2.9.4"
58
+
source = "registry+https://github.com/rust-lang/crates.io-index"
59
+
checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"
60
+
61
+
[[package]]
62
+
name = "cfg-if"
63
+
version = "1.0.3"
64
+
source = "registry+https://github.com/rust-lang/crates.io-index"
65
+
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
66
+
67
+
[[package]]
68
+
name = "cfg_aliases"
69
+
version = "0.2.1"
70
+
source = "registry+https://github.com/rust-lang/crates.io-index"
71
+
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
72
+
73
+
[[package]]
74
+
name = "clap"
75
+
version = "4.5.48"
76
+
source = "registry+https://github.com/rust-lang/crates.io-index"
77
+
checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae"
78
+
dependencies = [
79
+
"clap_builder",
80
+
"clap_derive",
81
+
]
82
+
83
+
[[package]]
84
+
name = "clap_builder"
85
+
version = "4.5.48"
86
+
source = "registry+https://github.com/rust-lang/crates.io-index"
87
+
checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9"
88
+
dependencies = [
89
+
"anstream",
90
+
"anstyle",
91
+
"clap_lex",
92
+
"strsim",
93
+
]
94
+
95
+
[[package]]
96
+
name = "clap_derive"
97
+
version = "4.5.47"
98
+
source = "registry+https://github.com/rust-lang/crates.io-index"
99
+
checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c"
100
+
dependencies = [
101
+
"heck",
102
+
"proc-macro2",
103
+
"quote",
104
+
"syn",
105
+
]
106
+
107
+
[[package]]
108
+
name = "clap_lex"
109
+
version = "0.7.5"
110
+
source = "registry+https://github.com/rust-lang/crates.io-index"
111
+
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
112
+
113
+
[[package]]
114
+
name = "colorchoice"
115
+
version = "1.0.4"
116
+
source = "registry+https://github.com/rust-lang/crates.io-index"
117
+
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
118
+
119
+
[[package]]
120
+
name = "ctrlc"
121
+
version = "3.5.0"
122
+
source = "registry+https://github.com/rust-lang/crates.io-index"
123
+
checksum = "881c5d0a13b2f1498e2306e82cbada78390e152d4b1378fb28a84f4dcd0dc4f3"
124
+
dependencies = [
125
+
"dispatch",
126
+
"nix",
127
+
"windows-sys 0.61.2",
128
+
]
129
+
130
+
[[package]]
131
+
name = "dispatch"
132
+
version = "0.2.0"
133
+
source = "registry+https://github.com/rust-lang/crates.io-index"
134
+
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
135
+
136
+
[[package]]
137
+
name = "heater"
138
+
version = "0.1.0"
139
+
dependencies = [
140
+
"clap",
141
+
"ctrlc",
142
+
"num_cpus",
143
+
]
144
+
145
+
[[package]]
146
+
name = "heck"
147
+
version = "0.5.0"
148
+
source = "registry+https://github.com/rust-lang/crates.io-index"
149
+
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
150
+
151
+
[[package]]
152
+
name = "hermit-abi"
153
+
version = "0.5.2"
154
+
source = "registry+https://github.com/rust-lang/crates.io-index"
155
+
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
156
+
157
+
[[package]]
158
+
name = "is_terminal_polyfill"
159
+
version = "1.70.1"
160
+
source = "registry+https://github.com/rust-lang/crates.io-index"
161
+
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
162
+
163
+
[[package]]
164
+
name = "libc"
165
+
version = "0.2.177"
166
+
source = "registry+https://github.com/rust-lang/crates.io-index"
167
+
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
168
+
169
+
[[package]]
170
+
name = "nix"
171
+
version = "0.30.1"
172
+
source = "registry+https://github.com/rust-lang/crates.io-index"
173
+
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
174
+
dependencies = [
175
+
"bitflags",
176
+
"cfg-if",
177
+
"cfg_aliases",
178
+
"libc",
179
+
]
180
+
181
+
[[package]]
182
+
name = "num_cpus"
183
+
version = "1.17.0"
184
+
source = "registry+https://github.com/rust-lang/crates.io-index"
185
+
checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b"
186
+
dependencies = [
187
+
"hermit-abi",
188
+
"libc",
189
+
]
190
+
191
+
[[package]]
192
+
name = "once_cell_polyfill"
193
+
version = "1.70.1"
194
+
source = "registry+https://github.com/rust-lang/crates.io-index"
195
+
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
196
+
197
+
[[package]]
198
+
name = "proc-macro2"
199
+
version = "1.0.101"
200
+
source = "registry+https://github.com/rust-lang/crates.io-index"
201
+
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
202
+
dependencies = [
203
+
"unicode-ident",
204
+
]
205
+
206
+
[[package]]
207
+
name = "quote"
208
+
version = "1.0.41"
209
+
source = "registry+https://github.com/rust-lang/crates.io-index"
210
+
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
211
+
dependencies = [
212
+
"proc-macro2",
213
+
]
214
+
215
+
[[package]]
216
+
name = "strsim"
217
+
version = "0.11.1"
218
+
source = "registry+https://github.com/rust-lang/crates.io-index"
219
+
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
220
+
221
+
[[package]]
222
+
name = "syn"
223
+
version = "2.0.106"
224
+
source = "registry+https://github.com/rust-lang/crates.io-index"
225
+
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
226
+
dependencies = [
227
+
"proc-macro2",
228
+
"quote",
229
+
"unicode-ident",
230
+
]
231
+
232
+
[[package]]
233
+
name = "unicode-ident"
234
+
version = "1.0.19"
235
+
source = "registry+https://github.com/rust-lang/crates.io-index"
236
+
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
237
+
238
+
[[package]]
239
+
name = "utf8parse"
240
+
version = "0.2.2"
241
+
source = "registry+https://github.com/rust-lang/crates.io-index"
242
+
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
243
+
244
+
[[package]]
245
+
name = "windows-link"
246
+
version = "0.2.1"
247
+
source = "registry+https://github.com/rust-lang/crates.io-index"
248
+
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
249
+
250
+
[[package]]
251
+
name = "windows-sys"
252
+
version = "0.60.2"
253
+
source = "registry+https://github.com/rust-lang/crates.io-index"
254
+
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
255
+
dependencies = [
256
+
"windows-targets",
257
+
]
258
+
259
+
[[package]]
260
+
name = "windows-sys"
261
+
version = "0.61.2"
262
+
source = "registry+https://github.com/rust-lang/crates.io-index"
263
+
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
264
+
dependencies = [
265
+
"windows-link",
266
+
]
267
+
268
+
[[package]]
269
+
name = "windows-targets"
270
+
version = "0.53.5"
271
+
source = "registry+https://github.com/rust-lang/crates.io-index"
272
+
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
273
+
dependencies = [
274
+
"windows-link",
275
+
"windows_aarch64_gnullvm",
276
+
"windows_aarch64_msvc",
277
+
"windows_i686_gnu",
278
+
"windows_i686_gnullvm",
279
+
"windows_i686_msvc",
280
+
"windows_x86_64_gnu",
281
+
"windows_x86_64_gnullvm",
282
+
"windows_x86_64_msvc",
283
+
]
284
+
285
+
[[package]]
286
+
name = "windows_aarch64_gnullvm"
287
+
version = "0.53.1"
288
+
source = "registry+https://github.com/rust-lang/crates.io-index"
289
+
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
290
+
291
+
[[package]]
292
+
name = "windows_aarch64_msvc"
293
+
version = "0.53.1"
294
+
source = "registry+https://github.com/rust-lang/crates.io-index"
295
+
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
296
+
297
+
[[package]]
298
+
name = "windows_i686_gnu"
299
+
version = "0.53.1"
300
+
source = "registry+https://github.com/rust-lang/crates.io-index"
301
+
checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
302
+
303
+
[[package]]
304
+
name = "windows_i686_gnullvm"
305
+
version = "0.53.1"
306
+
source = "registry+https://github.com/rust-lang/crates.io-index"
307
+
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
308
+
309
+
[[package]]
310
+
name = "windows_i686_msvc"
311
+
version = "0.53.1"
312
+
source = "registry+https://github.com/rust-lang/crates.io-index"
313
+
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
314
+
315
+
[[package]]
316
+
name = "windows_x86_64_gnu"
317
+
version = "0.53.1"
318
+
source = "registry+https://github.com/rust-lang/crates.io-index"
319
+
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
320
+
321
+
[[package]]
322
+
name = "windows_x86_64_gnullvm"
323
+
version = "0.53.1"
324
+
source = "registry+https://github.com/rust-lang/crates.io-index"
325
+
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
326
+
327
+
[[package]]
328
+
name = "windows_x86_64_msvc"
329
+
version = "0.53.1"
330
+
source = "registry+https://github.com/rust-lang/crates.io-index"
331
+
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
+9
Cargo.toml
+9
Cargo.toml
+48
README.md
+48
README.md
···
1
+
# Heater
2
+
3
+
A Rust command-line application that churns your CPU cores at maximum capacity so your laptop isn't cold
4
+
5
+
## Build
6
+
7
+
```bash
8
+
cargo build --release
9
+
```
10
+
11
+
The compiled binary will be at `target/release/heater`.
12
+
13
+
## Usage
14
+
15
+
### Run indefinitely (until Ctrl+C)
16
+
```bash
17
+
cargo run --release
18
+
# or
19
+
./target/release/heater
20
+
```
21
+
22
+
### Run for a specific duration (in seconds)
23
+
```bash
24
+
cargo run --release -- --duration 30
25
+
# or
26
+
./target/release/heater --duration 30
27
+
```
28
+
29
+
### Customize the number of free cores
30
+
```bash
31
+
# Leave 2 cores free
32
+
cargo run --release -- --free-cores 2
33
+
34
+
# Use ALL cores (leave 0 free)
35
+
cargo run --release -- --free-cores 0
36
+
37
+
# Run for 60 seconds, leaving 2 cores free
38
+
cargo run --release -- --duration 60 --free-cores 2
39
+
```
40
+
41
+
## Options
42
+
43
+
```
44
+
-d, --duration <DURATION> Duration to run in seconds (omit for indefinite run)
45
+
-f, --free-cores <FREE_CORES> Number of cores to leave free (default: 1)
46
+
-h, --help Print help
47
+
-V, --version Print version
48
+
```
+90
src/main.rs
+90
src/main.rs
···
1
+
use clap::Parser;
2
+
use std::sync::atomic::{AtomicBool, Ordering};
3
+
use std::sync::Arc;
4
+
use std::thread;
5
+
use std::time::{Duration, Instant};
6
+
7
+
#[derive(Parser, Debug)]
8
+
#[command(author, version, about = "A CPU heater that churns CPU cores", long_about = None)]
9
+
struct Args {
10
+
/// Duration to run in seconds (omit for indefinite run)
11
+
#[arg(short, long)]
12
+
duration: Option<u64>,
13
+
14
+
/// Number of cores to leave free (default: 1)
15
+
#[arg(short = 'f', long, default_value_t = 1)]
16
+
free_cores: usize,
17
+
}
18
+
19
+
fn main() {
20
+
let args = Args::parse();
21
+
22
+
// Get the number of logical CPU cores
23
+
let total_cores = num_cpus::get();
24
+
let cores_to_use = total_cores.saturating_sub(args.free_cores).max(1);
25
+
26
+
println!("Total CPU cores: {}", total_cores);
27
+
println!("Cores to heat: {}", cores_to_use);
28
+
println!("Cores to leave free: {}", args.free_cores);
29
+
30
+
match args.duration {
31
+
Some(seconds) => println!("Running for {} seconds", seconds),
32
+
None => println!("Running indefinitely (press Ctrl+C to stop)"),
33
+
}
34
+
35
+
// Set up signal handler for graceful shutdown
36
+
let running = Arc::new(AtomicBool::new(true));
37
+
let r = running.clone();
38
+
39
+
ctrlc::set_handler(move || {
40
+
println!("\nReceived Ctrl+C, shutting down...");
41
+
r.store(false, Ordering::SeqCst);
42
+
})
43
+
.expect("Error setting Ctrl-C handler");
44
+
45
+
let start_time = Instant::now();
46
+
let duration = args.duration.map(Duration::from_secs);
47
+
48
+
// Spawn threads to churn CPU
49
+
let mut handles = vec![];
50
+
for i in 0..cores_to_use {
51
+
let running = running.clone();
52
+
let handle = thread::spawn(move || {
53
+
println!("Thread {} started", i);
54
+
let mut counter: u64 = 0;
55
+
while running.load(Ordering::SeqCst) {
56
+
//compute something meaningless but CPU-intensive
57
+
counter = counter.wrapping_add(1);
58
+
for j in 0..1000 {
59
+
counter = counter
60
+
.wrapping_mul(1103515245)
61
+
.wrapping_add(j)
62
+
.wrapping_rem(2147483648);
63
+
}
64
+
}
65
+
println!("Thread {} stopped after {} iterations", i, counter);
66
+
});
67
+
handles.push(handle);
68
+
}
69
+
70
+
// Monitor duration if specified
71
+
if let Some(dur) = duration {
72
+
while start_time.elapsed() < dur && running.load(Ordering::SeqCst) {
73
+
thread::sleep(Duration::from_millis(100));
74
+
}
75
+
running.store(false, Ordering::SeqCst);
76
+
} else {
77
+
// Wait indefinitely until Ctrl+C
78
+
for handle in handles {
79
+
handle.join().unwrap();
80
+
}
81
+
return;
82
+
}
83
+
84
+
// Wait for all threads to finish
85
+
for handle in handles {
86
+
handle.join().unwrap();
87
+
}
88
+
89
+
println!("Finished heating for {:?}", start_time.elapsed());
90
+
}