2017-12-31 255 views
0

는 :디버그 모드에서 구조체의 큰 벡터 요소에 액세스하는 것이 왜 더 작은 구조체에 액세스하는 것보다 느린 것입니까? 나는이 코드를 실행하면

With struct, size of vec=100000: Time elapsed: 1.268881822 seconds 
With struct, size of vec=100000000: Time elapsed: 12.470818140 seconds 
With u64, size of vec=100000: Time elapsed: 1.171180429 seconds 
With u64, size of vec=100000000: Time elapsed: 1.230393828 seconds 

내가 두 번째 함수 호출이 첫 번째보다 10 배 느린해야 어떤 이유가 표시되지 않습니다

#[derive(Copy, Clone)] 
pub struct Element { 
    pub key: u64, 
} 

pub fn test1(u: usize) { 
    let now = std::time::SystemTime::now(); 

    let tt = vec![Element { key: 0 }; u]; 
    for _ in 0..10000000 as u64 { 
     if tt[155].key == 893472348628 {} 
    } 

    match now.elapsed() { 
     Ok(elapsed) => { 
      println!(
       "With struct, size of vec={}: Time elapsed: {}.{} seconds", 
       u, 
       elapsed.as_secs(), 
       elapsed.subsec_nanos() 
      ); 
     } 
     Err(e) => { 
      println!("Error: {:?}", e); 
      panic!(); 
     } 
    } 
} 

pub fn test2(u: usize) { 
    let now = std::time::SystemTime::now(); 

    let tt = vec![0u64; u]; 
    for _ in 0..10000000 as u64 { 
     if tt[155] == 893472348628 {} 
    } 

    match now.elapsed() { 
     Ok(elapsed) => { 
      println!(
       "With u64, size of vec={}: Time elapsed: {}.{} seconds", 
       u, 
       elapsed.as_secs(), 
       elapsed.subsec_nanos() 
      ); 
     } 
     Err(e) => { 
      println!("Error: {:?}", e); 
      panic!(); 
     } 
    } 
} 

fn main() { 
    test1(100000); 
    test1(100000000); 
    test2(100000); 
    test2(100000000); 
} 

을 나는 이러한 결과를 얻을 수 있습니다.

if tt[155].key == 893472348628 {} 

나는 어쩌면 그와 함께 할 수있는 뭔가가, 8GB의 RAM과 64 비트 리눅스 머신을 가지고 : 릴리스 모드는이 라인을 무시하기 때문에 나는 디버그 모드로 컴파일 했는가?

+1

게시물에 대한 수정 사항에 대해 감사드립니다. 질문은 이제 더 많은 * 좋은 상태에 있고 응답 할만큼 충분히 구체적입니다. – Shepmaster

답변

4

시간이 걸리지 만 벡터를 초기화하는 요소에 액세스하지 않습니다. 사실, 당신의 예제와 함께 내가 얻을 :

With struct, size of vec=100000: Time elapsed: 0.594704815 seconds 
With struct, size of vec=100000000: Time elapsed: 5.789152687 seconds 
With u64, size of vec=100000: Time elapsed: 0.584137362 seconds 
With u64, size of vec=100000000: Time elapsed: 0.586343084 seconds 

나는 다음과 같은 얻을 nowtt 후 초기화 할 경우

With struct, size of vec=100000: Time elapsed: 0.589499628 seconds 
With struct, size of vec=100000000: Time elapsed: 0.583244899 seconds 
With u64, size of vec=100000: Time elapsed: 0.584675666 seconds 
With u64, size of vec=100000000: Time elapsed: 0.583518382 seconds 

벡터를 초기화는 모든 요소가 0에 초기화 할 필요가 있기 때문에 선형 시간이 걸립니다 (또는 Element { key: 0 }).

0Element { key: 0 }보다 빠르기 때문에 왜 vec!이 작동하는지 살펴 보겠습니다. We can see it just calls vec::from_elem, 차례로 just calls <T as SpecFromElem>::from_elem입니다. 이 특성은 무엇입니까?

let mut v = Vec::with_capacity(n); 
v.extend_with(n, ExtendElement(elem)); 

을하지만 0u64 하나를 포함 bunch of special cases도 있습니다 : 글쎄, 기본 구현은 기본적으로 같은 보인다! 이것은 RawVec::with_capacity_zeroed(n)을 사용합니다. 의심 할 여지없이이 특별한 경우는 속도가 어디서 오는가입니다.

+0

아마도 릴리스 모드에서, 옵티마이 저는'Element' 구조체를 "보고"리터럴'u64'로 만들 것이고, 따라서 동일한 특별한 케이스를 열 수 있습니까? – Shepmaster

+0

나는 확실히 그렇게 바랄 것이다. – mcarton