

WinForms のラインチャートに100,000,000データポイントをどう表示しますか? 答えは、どのチャートライブラリを選ぶかに完全に依存します — そして、ほぼすべての比較が逆に捉えているディテールにも: 正しいエンジンの上では、WinForms は WPF より遅くありません。速いのです。
この記事は、開発者が実際に評価する WinForms チャートライブラリ — ProEssentials、LightningChart、DevExpress、Syncfusion、ComponentOne、ScottPlot — で1億ポイントをレンダリングする、完全な動作する C# コードを提供します。各ステップであなたのデータに何が起こるか、そしてなぜ同じ ProEssentials エンジンが WPF より WinForms でおよそ5%速くレンダリングするのかを示します。
「plot millions of points WinForms」「fastest WinForms chart」「WinForms chart 100 million points」と検索してきた方へ — これがコードレベルでの具体的な答えです。クローンしてすぐ動く GitHub リポジトリ付きなので、すべての数字をご自身で再現できます。
ご自身でお試しください: WinForms の1億ポイント デモは公開リポジトリです — クローンし、F5 を押し、1億ポイントが hDC 上にレンダリングされるのをご覧ください。アカウント不要、トライアル登録不要、グリッド化された代用データもなし。
Building on WinUI 3? See the WinUI edition of this 100M-point comparison
Reproduce the WinForms numbers yourself: clone, build, run the WinForms 100M-point chart demo on GitHub.Compare against the WPF build: clone, build, run the WPF 100M-point chart demo on GitHub.
コードの前に、すべてを捉え直すアーキテクチャ上のポイントを。WPF 上の GPU チャートは Direct3D を画面へ直接描けません — ピクセルは WPF のコンポジターのものなので、ライブラリはオフスクリーン テクスチャへレンダリングし、D3DImage 経由で WPF に渡し、コンポジターに合成させなければなりません。すべてのフレームがテクスチャコピーとコンポジター同期のコストを払います。
ネイティブ WinForms コントロールは、本物の Win32 ウィンドウハンドルとデバイスコンテキスト(hDC)を所有します。ProEssentials は Direct3D をその hDC へ直接結合します — コンピュートシェーダーで構築されたフレームは、render-to-texture も二度目の合成もなく、ウィンドウへ直接提示されます。代表的なデータセット全体で、これによりネイティブ WinForms パスは、同一エンジンで WPF コントロールを駆動する場合よりエンドツーエンドでおよそ5%速くなります。
同じコンピュートシェーダー、同じゼロコピー データパス、同じオンデマンド モデル。WinForms は妥協のインターフェイスではありません — 速いほうのインターフェイスです。WPF のコンポジターを完全にスキップするからです。
すべてのライブラリが同じテストを受けます: ネイティブ WinForms フォーム上で、1億個の連続 float 値から単一系列のラインチャートをレンダリングします。ソース配列を超えるメモリ オーバーヘッド、レンダリング時間、そしてライブラリがすべてのポイントを表示するのかダウンサンプリングされた近似なのかを計測します。
| Parameter | Value |
|---|---|
| Data points | 100,000,000 (100 million) |
| Data type | float (4 bytes per value) — 400 MB raw data |
| Chart type | 2-D line chart, single series, sequential X-axis |
| Pattern | Sine wave with random noise (realistic signal data) |
| Platform | WinForms (.NET 8), Windows 11, mid-range GPU |
| What we measure | Lines of code, memory overhead, render time, data fidelity |
以下に、各ライブラリの完全な C# コードを、各ステップであなたのデータに何が起こるかの注釈付きで示します。何よりも1点に注目してください: 1億個の値がコピーされるのか、変換されるのか、オブジェクトでラップされるのか — そしてチャートがウィンドウへ直接提示するのか、相互運用レイヤーを経由するのか。
ProEssentials は UseDataAtLocation() を使い、WinForms チャートを既存の float 配列へ直接向けます。コピーなし、変換なし、オブジェクトのラップなし。Direct3D コンピュートシェーダーが1億個すべての頂点を GPU 上で構築し、フレームをコントロールの hDC へ直接提示します。
// ProEssentials — Plot 100 Million Points (WinForms, ~15 lines)
// NuGet: Install-Package ProEssentials.Chart.Net.Winforms
// 1. Allocate your data — this is the ONLY copy that will ever exist
float[] yData = new float[100_000_000];
for (int i = 0; i < yData.Length; i++)
yData[i] = (float)Math.Sin(i * 0.0001) + (float)(rand.NextDouble() * 0.1);
// 2. Configure the WinForms chart control (PesgoWin)
pesgo1.PeData.Subsets = 1;
pesgo1.PeData.Points = 100_000_000;
pesgo1.PePlot.Method = SGraphPlottingMethod.Line;
pesgo1.PeConfigure.RenderEngine = RenderEngine.Direct3D;
pesgo1.PeData.ComputeShader = true;
pesgo1.PeData.Filter2D3D = true; // GPU pre-filter shader — lossless min/max
// 3. Zero-copy: point the chart at your existing array — no duplication
pesgo1.PeData.Y.UseDataAtLocation(yData, yData.Length);
// 4. Tell the Direct3D engine to rebuild vertices and colors
pesgo1.PeFunction.Force3dxVerticeRebuild = true;
pesgo1.PeFunction.Force3dxNewColors = true;
// 5. Render — presented DIRECTLY to the WinForms window hDC
// (no render-to-texture, no WPF compositor hop)
pesgo1.PeFunction.ReinitializeResetImage();鍵となる行は UseDataAtLocation(yData, yData.Length) です。これはコピー操作ではありません — ポインタの代入です。データがすでに占有している400 MB が、存在する唯一のコピーです。チャートが加えるオーバーヘッドは実質ゼロです。
Force3dxVerticeRebuild と Force3dxNewColors のフラグは、Direct3D エンジンに頂点と色を GPU 上で再構築するよう伝えます。ComputeShader = true と Filter2D3D = true により、GPU 前段フィルターがロスレスなピクセル列ごとの min/max を計算し、スパイクは1つも失われません — そして結果は、WPF のコンポジター中継なしに hDC へ提示されます。
C# 約15行。メモリ オーバーヘッド約0 MB。レンダリング時間約15ミリ秒 — 同じコードの WPF 版より約5%高速。GPU コンピュートシェーダーによるロスレス min/max フィルタリング、WinForms の hDC へ直接提示。
SciChart は最速の WPF チャートとして頻繁に引用されますが、WinForms にはどんなコードサンプルでも回避できない問題があります: SciChart にはネイティブの WinForms コントロールがありません。自社ドキュメントが、WinForms は WPF との統合を通じてのみサポートされる — WPF の SciChartSurface を Microsoft の ElementHost 内にホストする方式 — と述べています。
// SciChart — Plot 100 Million Points (WinForms)
// NOTE: SciChart has NO native WinForms control.
// WinForms is supported only by hosting the WPF control in an ElementHost.
// 1. Host the WPF SciChartSurface inside a WinForms ElementHost
var host = new System.Windows.Forms.Integration.ElementHost();
host.Dock = DockStyle.Fill;
var sciChartSurface = new SciChart.Charting.Visuals.SciChartSurface();
host.Child = sciChartSurface; // WPF control living inside WinForms
this.Controls.Add(host);
// 2. From here the code is identical to the WPF path — and inherits
// WPF's render-to-texture compositor cost plus ElementHost interop
// limitations (mouse events, focus, z-order / "airspace").
var dataSeries = new XyDataSeries<double, double>(); // double[], not float[]
dataSeries.Append(xData, yData); // full internal copy
var lineSeries = new FastLineRenderableSeries {
DataSeries = dataSeries,
ResamplingMode = ResamplingMode.Auto // downsamples to ~viewport width
};
sciChartSurface.RenderableSeries.Add(lineSeries);
// There is no native WinForms SciChart control to target.つまり SciChart の WinForms アプリは、WPF の render-to-texture コンポジターパスに加え、マウスイベント、フォーカス、Z オーダーに関する ElementHost の文書化された相互運用制限を引き継ぎます。1億ポイントのコードは事実上 WPF のコードをラップしたものであり — ネイティブ WinForms なら避けられるコンポジターコストを抱えています。
真のネイティブ WinForms アプリケーションには、第一級の SciChart の道はありません。このカテゴリーの看板的な高性能ブランドはネイティブ WinForms のエントリーを出していない — だからこそ、ここではコードサンプルではなく相互運用として示しています。
LightningChart は、真にネイティブな WinForms のライバルとして最強です。特殊なサンプル系列を使い、AddSamples 型の呼び出しであなたの float[] を内部ストレージへコピーして、DirectX パイプラインで1億ポイントをレンダリングします。
// LightningChart — Plot 100 Million Points (WinForms)
// NuGet: Install-Package LightningChart.NET (native WinForms control)
// 1. Allocate your data
float[] yData = new float[100_000_000];
for (int i = 0; i < yData.Length; i++)
yData[i] = (float)Math.Sin(i * 0.0001) + (float)(rand.NextDouble() * 0.1);
// 2. Configure the native WinForms chart for large data
lightningChart.BeginUpdate();
lightningChart.ViewXY.XAxes[0].SetRange(0, 100_000_000);
// 3. SampleDataSeries (fixed-interval) — copies float[] into internal buffer
var series = new SampleDataSeries(lightningChart.ViewXY,
lightningChart.ViewXY.XAxes[0], lightningChart.ViewXY.YAxes[0]);
series.FirstSampleTimeStamp = 0;
series.SamplingFrequency = 1;
// 4. Add all 100M samples — array copy (not zero-copy)
series.AddSamples(yData, false);
// 5. Add series; continuous DirectX render loop keeps the GPU active
lightningChart.ViewXY.SampleDataSeries.Add(series);
lightningChart.EndUpdate();(正しい系列タイプであれば)1億ポイントすべてをロスレスにレンダリングします — これは本物の強みです。トレードオフは全体比較と同じです: 連続 DirectX レンダーループは何も変わらなくても GPU を稼働させ続け、データパスは配列を参照するのではなくコピーします。
LightningChart は、素の能力では最も近いネイティブ WinForms の競合です。違いは、配列コピー、連続ループの電力消費、アクティベーション/ライセンスに帰着します — ポイントをレンダリングできるかどうかではありません。
DevExpress は興味深い逆転です: その高速大規模データビュー SwiftPlotSeriesView は WinForms 専用で — WPF の ChartControl には存在しません。つまり、大規模データに関しては WinForms のほうが DevExpress の強い面なのです。
// DevExpress — Plot 100 Million Points (WinForms)
// NuGet: DevExpress.Win.Charts
// NOTE: SwiftPlotSeriesView is WinForms-ONLY — it does not exist in WPF.
// 1. Create data model — DevExpress uses object-per-point
public class DataPoint {
public double Argument { get; set; }
public double Value { get; set; }
}
// 2. Allocate the objects (object-per-point is the binding constraint)
var data = new List<DataPoint>(100_000_000);
for (int i = 0; i < 100_000_000; i++)
data.Add(new DataPoint {
Argument = i,
Value = Math.Sin(i * 0.0001) + rand.NextDouble() * 0.1
});
// ⚠ Billions of bytes of DataPoint objects before rendering starts.
// DevExpress markets 20M+ "without preprocessing" — short of 100M.
// 3. SwiftPlotDiagram + SwiftPlotSeriesView (the WinForms fast path)
var series = new Series("Signal", ViewType.SwiftPlot);
series.DataSource = data;
series.ArgumentDataMember = "Argument";
series.ValueDataMembers.AddRange("Value");
chartControl.Series.Add(series);
((SwiftPlotDiagram)chartControl.Diagram).EnableAxisXScrolling = true;SwiftPlot は軽量化された生成アルゴリズムと、ポイントごとオブジェクトのデータモデルを使います。1億ポイントでは、レンダリングが始まる前に膨大な数の SeriesPoint オブジェクトを割り当てなければなりません。実際には、レンダラーよりはるか手前で、これが拘束条件になります。DevExpress が宣伝するのは「前処理なしで2,000万ポイント超」 — 1億にはほど遠い数字です。
Syncfusion の看板「Fast Series」(FastLineSeries、FastLineBitmapSeries)は WPF、WinUI、UWP にしか存在しません。WinForms には高速系列のパスがまったくありません — Syncfusion 自身のサポートチームが機能リクエストを記録し、実装の当面の計画はないと述べています。
残るのは、GPU アクセラレーションのない標準 GDI+ レンダリングです。1億ポイントでは現実的なシナリオではありません。Syncfusion WinForms は約10万ポイント未満のビジネス ダッシュボードには強い選択肢ですが、大規模な科学計測向けではありません。
ScottPlot は支配的な無料/オープンソースの WinForms の選択肢です。System.Drawing、その後 SkiaSharp により CPU でレンダリングし、応答性を保つためにデータ間引き — データセットを視覚的なポイントの代表サブセットへ削減すること — に頼ります。
// ScottPlot — Plot 100 Million Points (WinForms, free / open-source)
// NuGet: Install-Package ScottPlot.WinForms
// 1. Allocate your data
double[] yData = new double[100_000_000];
for (int i = 0; i < yData.Length; i++)
yData[i] = Math.Sin(i * 0.0001) + rand.NextDouble() * 0.1;
// 2. SignalPlot is the large-data path (assumes even X spacing)
formsPlot1.Plot.Add.Signal(yData);
// 3. ScottPlot renders on the CPU (System.Drawing -> SkiaSharp) and
// relies on DECIMATION — it draws a representative subset, not all
// 100M points. Init for 10M+ runs 100+ ms; the displayed line is
// not lossless.
formsPlot1.Refresh();1,000万ポイント以上では初期化に100ミリ秒以上かかり、表示される結果は間引きされたものでロスレスではありません。ScottPlot のメンテナーは、ポイント配列のマネージド→ネイティブ マーシャリングが根本的な上限だと述べています。中程度のデータには素晴らしい価値ですが、ロスレスな1億エンジンではありません。
各ライブラリがネイティブ WinForms フォーム上で100,000,000個の float 値のプロットを試みたとき、何が起こるか:
| Factor | ProEssentials | SciChart | LightningChart | DevExpress | Syncfusion | ScottPlot |
|---|---|---|---|---|---|---|
| Native WinForms? | ✅ Yes | ❌ ElementHost | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |
| Plots 100M? | ✅ Lossless | ⚠️ via WPF, resampled | ✅ Lossless | ⚠️ object-per-point | ❌ No fast path | ⚠️ Decimated |
| Data loading | Zero-copy pointer | Copy into double[] | Array copy | Object-per-point | GDI+ iteration | Array (managed↔native) |
| Library overhead | ~0 MB | ~800 MB | ~400 MB | ~2,400 MB+ | — | ~copy |
| Render time | ~15 ms (GPU) | via WPF | Fast | Fast (lightened) | Slow (GDI+) | 100+ ms init |
| Data fidelity | 100% lossless | Resampled | 100% | Feature-reduced | Lossless but slow | Decimated |
| GPU rendering | Compute shaders | (WPF) DirectX | DirectX | GDI+/DirectX | None | CPU |
| Present path | Direct to hDC | WPF compositor | Direct | Direct | Direct | Direct |
| vs WPF (same engine) | ~5% faster | — | — | — | — | — |
WinForms では2つのアーキテクチャ上の事実が重なります。第一に、ProEssentials が UseDataAtLocation() を呼ぶとき、配列をコピーするのではなくポインタを保持します — メモリ オーバーヘッドはゼロです。第二に、完成したフレームは hDC へ直接提示され、WPF のテクスチャコピーと合成のオーバーヘッドは一切ありません。
恩恵は連鎖します。読み込み時間は瞬時です(1億個の値の反復に対し、ポインタの代入)。メモリは元の400 MB のまま増えません。そして提示パスは WPF より短く — そこからエンドツーエンド約5%の優位が生まれます。同じエンジン、マイナス・コンポジターです。
コピーする(LightningChart の AddSamples)、変換する(double[] 保存)、ラップする(ポイントごとオブジェクト)競合は、値あたりのメモリを倍増させます。1億ポイントでは、その倍率がフラットな400 MB とギガバイト単位の差 — あるいはチャートが描かれる前の OutOfMemoryException — になります。
| Data Model | Overhead (100M pts) | Used By |
|---|---|---|
| Zero-copy pointer | ~0 MB | ProEssentials |
| Array copy (float) | ~400 MB | LightningChart |
| Array copy (double) | ~800 MB | SciChart (via WPF) |
| Object-per-point | ~2,400 MB+ | DevExpress |
| CPU decimation | copy + subset | ScottPlot |
1億 float × 4バイト = 400 MB(あなたのデータ)。ProEssentials の追加は約0 MB、そして hDC へ提示。同じエンジンの WPF 版はフレームごとのテクスチャコピー + コンポジター同期を加えます — それこそが、ネイティブ WinForms パスが節約する約5%の正体です。
Telerik、ScottPlot、DevExpress の軽量ビューはいずれも、スケールで応答性を保つために何らかの形でデータを削減します — すべてのポイントではなく代表サブセットを表示するのです。トレンドの概観には、これで視覚的に問題ないことも多いでしょう。
しかし間引きされたチャートは、単一サンプルのイベントを隠し得ます: ECG の不整脈、振動の共振スパイク、マイクロ秒単位の半導体の逸脱。サブセットがたまたまそのサンプルを含まなければ、あなたは決してそれを見ることがありません。数百万ポイントを平均化して「扱う」とは、あなたのデータではなく、データの要約をレンダリングするということです。
ProEssentials は Filter2D3D GPU コンピュートシェーダーで異なるアプローチを取ります。ポイントを捨てるのではなく、1億個すべての値にわたって正しいピクセル列ごとの min/max を計算するため、すべてのスパイクが生き残ります — ロスレスで、hDC の上で。
ネイティブ WinForms の選択肢のうち、現実的に1億をロスレスにレンダリングできるのは ProEssentials と LightningChart だけです。DevExpress はポイントごとオブジェクトでそれより低い上限に達し、SciChart にはネイティブ コントロールがなく、Syncfusion には高速パスがなく、ScottPlot は間引きします。実用的なまとめは次のとおりです:
ProEssentials は、ゼロコピー データ読み込み、ロスレスな GPU コンピュートシェーダー フィルタリング、オンデマンド レンダリング、直接の hDC 提示を併せ持つ唯一の WinForms ライブラリです — しかも同じエンジンの WPF 版より約5%速く、それを証明する公開のクローンしてすぐ動くリポジトリ付きです。
WinForms で1億ポイントを試みられるライブラリは複数ありますが、勢力図は WPF より狭いものです。メモリ オーバーヘッドゼロ、ロスレスな忠実度、直接の hDC 提示で — しかも自社の WPF ビルドより速く — それをやるのは ProEssentials だけです。
SciChart にはネイティブ WinForms コントロールがありません。Syncfusion には WinForms の高速パスがありません。ScottPlot は間引きします。DevExpress の SwiftPlot は WinForms 専用ですがポイントごとオブジェクトです。LightningChart が真のネイティブな対抗馬で、配列コピーと連続ループのトレードオフを抱えています。
あなたの WinForms アプリケーションが1億ポイントの表示を必要とするなら — センサーデータ、信号処理、科学計測、LiDAR — hDC 結合のコンピュートシェーダー パスが、入手可能な最速のロスレスの選択肢であり、今日クローンして再現できる唯一の選択肢です。
この記事のすべての競合コード例と主張は、公式ドキュメント、公開 GitHub リポジトリ、ベンダーのサポート上の発言から構成されています。直接ご確認ください:
SciChart
LightningChart
DevExpress
Syncfusion
ComponentOne、Telerik、ScottPlot
ProEssentials は、登録なし、アカウントなし、営業電話なしで NuGet から入手できます。WinForms パッケージをインストールし、1億ポイントのリポジトリをクローンして、このページのすべての数字を再現してください。
ProEssentials チームに連絡 →御社とエンドユーザーに最も簡単で最もプロフェッショナルな価値を提供することで、お客様の成功を最優先目標とします。
ProEssentials は、自らのチャートコンポーネントを必要としたプロの電気エンジニアから生まれました。ProEssentials を使う一流エンジニアリング企業の長いリストに加わってください。
ProEssentials のお客様であることに感謝するとともに、ProEssentials チャートエンジンをご検討いただきありがとうございます。