c#이 c++보다 빠른 경우도 있네요

평소 체감상 비슷한 프로그램을 개발했을때 초기 로딩속도나 UI 렌더링(윈폼) 속도 같은건 c#이 확실히 느리긴 하더군요.
최근에 몇만개~몇십만개 파일을 찾아서 링크드 리스트로 만들고 마지막에 소팅시키는 기능을 구현했는데
서로 로직이 약간 다르긴한데 c++보다 c#이 훨씬 빠르더라구요.
물론 로직이 다른 부분땜에 그렇다고 볼 수도 있긴한데 전체 흐름은 비슷하거든요.
엄격한 테스트를 위해선 c++도 c#과 완전히 똑같은 로직으로 구현해야하는데 그건 못해봤습니다.
어쨌든 c#이 생각보다 빨라서 의외였습니다.

부연설명하자면 소팅하기전 파일 찾을때 Directory.GetFiles() 메소드 사용했는데
찾은 파일을 리스트에 추가할때마다 콘솔창에 로그를 찍게했습니다.
이 로그 찍는 속도가 c++보다 몇 배는 빠르게 찍혔습니다.
결국 소팅이전에 파일찾는 속도 자체가 c#이 더 빨랐습니다.

4개의 좋아요

개인적으로는 조금 다른 생각이 듭니다.

막연히 "C#이 C++보다 우수해서 빠르다"는 평가는 오해를 유발할 수 있다고 봅니다.

어떻게 구현했는가에 따라 다르겠지만, 언급하신 내용 중에 파일을 탐색하는 동작이 있으면 이런 차이가 언어의 우수성이 아닌 구현 방식 상의 차이 때문에 얼마든지 벌어질 수 있다고 보는데요,

문자열 버퍼를 실행 도중에 얼마나 자주 할당하고 해제하는지 (힙 메모리 관리를 얼마나 빈번하게 하는지), 문자열 탐색은 어떻게 구현하는지 (BSTR의 경우 문자열 서두에 길이를 기록하고, SZ의 경우 문자열을 끝까지 돌려봐야 길이를 알 수 있는 등)와 같은 디테일한 부분의 차이가 결과물로 나오는 알고리즘의 실행 시간에서 큰 차이를 만들 수 있기 때문에 특히 그렇다고 생각합니다.

그리고 Windows Forms의 경우 UI를 렌더링하는 과정에서 COM 개체도 자주 사용하고, 네이티브 API와 마샬링을 빈번하게 주고 받기 때문에 거기서 오는 비용도 무시할 수 없습니다. 이 또한 C#이 느려서라기보다, 같은 기능을 어떻게 구현했는가에 따라서 오는 차이라고 생각합니다.

6개의 좋아요

stackoverflow에 올리면 down vote 얻어 맞을 글입니다.
쉽게 결론 내지 마시고 테스트 방법이 올바른지 충분히 검토하시기 바랍니다.
이런 주제는 모두가 확인 가능하도록 테스트 코드 공개해야 합니다.

4개의 좋아요

둘 다 하는 사람으로서 말씀드리자면 평범하게 짜면 이제는 C#이 더 빠를 수 있습니다.
라이브러리에 따라 많이 갈리기도 하고요.
결론은 C++은 개발자 역량이 퍼포먼스에 그대로 반영 됩니다.

4개의 좋아요

구현했던 내용에 대해 좀더 설명하자면 c++은 Qt 기반으로 작성되었습니다.
c++ 소스는 아래와 같습니다.

QDirIterator dirIter(SearchPath, QStringList() << "*", QDir::Files | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
while (dirIter.hasNext())
{
    QString filepath = dirIter.next();

    if (filepath.endsWith(".") || filepath.endsWith("..")) {
        continue;
    }

    QFileInfo fileInfo(filepath);
    if (fileInfo.isFile())
    {
        // 여기서 QList에 fileInfo 추가
        qDebug() << fileInfo.filePath() << "added";
    }
}

c# 코드는 아래와 같습니다.

string[] filepaths = null;

try
{
    filepaths = Directory.GetFiles(SearchPath, "*", SearchOption.AllDirectories);
}
catch (Exception ex)
{
	Console.WriteLine(ex.ToString());
}

if (filepaths != null)
{
    for (int i = 0; i < filepaths.Length; i++)
    {
        string filepath = filepaths[i];
        Console.WriteLine($"{filepath} added");
		// 여기서 filepath를 이용해서 객체생성 후 리스트에 추가
	}
}

둘의 차이점은 c++은 QList 사용, c#은 List를 사용, 리스트 삽입 전 객체 생성부분이 틀린데 이런 차이가 원인일 수도 있겠네요

1개의 좋아요

QList::reserve()로 메모리 충분히 확보했나요?
QList changes in Qt 6
참고로 Qt6에서 QList 변경이 있습니다.

1개의 좋아요

reserve() 는 안했는데 그게 원인일 수도 있겠네요

1개의 좋아요

C++에서 컨테이너 계열은 미리 할당을 하는게 좋습니다.
안하면 추가할때마다 메모리를 계속해서 할당하는데. 이게 별거 아닐 것 같아도 누적되면 차이가 큽니다.
특히 vector는 내부적으로 포인터라 추가하면 메모리 전체를 삭제하고 다시 할당 합니다.
물론 그걸 피하는 방법도 있긴 한데. 기본적으로는 미리 공간을 만들어 두는 것이 좋습니다.

다만 제가 QT를 극혐하는지라 QT는 어떤식으로 만들어져 있는지 까지는 모르겠네요.
극혐하는 이유는 별거 없고 한번 QT로 만들면 QT에 종속이 된다는게 매우 싫습니다.

1개의 좋아요