c++ stl Vector push_back 에 관하여

익명 사용자의 이미지

안녕하세요
Vector 컨테이너 사용중 다음과 같은 현상이 있어 질문이 있습니다
템플릿 환경 : mfc

1. 약 400byte 사이즈를 가지는 구조체가 있음
2. 해당 구조체는 vector로 관리
3. 100만개 데이터 push_back 수행속도 약 3초
4. 이후 3번의 로직이 진행된 Dialog는 특정 시간동안 먹통(체감상 10초이상,디버깅 포인트를 못찾겠습니다)

struct _tagData{ // size 400byte
int m_nData;
...
}

std::vector<_tagData> vecData;
vecData.reserve(1000000);

DWORD dwStart = GetTickCount();

_tagData row;
for (int i = 0; i < 1000000; ++i)
{
row.m_nData = i;
vecData.push_back(row);
}

DWORD dwEnd = GetTickCount();

TRACE("rows size %d, time %d\n", rows.size(), (dwEnd - dwStart) / 1000);

return;
//리턴 이후 해당 dlg는 특정 시간 먹통(뭔가 내부적으로 처리가 이뤄지는거 같은데..감이 안잡힙니다)

혹시 관리하는 구조체 사이즈 때문인가 싶어 자료형을 int형만으로 테스트 결과 현상은 사라졌습니다
그럼 구조체 크기 때문이다 라고 접근이 가능한데
좀더 빠른속도로 수행이 가능한 기법이 있는지 궁금합니다

답변 감사합니다!

작성자의 이미지

본문에 내용이 빠져있네요

Stephen Kyoungwon Kim@Google의 이미지

윈도우즈 프로그래밍 경험이 없어서 구체적인 맥락은 잘 모르겠습니다만.. 대충 GUI event handler가 말씀하신 루틴을 불러서 실행한 뒤 리턴을 해도 GUI가 새로운 event를 받을 준비가 안 된다는 말씀이죠? 그리고 지금 문제인 건 3번의 3초가 아니라 4번의 10초인 거고요?

저 대규모 벡터의 scope은 어떻게 되나요? 리턴을 하면 이 vector의 lifetime이 끝나나요? 예컨대 핸들러가 부르는 함수 안에 로컬 변수로 정의된다거나 하는 식으로요.

아니면 핸들러가 수행을 끝내고도 살아 있어서 코드의 다른 부분에서 활용될 수 있나요?

그냥 봐서 가장 의심되는 건, scope 밖으로 나가면서 lifetime이 다 되어 100만개의 아이템에 대해 destructor를 부른 다음 그 100만개 아이템이 들어갈 메모리 공간 할당해 놓았던 것을 반납하고 실제로 콜러로 리턴하는 상황 같은데, 그건 caller, callee와 vector 선언 부분 등을 봐야 알 수 있을 것 같습니다.

작성자의 이미지

말씀하신 vector의 생명주기는 테스트를위해 지역변수 형태로 사용되었습니다
제가 대규모 인것을 놓치고 엉성하게 테스트를 했네요 ^^;;
클래스 맴버로 잡아놓고 진행하니 딜레이가 현저히 줄었지만 여전히 존재하긴 합니다

마찬가지로 궁금한 요지는 4번의 상황에서 왜 딜레이가 존재하는가 입니다
구현된 함수가 리턴 되었다는것은 100만번의 처리를 수행이 다끝났다는 것으로 봐야 되는게 아닌지..

그것이 아니라면 실제 처리에대한 예외적 상황을 구현해야 하는것인지
그럼 정확한 처리시간의 계산은 어떤식으로 이뤄져야하는지
많은양의 데이터를 관리해보려고 하는건 처음이라 난감한것들이 있네요ㅠㅠ

Stephen Kyoungwon Kim@Google의 이미지

재현가능, 까지는 아니라도 코드를 첨부하시면 읽기가 더 쉬울 것 같습니다. 말로 설명하시는 부분은 애매해서 어떤 상황인지 정확하게 이해가 되지 않아요.

100만번 수행이 다 끝나고 나서 getTickCount()가 수행되는 것까지는 맞다고 생각합니다. 다만 그때까지 생성되어 vector 안에 저장된 1백만 개의 object를 destroy하는 게 문제 같다는 얘기였습니다.

이게 stack에 잡힌 int variable이면, 그냥 stack을 날리면서 저절로 날아갈 텐데 destructor가 있는, 심지어 그 안에서 약간이라도 복잡한 일을 하는 class의 object라면 얘기가 다르죠. 컴파일러는 이 vector 안의 100만개의 lifetime이 다할 때 100만개 각각에 대해 destructor를 일일이 부를 수밖에 없습니다.

본문처럼 vector type의 변수가 function scope에서 정의가 되고 그 안에 100만개가 푸쉬된 상태라면, vecData가 더 이상 유효하지 않을 때, 그러니까 function이 return을 하거나 exception이 생겨서 function code의 수행이 중지되는 등의 일이 발생할 때, vecData의 destructor가 불릴 텐데, 그 안에서 아마 vecData 원소 각각의 destructor가 불리게끔 되어 있을 겁니다.

언제 불리느냐의 문제지 100만개 원소의 lifetime이 다한다면 destructor가 100만번 불리고 나서 vector 자체의 clean up을 수행하는 것까지는 불가피한 일로 보이네요.

이 destructor를 수행하는 thread가 event handler라서 새 event를 못 받는 것이 문제라고 이해했는데, 그런 경우라면 destructor가 다른 thread에서 수행되도록 코드를 설계해야 할 것으로 보이네요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.