10억 행 챌린지(The One Billion Row Challenge)

10억 행 챌린지(The One Billion Row Challenge)는 현대 Java를 이용해서 10억 행의 텍스트 파일을 얼마나 빨리 집계할 수 있는지를 살펴보는 탐구 입니다.

이 첼린지의 .NET 버전도 있습니다!


7 Likes
3 Likes

각 챌린지에서 탑 랭커의 속도가 닷넷이 많이 앞서는데, 그걸 그대로 받아 들일 수 있는지 의문스럽네요.

3 Likes

저도 비교 실행해보지는 않아서 뭐라 말할 수는 없지만 Java보다 .NET C#이 메모리 최적화와 속도 최적화에 좀 더 앞선 것으로 아는데요, 그 결과가 아닐까 살며시 생각해봅니다.

시간 될 때 C#으로 일반적인 방법을 써서 결과를 내보고 싶네요

3 Likes

맥에서는 파일 io에 대한 속도가 윈도우 대비 빠르게 나오는 부분이 있습니다.
애플 자체의 파일 테이블 시스템과 연계되어 있는 부분인데 깃헙의 결과 테이블에 net8/wasm 부터는 속도가 2분 이상으로 떨어지는게 바로 파일 읽는 방식이 달라지기 때문입니다.

실제로 파일 내부를 쓰거나 하지 않는 이상 마치 처리된것 처럼 보이게 하는 것도 있습니다.

일전에 대용량 파일을 생성 및 삭제하는 테스트를 해본적이 있는데
윈도우에는 실제로 파일 내부 바이너리를 다 채우고 io가 종료되는때까지의 시간이 기록되어서 오래걸리는걸로 확인됐지만, 맥에서는 파일 구조설정 및 공간 예약까지만 하고 끝내는 듯한 그런 모습으로(마치 비동기처리 되는것같은 느낌) 처리되는것 같았습니다. 그래서 두 os간 속도 차가 컸습니다.

제가 글을 잘 못적는데,
맥에서는 파일 io 처리 방식이 독특해서 속도가 굉장히 빨라 보인다 라는 점을 말씀드리고 싶었습니다.

6 Likes

.net 이 java보다 퍼포먼스가 좋다는것은 여기가 닷넷 커뮤니티라 하는 말이 아니라
유명한 얘기입니다.
심지어 자바 컨퍼런스 할때 닷넷 관계자들이 당당히 가서 퍼포먼스 자랑하는 마케팅도 벌인적이 있을정도로
아무래도 글로벌 회사인 MS 에 기준에 HW 업체들이 맞추고 공식적인 정보나 HW를 C언어 기준으로 최적화
하는 경우가 많아서 그런것이 아닐까 싶네
구글에 java vs .net performance benchmark 이렇게 검색해도 대부분 속도면에서 우위를 말하는 아티클이 많죠

2 Likes

궁금해져서 프로젝트 클론하고 measurements.txt 파일을 생성해서 잠깐 살펴봤는데 용량이 12.8GB 군요! -_-;;;; 일반적인 방법으로는 2~3초대 절대로 나올 수 없는 크기군요!

2 Likes

다음의 구조로

class MeasurementAggregator
{
    public double Min { get; set; } = double.MaxValue;
    public double Max { get; set; } = double.MinValue;
    public double Sum { get; set; }
    public long Count { get; set; }
}

Dictionary를 이용해서 최소, 최대, 합계, 개수를 저장하는 일반적인 코드를 작성한 후

var count = 0;
var dic = new Dictionary<string, MeasurementAggregator>();
while (true)
{
    var line = await file.ReadLineAsync();
    if (line is null)
        break;

    var (zoneName, strTemp) = line.Split(';') is string[] splits ? (splits[0], splits[1])
        : throw new Exception("Invalid line format");

    var bResult = dic.TryGetValue(zoneName, out var zone);
    if (bResult is false)
        zone = new MeasurementAggregator();

    var temp = double.Parse(strTemp);
    zone!.Min = Math.Min(zone!.Min, temp);
    zone!.Max = Math.Max(zone.Max, temp);
    zone!.Sum += temp;
    zone!.Count++;
    
    count++;

    if (count % 10000000 is 0)
    {
        Console.WriteLine($"{count}: {zoneName}|{strTemp}");
    }
}

i9-12900H, n.2 nvme
.NET 8, Release, x64로 컴파일 실행했을 때 140,638 ms (2.34 분) 걸리네요.

2~3초는 어떻게 나오는 걸까요? ;;

2 Likes

파일이 12기가 가량이니까, 3초가 나올려면 적어도 초당 5기가는 읽어들이고 그와 동시에 처리되어야 하지 않을까 싶네요. 재밌겠네요 나중에 한번 해봐야겠습니다.

2 Likes

아무리 그래도, 3초만에 12GB를 처리하는 것은 매우 어렵지 않나요?

2 Likes

닷넷 버전은 맥을 사용한 것을 확인할 수 있는데, 자바의 경우 동일하게 맥에서 사용한 것인지 확인이 안되어서, 수치를 그대로 받아 들이기 어렵습니다.

만약, 동일 사양 컴퓨터에서 JDK 와 .Net Sdk 를 모두 설치하고 실행해 봐야 어느 것이 더 빠르다고 할 수 있지 않을까요?

2 Likes

1BRC in .NET among fastest on Linux: My Optimization Journey · Victor Baybekov (hotforknowledge.com)

C++ 과 rust 의 중간이군요.

4 Likes
2 Likes
3 Likes

요즘 이 프로젝트에 매료되신 것 같네요.

덕분에, 즐겁게 벤치마크 결과를 보고 있습니다.
특히, C++, 러스트 보다 빠르다는 점이요. ^^

해당 프로젝트의 코드를 보고 이해하는 게 너무 어려운 게 함정이지만요. ㅠㅠ

3 Likes