Skip to content

Commit 1dc0d20

Browse files
committed
---
yaml --- r: 125530 b: refs/heads/auto c: e65bcff h: refs/heads/master v: v3
1 parent 7098473 commit 1dc0d20

File tree

2 files changed

+146
-2
lines changed

2 files changed

+146
-2
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ refs/heads/try3: 9387340aab40a73e8424c48fd42f0c521a4875c0
1313
refs/tags/release-0.3.1: 495bae036dfe5ec6ceafd3312b4dca48741e845b
1414
refs/tags/release-0.4: e828ea2080499553b97dfe33b3f4d472b4562ad7
1515
refs/tags/release-0.5: 7e3bcfbf21278251ee936ad53e92e9b719702d73
16-
refs/heads/auto: 24a62e176ab1a91a249d040143cb91bac882cf7c
16+
refs/heads/auto: e65bcff7d5aa8040058580ff256cc9521ff40f29
1717
refs/heads/servo: af82457af293e2a842ba6b7759b70288da276167
1818
refs/tags/release-0.6: b4ebcfa1812664df5e142f0134a5faea3918544c
1919
refs/tags/0.1: b19db808c2793fe2976759b85a355c3ad8c8b336

branches/auto/src/librustrt/local_data.rs

Lines changed: 145 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,20 @@ impl<T: 'static> KeyValue<T> {
285285
None => None
286286
}
287287
}
288+
289+
// it's not clear if this is the right design for a public API, or if
290+
// there's even a need for this as a public API, but our benchmarks need
291+
// this to ensure consistent behavior on each run.
292+
#[cfg(test)]
293+
fn clear(&'static self) {
294+
let map = match unsafe { get_local_map() } {
295+
Some(map) => map,
296+
None => return
297+
};
298+
let keyval = key_to_key_value(self);
299+
self.replace(None); // ensure we have no outstanding borrows
300+
map.remove(&keyval);
301+
}
288302
}
289303

290304
impl<T: 'static> Deref<T> for Ref<T> {
@@ -392,6 +406,8 @@ impl Drop for TLDValue {
392406

393407
#[cfg(test)]
394408
mod tests {
409+
extern crate test;
410+
395411
use std::prelude::*;
396412
use std::gc::{Gc, GC};
397413
use super::*;
@@ -495,6 +511,26 @@ mod tests {
495511
fail!();
496512
}
497513

514+
#[test]
515+
fn test_cleanup_drops_values() {
516+
let (tx, rx) = channel::<()>();
517+
struct Dropper {
518+
tx: Sender<()>
519+
};
520+
impl Drop for Dropper {
521+
fn drop(&mut self) {
522+
self.tx.send(());
523+
}
524+
}
525+
static key: Key<Dropper> = &Key;
526+
let _ = task::try(proc() {
527+
key.replace(Some(Dropper{ tx: tx }));
528+
});
529+
// At this point the task has been cleaned up and the TLD dropped.
530+
// If the channel doesn't have a value now, then the Sender was leaked.
531+
assert_eq!(rx.try_recv(), Ok(()));
532+
}
533+
498534
#[test]
499535
fn test_static_pointer() {
500536
static key: Key<&'static int> = &Key;
@@ -543,9 +579,117 @@ mod tests {
543579
#[should_fail]
544580
fn test_nested_get_set1() {
545581
static key: Key<int> = &Key;
546-
key.replace(Some(4));
582+
assert_eq!(key.replace(Some(4)), None);
547583

548584
let _k = key.get();
549585
key.replace(Some(4));
550586
}
587+
588+
// ClearKey is a RAII class that ensures the keys are cleared from the map.
589+
// This is so repeated runs of a benchmark don't bloat the map with extra
590+
// keys and distort the measurements.
591+
// It's not used on the tests because the tests run in separate tasks.
592+
struct ClearKey<T>(Key<T>);
593+
#[unsafe_destructor]
594+
impl<T: 'static> Drop for ClearKey<T> {
595+
fn drop(&mut self) {
596+
let ClearKey(ref key) = *self;
597+
key.clear();
598+
}
599+
}
600+
601+
#[bench]
602+
fn bench_replace_none(b: &mut test::Bencher) {
603+
static key: Key<uint> = &Key;
604+
let _clear = ClearKey(key);
605+
key.replace(None);
606+
b.iter(|| {
607+
key.replace(None)
608+
});
609+
}
610+
611+
#[bench]
612+
fn bench_replace_some(b: &mut test::Bencher) {
613+
static key: Key<uint> = &Key;
614+
let _clear = ClearKey(key);
615+
key.replace(Some(1u));
616+
b.iter(|| {
617+
key.replace(Some(2))
618+
});
619+
}
620+
621+
#[bench]
622+
fn bench_replace_none_some(b: &mut test::Bencher) {
623+
static key: Key<uint> = &Key;
624+
let _clear = ClearKey(key);
625+
key.replace(Some(0u));
626+
b.iter(|| {
627+
let old = key.replace(None).unwrap();
628+
let new = old + 1;
629+
key.replace(Some(new))
630+
});
631+
}
632+
633+
#[bench]
634+
fn bench_100_keys_replace_last(b: &mut test::Bencher) {
635+
static keys: [KeyValue<uint>, ..100] = [Key, ..100];
636+
let _clear = keys.iter().map(ClearKey).collect::<Vec<ClearKey<uint>>>();
637+
for (i, key) in keys.iter().enumerate() {
638+
key.replace(Some(i));
639+
}
640+
b.iter(|| {
641+
let key: Key<uint> = &keys[99];
642+
key.replace(Some(42))
643+
});
644+
}
645+
646+
#[bench]
647+
fn bench_1000_keys_replace_last(b: &mut test::Bencher) {
648+
static keys: [KeyValue<uint>, ..1000] = [Key, ..1000];
649+
let _clear = keys.iter().map(ClearKey).collect::<Vec<ClearKey<uint>>>();
650+
for (i, key) in keys.iter().enumerate() {
651+
key.replace(Some(i));
652+
}
653+
b.iter(|| {
654+
let key: Key<uint> = &keys[999];
655+
key.replace(Some(42))
656+
});
657+
for key in keys.iter() { key.clear(); }
658+
}
659+
660+
#[bench]
661+
fn bench_get(b: &mut test::Bencher) {
662+
static key: Key<uint> = &Key;
663+
let _clear = ClearKey(key);
664+
key.replace(Some(42));
665+
b.iter(|| {
666+
key.get()
667+
});
668+
}
669+
670+
#[bench]
671+
fn bench_100_keys_get_last(b: &mut test::Bencher) {
672+
static keys: [KeyValue<uint>, ..100] = [Key, ..100];
673+
let _clear = keys.iter().map(ClearKey).collect::<Vec<ClearKey<uint>>>();
674+
for (i, key) in keys.iter().enumerate() {
675+
key.replace(Some(i));
676+
}
677+
b.iter(|| {
678+
let key: Key<uint> = &keys[99];
679+
key.get()
680+
});
681+
}
682+
683+
#[bench]
684+
fn bench_1000_keys_get_last(b: &mut test::Bencher) {
685+
static keys: [KeyValue<uint>, ..1000] = [Key, ..1000];
686+
let _clear = keys.iter().map(ClearKey).collect::<Vec<ClearKey<uint>>>();
687+
for (i, key) in keys.iter().enumerate() {
688+
key.replace(Some(i));
689+
}
690+
b.iter(|| {
691+
let key: Key<uint> = &keys[999];
692+
key.get()
693+
});
694+
}
551695
}

0 commit comments

Comments
 (0)