Forcing NDSolve not to store full solution, in order to save memory

Inspired from Nasser's answer:

It's possible to return only the last (or some other specific values) value from NDSolve.

Try

sol3 = NDSolveValue[{y''[x] + Sin[x]*x == 5, y[0] == 1, y'[0] ==0},y[5], {x, 4.5, 5}]
ByteCount[sol3](*16*)

Is there a way to save memory by forcing NIntegrate to only return the final values of the dependent variables?

One way could be to just give it the small end range of interest, this way the interpolation function will have much smaller size. You can still give initial conditions at say x=0 but tell it to given solution starting at much larger x value, and it will still work. The x_start in {x,x_start,x_end} does not have to be the same as the initial value of x.

For example, instead of

sol = NDSolveValue[{y''[x] + Sin[x]*x == 5, y[0] == 1, y'[0] == 0}, y, {x, 0, 5}]
Plot[sol[x], {x, 0, 5}]

Mathematica graphics

sol2 = NDSolveValue[{y''[x]+Sin[x]*x==5,y[0]==1,y'[0]==0},y,{x,4.5,5}]
Plot[sol2[x],{x,4.5,5},AxesOrigin->{0,0}]

Mathematica graphics

If you compare sol and sol2, you'll see sol2 has less data in it.

 ByteCount[sol]
 (*3984*)

 ByteCount[sol2]
  (*1936*)

I feel some clarification is needed to the answers by @Nasser and @UlrichNeumann. There's not really much difference in the memory used by either. @UlrichNewmann's sol3 = NDSolveValue[..., y[5],...] seems basically to be syntactic sugar for sol3 = NDSolveValue[..., y,...]; sol3 = sol3[5]. The main memory saving comes from @Nasser's {x, 4.5, 5}, instead of which {x, 5, 5} would give even more memory savings.

Examples: I've extended the domain so that the differences would be more noticeable.

@UlrichNeumann's method:

Quit[]

$HistoryLength = 0;
MaxMemoryUsed[]
(*  65508912 -- baseline  *)

sol3 = NDSolveValue[{y''[x] + Sin[x]*x == 1/1000, y[0] == 1, 
    y'[0] == 0}, y[200000], {x, 100000, 200000}];
ByteCount[sol3]
MaxMemoryUsed[]
(*
  16
  235687584
*)

MemoryInUse[]
(*  82906632  *)

Quit[]

@Nasser's method. Note that the max memory usage and the memory in use after sol3 = sol3[200000] are similar.

$HistoryLength = 0;
MaxMemoryUsed[]
(*  65508848 -- baseline  *)

sol3 = NDSolveValue[{y''[x] + Sin[x]*x == 1/20, y[0] == 1, 
    y'[0] == 0}, y, {x, 100000, 200000}];
ByteCount[sol3]
MaxMemoryUsed[]
(*
  59626536
  238685400
*)

MemoryInUse[]
(*  142533152  *)

sol3 = sol3[200000];
ByteCount[sol3]
(*  16  *)

MemoryInUse[]
(*  82906320  *)

The equivalent of using {x, 5, 5} with @UlrichNeumann's method. Note that the max memory used is just a little above the memory in use.

Quit[]

$HistoryLength = 0;
MaxMemoryUsed[]
(*  65508848 -- baseline  *)

sol3 = NDSolveValue[{y''[x] + Sin[x]*x == 1/20, y[0] == 1, 
    y'[0] == 0}, y[200000], {x, 200000, 200000}];
ByteCount[sol3]
MaxMemoryUsed[]
(*
  16
  85011648
*)

MemoryInUse[]
(*  82640112  *)