My observations:
While there are many ways you can squeeze every bit of performance from your system to display graphics, I sincerely do not believe you can find your solution from an answer from this question. But you can find many leads.
You have performance problems drawing a simple graph while "modern applications" have no problem rendering thousands of points, so why is that? A game can render more than 60 frames per second in 4K resolution and you can not render a single frame of dummy graphics to a surface.
How do they do that? Well, they cheat optimize.
If you draw not every point, but only meaningful points and fill the rest by curving like @yves-daoust suggested, you will save on some drawing time. This is like how MP3 compresses audio, it simply removes the parts you most likely be unable to hear.
If you enable DoubleBuffering
like @tigran suggested, your result will displayed on screen more efficiently, or better you can draw your graph in another thread and then paint that graph instead of redrawing it in every OnPaint.
You can update only relevant parts of the graph by utilizing Invalidate(Rect) method.
You can draw you graph into a bitmap using direct bit manipulation as @yves-daoust (again) suggested, this may greatly improve your performance but you have to implement every function which is crazy.
While Graphics
object uses not GDI but GDI+ it is very well optimized for many not-so-complex drawing operations, you can use othe graphics libraries optimized for performance like DirectX and Skia.
My Suggestion:
If you insist you should draw everything then get some books about Graphics using C# and spend some quality time with them. If not, then get some low-cost low-size charting library and be done with it.
My situation:
I had implemented a simple line drawing algorithm in Pascal 6.0 (DOS times), using BGIs, using interrupts, using direct memory access and using IO ports. After some skimming on code, one can say I'm into BDSM.