Skip to content

Commit 291bf05

Browse files
Alexandra Iordacheacatangiu
authored andcommitted
process startup time in CPU and wall clock micros
Signed-off-by: Alexandra Iordache <[email protected]>
1 parent f69dacb commit 291bf05

File tree

8 files changed

+53
-25
lines changed

8 files changed

+53
-25
lines changed

api_server/src/lib.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ impl ApiServer {
7878
pub fn bind_and_run<P: AsRef<Path>>(
7979
&self,
8080
path_or_fd: UnixDomainSocket<P>,
81-
jailer_start_time_ms: Option<u64>,
81+
start_time_us: Option<u64>,
82+
start_time_cpu_us: Option<u64>,
8283
) -> Result<()> {
8384
let mut core = Core::new().map_err(Error::Io)?;
8485
let handle = Rc::new(core.handle());
@@ -95,12 +96,20 @@ impl ApiServer {
9596
}
9697
};
9798

98-
if let Some(start_time_ms) = jailer_start_time_ms {
99-
let delta = (chrono::Utc::now().timestamp_millis() as u64) - start_time_ms;
99+
if let Some(start_time) = start_time_us {
100+
let delta_us = (chrono::Utc::now().timestamp_nanos() / 1000) as u64 - start_time;
100101
METRICS
101102
.api_server
102-
.process_startup_time_ms
103-
.add(delta as usize);
103+
.process_startup_time_us
104+
.add(delta_us as usize);
105+
}
106+
107+
if let Some(cpu_start_time) = start_time_cpu_us {
108+
let delta_us = fc_util::now_cputime_us() - cpu_start_time;
109+
METRICS
110+
.api_server
111+
.process_startup_time_cpu_us
112+
.add(delta_us as usize);
104113
}
105114

106115
let http: Http<hyper::Chunk> = Http::new();

data_model/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ pub struct FirecrackerContext {
1717
pub id: String,
1818
pub jailed: bool,
1919
pub seccomp_level: u32,
20-
pub start_time_ms: u64,
20+
pub start_time_us: u64,
21+
pub start_time_cpu_us: u64,
2122
}

jailer/src/env.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,12 @@ pub struct Env {
4343
netns: Option<String>,
4444
daemonize: bool,
4545
seccomp_level: u32,
46-
start_time_ms: u64,
46+
start_time_us: u64,
47+
start_time_cpu_us: u64,
4748
}
4849

4950
impl Env {
50-
pub fn new(args: ArgMatches, start_time_ms: u64) -> Result<Self> {
51+
pub fn new(args: ArgMatches, start_time_us: u64, start_time_cpu_us: u64) -> Result<Self> {
5152
// All arguments are either mandatory, or have default values, so the unwraps
5253
// should not fail.
5354
let id = args.value_of("id").unwrap();
@@ -117,7 +118,8 @@ impl Env {
117118
netns,
118119
daemonize,
119120
seccomp_level,
120-
start_time_ms,
121+
start_time_us,
122+
start_time_cpu_us,
121123
})
122124
}
123125

@@ -271,7 +273,8 @@ impl Env {
271273
id: self.id.clone(),
272274
jailed: true,
273275
seccomp_level: self.seccomp_level,
274-
start_time_ms: self.start_time_ms,
276+
start_time_us: self.start_time_us,
277+
start_time_cpu_us: self.start_time_cpu_us,
275278
};
276279

277280
Err(Error::Exec(
@@ -358,6 +361,7 @@ mod tests {
358361
true,
359362
),
360363
0,
364+
0,
361365
).expect("This new environment should be created successfully.");
362366

363367
let mut chroot_dir = PathBuf::from(chroot_base);
@@ -374,14 +378,16 @@ mod tests {
374378
let another_good_env = Env::new(
375379
make_args(node, id, exec_file, uid, gid, chroot_base, None, false),
376380
0,
381+
0,
377382
).expect("This another new environment should be created successfully.");
378383
assert!(!another_good_env.daemonize);
379384

380385
// Not fine - invalid node.
381386
assert!(
382387
Env::new(
383388
make_args("zzz", id, exec_file, uid, gid, chroot_base, None, true),
384-
0
389+
0,
390+
0,
385391
).is_err()
386392
);
387393

@@ -398,6 +404,7 @@ mod tests {
398404
None,
399405
true
400406
),
407+
0,
401408
0
402409
).is_err()
403410
);
@@ -415,6 +422,7 @@ mod tests {
415422
None,
416423
true
417424
),
425+
0,
418426
0
419427
).is_err()
420428
);
@@ -423,6 +431,7 @@ mod tests {
423431
assert!(
424432
Env::new(
425433
make_args(node, id, exec_file, "zzz", gid, chroot_base, None, true),
434+
0,
426435
0
427436
).is_err()
428437
);
@@ -431,6 +440,7 @@ mod tests {
431440
assert!(
432441
Env::new(
433442
make_args(node, id, exec_file, uid, "zzz", chroot_base, None, true),
443+
0,
434444
0
435445
).is_err()
436446
);

jailer/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ fn open_dev_kvm() -> Result<i32> {
190190
Ok(ret)
191191
}
192192

193-
pub fn run(args: ArgMatches, start_time_ms: u64) -> Result<()> {
193+
pub fn run(args: ArgMatches, start_time_us: u64, start_time_cpu_us: u64) -> Result<()> {
194194
// We open /dev/kvm and create the listening socket. These file descriptors will be
195195
// passed on to Firecracker post exec, and used via knowing their values in advance.
196196

@@ -200,7 +200,7 @@ pub fn run(args: ArgMatches, start_time_ms: u64) -> Result<()> {
200200
sanitize_process();
201201
open_dev_kvm()?;
202202

203-
let env = Env::new(args, start_time_ms)?;
203+
let env = Env::new(args, start_time_us, start_time_cpu_us)?;
204204

205205
// Ensure the folder exists.
206206
fs::create_dir_all(env.chroot_dir())

logger/src/metrics.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ impl Serialize for SharedMetric {
117117
#[derive(Default, Serialize)]
118118
pub struct ApiServerMetrics {
119119
pub instance_info_fails: SharedMetric,
120-
pub process_startup_time_ms: SharedMetric,
120+
pub process_startup_time_us: SharedMetric,
121+
pub process_startup_time_cpu_us: SharedMetric,
121122
pub sync_outcome_fails: SharedMetric,
122123
pub sync_vmm_send_timeout_count: SharedMetric,
123124
}

src/bin/jailer.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
extern crate chrono;
22
extern crate clap;
33

4+
extern crate fc_util;
45
extern crate jailer;
56

67
fn main() -> jailer::Result<()> {
78
jailer::run(
89
jailer::clap_app().get_matches(),
9-
chrono::Utc::now().timestamp_millis() as u64,
10+
(chrono::Utc::now().timestamp_nanos() / 1000) as u64,
11+
fc_util::now_cputime_us(),
1012
)
1113
}

src/main.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,16 +74,17 @@ fn main() {
7474

7575
let mut instance_id = String::from(DEFAULT_INSTANCE_ID);
7676
let mut seccomp_level = 0;
77-
let mut start_time_ms = None;
78-
77+
let mut start_time_us = None;
78+
let mut start_time_cpu_us = None;
7979
let mut is_jailed = false;
8080

8181
if let Some(s) = cmd_arguments.value_of("context") {
8282
let context = serde_json::from_str::<FirecrackerContext>(s).unwrap();
8383
is_jailed = context.jailed;
8484
instance_id = context.id;
8585
seccomp_level = context.seccomp_level;
86-
start_time_ms = Some(context.start_time_ms);
86+
start_time_us = Some(context.start_time_us);
87+
start_time_cpu_us = Some(context.start_time_cpu_us);
8788
}
8889

8990
let shared_info = Arc::new(RwLock::new(InstanceInfo {
@@ -113,7 +114,9 @@ fn main() {
113114
UnixDomainSocket::Path(bind_path)
114115
};
115116

116-
server.bind_and_run(uds_path_or_fd, start_time_ms).unwrap();
117+
server
118+
.bind_and_run(uds_path_or_fd, start_time_us, start_time_cpu_us)
119+
.unwrap();
117120
}
118121

119122
#[cfg(test)]

tests/integration_tests/performance/test_process_startup_time.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88

99
import host_tools.logging as log_tools
1010

11-
MAX_STARTUP_TIME_US = 80
12-
""" The maximum acceptable startup time in ms. """
11+
MAX_STARTUP_TIME_CPU_US = 8000
12+
""" The maximum acceptable startup time in CPU us. """
1313
# TODO: Keep a `current` startup time in S3 and validate we don't regress
1414

1515

@@ -44,9 +44,11 @@ def test_startup_time(test_microvm_with_api):
4444
# Since metrics are flushed at InstanceStart, the first line will suffice.
4545
lines = log_tools.sequential_fifo_reader(metrics_fifo_path, 1)
4646
metrics = json.loads(lines[0])
47-
startup_time = int(metrics['api_server']['process_startup_time_ms'])
47+
startup_time_us = metrics['api_server']['process_startup_time_us']
48+
cpu_startup_time_us = metrics['api_server']['process_startup_time_cpu_us']
4849

49-
print('Process startup time is: {} ms'.format(startup_time))
50+
print('Process startup time is: {} us ({} CPU us)'
51+
.format(startup_time_us, cpu_startup_time_us))
5052

51-
assert startup_time > 0
52-
assert startup_time <= MAX_STARTUP_TIME_US
53+
assert cpu_startup_time_us > 0
54+
assert cpu_startup_time_us <= MAX_STARTUP_TIME_CPU_US

0 commit comments

Comments
 (0)