sgcPivotGrid 벤치마크
1,000,000행과 10,000,000행에서 측정한 sgcPivotGrid 엔진 TsgcPivotEngine의 시간입니다. 데이터 로드, 세 가지 피벗 레이아웃을 단일 패스와 병렬 계산으로 재계산하는 시간, 데이터 위에 엔진이 추가로 사용하는 메모리를 다룹니다. 모든 수치는 sgcUI 데모에 포함된 벤치마크 프로그램에서 나온 것이므로, 같은 테스트를 직접 하드웨어에서 실행할 수 있습니다.
1,000,000행과 10,000,000행에서 측정한 sgcPivotGrid 엔진 TsgcPivotEngine의 시간입니다. 데이터 로드, 세 가지 피벗 레이아웃을 단일 패스와 병렬 계산으로 재계산하는 시간, 데이터 위에 엔진이 추가로 사용하는 메모리를 다룹니다. 모든 수치는 sgcUI 데모에 포함된 벤치마크 프로그램에서 나온 것이므로, 같은 테스트를 직접 하드웨어에서 실행할 수 있습니다.
AppendRow로 10,000,000행 로드Win64, Delphi 13, 워밍업 1회 후 5회 실행의 중앙값이며, 아래에 설명한 테스트 머신에서 측정했습니다. Win64 결과, Win32 결과, QA 예산, 직접 테스트하는 방법으로 바로 이동할 수 있습니다.
행은 고정된 시드로 생성되므로 모든 머신이 같은 피벗을 계산합니다. 모든 모드에서 P1 총합계가 값 열의 합계와 같은지 확인합니다.
| 시나리오 | 프로그램의 동작 |
|---|---|
| 로드 | 텍스트 값 3개, 숫자 1개, 날짜 1개로 이루어진 1,000,000행 또는 10,000,000행을 AppendRow로 추가합니다. 텍스트는 도착하는 대로 멤버 인덱스로 인코딩됩니다. 두 번째 단계에서는 Store.SetFloat로 숫자 열을 100,000개의 고유 값으로 채웁니다. |
| P1 Sum | 행 필드 2개(50개 지역 x 20개 제품, 소계와 총합계를 포함해 행 항목 1,051개)와 열 필드 1개(12개월), 값 하나의 Sum. 기본 피벗입니다. |
| P3 CountDistinct | 고유 값이 100,000개인 열의 고유 값을 세는 P1 레이아웃으로, 표준 집계 중 가장 비용이 큽니다. |
| P4 StdDev, Average, Max | P1 레이아웃에서 세 가지 측정값을 동시에 계산합니다. |
| 단일 패스 | 기본 엔진이며 ParallelCalculation이 꺼져 있습니다. |
| 스레드 1~14개 | MaxThreads를 지정하고 ParallelCalculation := True, ParallelThreshold := 1로 설정하므로 1,000,000행도 병렬로 실행됩니다. "모든 CPU"는 MaxThreads := 0으로, 논리 CPU당 스레드 하나이며 테스트 머신에서는 14개입니다. |
| 엔진 메모리 | P1에서 로드된 데이터 위에 엔진이 추가로 할당하는 메모리입니다(QA 게이트 M1). 저장소 메모리는 로드된 데이터 자체입니다. |
격리된 실험실 머신이 아니라 평소의 데스크톱 부하가 있는 개발자 워크스테이션입니다. 2026년 11월 4일에 측정했습니다.
| 항목 | 값 |
|---|---|
| CPU | Intel Core Ultra 5 245T, 35 W 데스크톱 프로세서 |
| 코어 | 고성능 코어 6개와 효율 코어 8개, 논리 CPU 14개 |
| 메모리 | 31.5 GB |
| 운영 체제 | Windows 11 Pro 26H2 (빌드 26300) |
| 컴파일러 | Delphi 13 Florence, 릴리스 빌드: 최적화 켜짐, 범위 및 오버플로 검사 꺼짐 |
| 플랫폼 | Win64(워밍업 1회 후 5회 실행의 중앙값)와 Win32(빠른 실행: 워밍업 1회 후 측정 1회) |
| sgcPivotGrid | 2026.11.0 Registered |
이 프로세서는 고성능 코어와 효율 코어가 섞여 있으며, 각 작업자 스레드가 어디에서 실행될지는 Windows가 결정합니다. 스레드가 8개 이상이면 일부 작업이 효율 코어에서 실행됩니다. 그래서 Win64에서 1,000,000행의 P4는 실행마다 약 13 ms와 약 32 ms를 오가며, 스레드 8개에서 중앙값이 31.2 ms로 뛰어오릅니다.
워밍업 1회 후 5회 실행의 중앙값입니다. 시간 단위는 밀리초입니다.
| 로드와 메모리 | 1,000,000행 | 10,000,000행 |
|---|---|---|
AppendRow, 텍스트 3개, 실수 1개, 날짜 1개 열 | 132.9 ms | 1,384.0 ms |
Store.SetFloat, 고유 값 100,000개의 실수 열 1개 | 8.6 ms | 98.3 ms |
| 저장소 메모리(열 6개) | 36.0 MB | 576.0 MB |
| P1 이후 엔진 메모리, 모든 모드 | 4.8 MB | 39.1 MB |
| 모드 | 스레드 | P1 Sum | P3 CountDistinct | P4 StdDev, Average, Max |
|---|---|---|---|---|
| 단일 패스 | 1 | 13.9 ms | 25.6 ms | 26.3 ms |
| 병렬, 스레드 1개 | 1 | 12.2 ms | 21.6 ms | 26.3 ms |
| 병렬, 스레드 2개 | 2 | 9.6 ms | 18.2 ms | 17.8 ms |
| 병렬, 스레드 4개 | 4 | 7.1 ms | 15.9 ms | 12.9 ms |
| 병렬, 스레드 8개 | 8 | 6.8 ms | 15.3 ms | 31.2 ms |
| 병렬, 모든 CPU | 14 | 6.8 ms | 16.5 ms | 31.8 ms |
| 모드 | 스레드 | P1 Sum | P3 CountDistinct | P4 StdDev, Average, Max |
|---|---|---|---|---|
| 단일 패스 | 1 | 121.1 ms | 300.2 ms | 216.9 ms |
| 병렬, 스레드 1개 | 1 | 106.4 ms | 253.0 ms | 230.6 ms |
| 병렬, 스레드 2개 | 2 | 67.1 ms | 212.7 ms | 130.3 ms |
| 병렬, 스레드 4개 | 4 | 46.9 ms | 184.6 ms | 127.5 ms |
| 병렬, 스레드 8개 | 8 | 63.6 ms | 181.1 ms | 111.9 ms |
| 병렬, 모든 CPU | 14 | 73.5 ms | 186.4 ms | 105.4 ms |
빠른 실행: 워밍업 1회 후 측정 1회이므로 Win64 중앙값보다 수치의 편차가 큽니다. 프로그램은 large address aware이며, 10,000,000행 저장소에 이것이 필요합니다.
| 로드와 메모리 | 1,000,000행 | 10,000,000행 |
|---|---|---|
AppendRow, 텍스트 3개, 실수 1개, 날짜 1개 열 | 143.7 ms | 1,511.9 ms |
Store.SetFloat, 고유 값 100,000개의 실수 열 1개 | 16.8 ms | 183.7 ms |
| 저장소 메모리(열 6개) | 36.0 MB | 576.0 MB |
| P1 이후 엔진 메모리, 모든 모드 | 4.7 MB | 39.1 MB |
| 모드 | 스레드 | P1 Sum | P3 CountDistinct | P4 StdDev, Average, Max |
|---|---|---|---|---|
| 단일 패스 | 1 | 16.9 ms | 27.3 ms | 50.8 ms |
| 병렬, 스레드 1개 | 1 | 16.7 ms | 22.9 ms | 51.0 ms |
| 병렬, 스레드 2개 | 2 | 11.3 ms | 20.4 ms | 32.8 ms |
| 병렬, 스레드 4개 | 4 | 8.6 ms | 16.3 ms | 23.1 ms |
| 병렬, 스레드 8개 | 8 | 8.5 ms | 16.3 ms | 19.2 ms |
| 병렬, 모든 CPU | 14 | 8.5 ms | 15.6 ms | 19.2 ms |
| 모드 | 스레드 | P1 Sum | P3 CountDistinct | P4 StdDev, Average, Max |
|---|---|---|---|---|
| 단일 패스 | 1 | 143.6 ms | 286.8 ms | 442.6 ms |
| 병렬, 스레드 1개 | 1 | 139.4 ms | 253.6 ms | 463.7 ms |
| 병렬, 스레드 2개 | 2 | 88.0 ms | 207.8 ms | 252.4 ms |
| 병렬, 스레드 4개 | 4 | 52.5 ms | 176.8 ms | 141.7 ms |
| 병렬, 스레드 8개 | 8 | 57.2 ms | 167.1 ms | 159.6 ms |
| 병렬, 모든 CPU | 14 | 64.4 ms | 172.0 ms | 131.9 ms |
Delphi 프로그램과 같은 행, 레이아웃, 모드를 사용하는 벤치마크 프로그램의 .NET 포트입니다. 다른 런타임에서 실행되므로 이 수치는 별도의 표로 읽어 주세요. 워밍업 1회 후 5회 실행의 중앙값이며, 시간 단위는 밀리초입니다.
| 로드와 메모리 | 1,000,000행 | 10,000,000행 |
|---|---|---|
AppendRow, 텍스트 3개, 실수 1개, 날짜 1개 열 | 75.6 ms | 770.4 ms |
Store.SetFloat, 고유 값 100,000개의 실수 열 1개 | 2.9 ms | 43.0 ms |
| 저장소 메모리(열 6개) | 36.0 MB | 576.0 MB |
| P1 이후 엔진 메모리, 모든 모드 | 4.7 MB | 39.1 MB |
런타임: .NET 8.0.31, x64 프로세스, 릴리스 빌드, sgcPivotGrid 2026.11.0 Registered를 사용하는 net8.0 콘솔 프로그램이며, 위의 테스트 머신에서 같은 날 측정했습니다. 메모리는 전체 수집 후 GC.GetTotalMemory(true)로 측정한 실시간 관리 힙입니다.
| 모드 | 스레드 | P1 Sum | P3 CountDistinct | P4 StdDev, Average, Max |
|---|---|---|---|---|
| 단일 패스 | 1 | 11.9 ms | 23.3 ms | 14.7 ms |
| 병렬, 스레드 1개 | 1 | 12.1 ms | 21.3 ms | 20.1 ms |
| 병렬, 스레드 2개 | 2 | 8.5 ms | 15.5 ms | 12.6 ms |
| 병렬, 스레드 4개 | 4 | 6.3 ms | 14.8 ms | 9.9 ms |
| 병렬, 스레드 8개 | 8 | 6.8 ms | 13.6 ms | 9.8 ms |
| 병렬, 모든 CPU | 14 | 6.6 ms | 13.3 ms | 9.6 ms |
| 모드 | 스레드 | P1 Sum | P3 CountDistinct | P4 StdDev, Average, Max |
|---|---|---|---|---|
| 단일 패스 | 1 | 67.6 ms | 275.1 ms | 128.0 ms |
| 병렬, 스레드 1개 | 1 | 76.4 ms | 215.0 ms | 175.9 ms |
| 병렬, 스레드 2개 | 2 | 44.2 ms | 159.6 ms | 89.9 ms |
| 병렬, 스레드 4개 | 4 | 28.8 ms | 133.7 ms | 56.2 ms |
| 병렬, 스레드 8개 | 8 | 34.0 ms | 151.7 ms | 72.6 ms |
| 병렬, 모든 CPU | 14 | 28.3 ms | 154.9 ms | 66.0 ms |
.NET QA 성능 테스트는 Delphi 예산의 1.2배를 사용합니다(x64에서 P1 120 ms). 이번 실행에서 1,000,000행의 모든 게이트가 예산 이내였고, 모든 모드에서 P1 총합계가 값의 합계와 같았습니다.
PivotGrid\Benchmark\Benchmark.csproj를 엽니다. 자세한 내용은 해당 폴더의 README.md에 있습니다.dotnet-<arch>.md, .json, .csv를 쓰며, 예를 들어 dotnet-x64.md가 만들어집니다.dotnet run -c Release
dotnet run -c Release -- --rows=1m,10m --quick
dotnet run -c Release -- --rows=500k,2m --threads=4 --out=C:\benchQA 성능 그룹은 모든 빌드에서 Win64와 Win32에 대해 이 예산을 검증하며, 하나라도 초과하면 QA 실행이 실패합니다. 10,000,000행에는 예산이 없고 QA는 결과만 보고합니다.
| 게이트 | 측정 대상 | Win64 예산 | Win64 측정값 | Win32 예산 | Win32 측정값 |
|---|---|---|---|---|---|
| P1 | 1,000,000행 재계산, 행 필드 2개, 열 필드 1개, Sum 1개 | 100 ms | 13.9 ms | 160 ms | 16.9 ms |
| P1P | ParallelCalculation을 사용한 P1, CPU당 스레드 하나 | 100 ms | 6.8 ms | 160 ms | 8.5 ms |
| P2 | 텍스트 3개, 실수 1개, 날짜 값 1개로 이루어진 1,000,000행의 AppendRow, 인코딩 포함 | 900 ms | 132.9 ms | 1,400 ms | 143.7 ms |
| P3 | 고유 값이 100,000개인 열에 CountDistinct를 적용한 P1 레이아웃 | 400 ms | 25.6 ms | 600 ms | 27.3 ms |
| P4 | StdDev, Average, Max를 적용한 P1 레이아웃 | 180 ms | 26.3 ms | 280 ms | 50.8 ms |
| M1 | P1에서 저장소 위의 엔진 메모리 | 32 MB | 4.8 MB | 32 MB | 4.7 MB |
| M1P | ParallelCalculation을 사용한 M1, CPU당 스레드 하나 | 32 MB | 4.8 MB | 32 MB | 4.7 MB |
예산은 느린 빌드 머신에서도 성능 저하를 잡아내도록 일부러 넉넉하게 잡았습니다. 테스트 머신에서 측정값은 예산보다 5.5배에서 22배 낮습니다.
표의 병렬 행이 추가하는 것과 사용할 스레드 수입니다. Registered
ParallelCalculation := True는 큰 재계산을 131,072행 단위의 고정 청크로 나누어 작업자 스레드에서 계산하고, 청크 순서대로 병합합니다. MaxThreads는 작업자 수를 제한하며(0은 CPU당 하나, 최대 64), 기본값이 1,000,000행인 ParallelThreshold는 그보다 작은 저장소를 단일 패스로 유지합니다. Sum, Average, Product, StdDev 계열은 마지막 비트에서 단일 패스와 달라질 수 있으므로 기본값은 꺼짐입니다. Registered 및 체험판 에디션에 포함됩니다.
MaxThreads는 4에서 8을 사용하세요. 테스트 머신의 Win64에서는 두 크기 모두 스레드 4개에서 P1이 가장 좋았습니다. 1,000,000행에서 7.1 ms, 10,000,000행에서 46.9 ms이며, 단일 패스는 각각 13.9 ms와 121.1 ms입니다.같은 프로그램, 같은 행, 같은 레이아웃을 직접 하드웨어에서 실행합니다.
Demos\PivotGrid\Delphi\Benchmark\sgcPivotGridBenchmark.dpr을 엽니다. 자세한 내용은 해당 폴더의 README.txt에 있습니다.sgcPivotGridBenchmark [--rows=1m,10m] [--threads=1,2,4,8,0] [--out=folder] [--quick]
sgcPivotGridBenchmark
sgcPivotGridBenchmark --rows=1m,10m --quick
sgcPivotGridBenchmark --rows=500k,2m --threads=4 --out=C:\bench| 스위치 | 의미 |
|---|---|
--rows | 테스트할 행 수이며, k와 m 접미사를 사용할 수 있습니다. |
--threads | 병렬 모드의 MaxThreads 값입니다. 0 또는 all은 CPU당 스레드 하나입니다. 단일 패스는 항상 실행됩니다. |
--out | 출력 폴더이며, 기본값은 exe 옆의 benchmark 폴더입니다. |
--quick | 5회 실행의 중앙값 대신 워밍업 후 측정 1회만 실행합니다. |
실행할 때마다 머신, 설정, 모든 측정 시간을 담은 delphi-<platform>.md, .json, .csv를 쓰고 1,000,000행의 QA 예산을 확인합니다. BenchmarkMain.pas에 모든 로직이 들어 있으므로, 생성된 행을 직접 데이터로 바꾸고 같은 시간 측정과 보고서를 그대로 사용할 수 있습니다. 수치가 여기와 크게 다르면 알려 주세요.
QA 예산은 Architecture 도움말 항목에도 설명되어 있습니다.