title: how do i get more frames per second from this jogl program?
body: <p>trying to get more fps from this jogl program. theoretical fps is very high, but actual fps is low. jvisualvm says that most (over 90%) of the time is spent in AWTAnimatorImpl.display() &amp; GLDrawableHelper.displayImpl().</p>
  
  <pre><code>package stanalone;
  import static java.awt.Color.cyan;
  import static java.awt.Color.magenta;
  import static java.awt.Color.white;
  import static java.awt.Color.yellow;
  import static java.awt.Color.red;
  import static java.lang.Math.PI;
  import static java.lang.Math.cos;
  import static java.lang.Math.min;
  import static java.lang.Math.signum;
  import static java.lang.Math.sin;
  import static javax.media.opengl.GL.GL_ARRAY_BUFFER;
  import static javax.media.opengl.GL.GL_COLOR_BUFFER_BIT;
  import static javax.media.opengl.GL.GL_DEPTH_BUFFER_BIT;
  import static javax.media.opengl.GL.GL_DEPTH_TEST;
  import static javax.media.opengl.GL.GL_FLOAT;
  import static javax.media.opengl.GL.GL_FRONT;
  import static javax.media.opengl.GL.GL_FRONT_AND_BACK;
  import static javax.media.opengl.GL.GL_LEQUAL;
  import static javax.media.opengl.GL.GL_MAX_TEXTURE_SIZE;
  import static javax.media.opengl.GL.GL_NICEST;
  import static javax.media.opengl.GL.GL_POINTS;
  import static javax.media.opengl.GL.GL_WRITE_ONLY;
  import static javax.media.opengl.GL2ES1.GL_PERSPECTIVE_CORRECTION_HINT;
  import static javax.media.opengl.GL2GL3.GL_FILL;
  import static javax.media.opengl.fixedfunc.GLLightingFunc.GL_SMOOTH;
  import static javax.media.opengl.fixedfunc.GLMatrixFunc.GL_MODELVIEW;
  import static javax.media.opengl.fixedfunc.GLMatrixFunc.GL_PROJECTION;
  
  import java.awt.Color;
  import java.awt.Component;
  import java.awt.Dimension;
  import java.awt.Point;
  import java.awt.event.WindowAdapter;
  import java.awt.event.WindowEvent;
  import java.awt.geom.Point2D;
  import java.nio.ByteBuffer;
  import java.nio.ByteOrder;
  import java.nio.FloatBuffer;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.Random;
  import java.util.concurrent.ScheduledThreadPoolExecutor;
  import java.util.concurrent.TimeUnit;
  
  import javax.media.opengl.GL;
  import javax.media.opengl.GL2;
  import javax.media.opengl.GLAutoDrawable;
  import javax.media.opengl.GLCapabilities;
  import javax.media.opengl.GLEventListener;
  import javax.media.opengl.GLProfile;
  import javax.media.opengl.awt.GLJPanel;
  import javax.media.opengl.fixedfunc.GLLightingFunc;
  import javax.media.opengl.fixedfunc.GLPointerFunc;
  import javax.media.opengl.glu.GLU;
  import javax.swing.JFrame;
  import javax.swing.SwingUtilities;
  
  import com.jogamp.common.nio.Buffers;
  import com.jogamp.opengl.util.FPSAnimator;
  import com.jogamp.opengl.util.gl2.GLUT;
  class Histogram {
      public Histogram() {
          this(10,0,1);
      }
      public Histogram(int bins,double low,double high) {
          this.bins=bins;
          bin=new int[bins];
          this.low=low;
          this.high=high;
          range=high-low;
      }
      public void add(double[] x) {
          for(int i=0;i&lt;x.length;i++)
              add(x[i]);
      }
      public void add(double x) {
          n++;
          sum+=x;
          final double x2=x*x;
          sum2+=x2;
          min=Math.min(min,x);
          max=Math.max(max,x);
          if(x&gt;=high)
              overflows++;
          else if(x&lt;low)
              underflows++;
          else {
              double val=x-low;
              int index=(int)(bins*(val/range));
              bin[index]++;
          }
      }
      public void clear() {
          for(int i=0;i&lt;bins;i++)
              bin[i]=0;
          overflows=0;
          underflows=0;
          min=Double.MAX_VALUE;
          max=Double.MIN_VALUE;
      }
      public int n() {
          return n;
      }
      public double low() {
          return low;
      }
      public double high() {
          return high;
      }
      public double range() {
          return high()-low();
      }
      public int bins() {
          return bins;
      }
      public double min() {
          return n==0?Double.NaN:min;
      }
      public double max() {
          return n==0?Double.NaN:max;
      }
      public double sum() {
          return n==0?Double.NaN:sum;
      }
      public double mean() {
          return n==0?Double.NaN:sum/n;
      }
      public double variance() {
          return n==0?Double.NaN:sum2/n-mean()*mean();
      }
      public int bin(int index) {
          if(index&lt;0)
              return underflows;
          else if(index&gt;=bins)
              return overflows;
          else return bin[index];
      }
      public double maxDifference() {
          double max=0;
          for(int i=0;i&lt;bins();i++)
              max=Math.max(max,Math.abs(bin(i)-n()/(double)bins())/(n()/(double)bins()));
          return max;
      }
      public String toString() {
          final StringBuffer sb=new StringBuffer();
          sb.append((float)min()).append("&lt;=").append((float)mean()).append("&lt;=").append((float)max()).append(" ");
          sb.append(bin(-1)).append(",[");
          for(int i=0;i&lt;bins;i++)
              sb.append(i&gt;0?",":"").append(bin(i));
          sb.append("],").append(bin(bins));
          return sb.toString();
      }
      private int[] bin;
      private int n,bins,underflows,overflows;
      private final double low,high,range;
      private double min=Double.MAX_VALUE,max=Double.MIN_VALUE,sum,sum2;
  }
  class MyDataObject {
      MyDataObject(Point2D[] points) {
          this(points,white);
      }
      MyDataObject(Point2D[] points,Color color) {
          this.points=points;
          this.color=color;
      }
      Point2D[] points;
      Color color;
      static Point2D[] randomPoints(Random random,Point2D offset) {
          List&lt;Point2D&gt; l=new LinkedList&lt;Point2D&gt;();
          int n=nPoints/pieces.length;
          for(int j=0;j&lt;n;j++)
              l.add(new Point2D.Double(offset.getX()+random.nextFloat(),offset.getY()+random.nextFloat()));
          return l.toArray(new Point2D[0]);
      }
      static MyDataObject[] pieces;
      static Color[] colors=new Color[]{cyan,magenta,yellow,white};
      static int nPoints=1000000;
  }
  class StandAlone implements GLEventListener {
      StandAlone(GLAutoDrawable drawable) {
          this.drawable=drawable;
          drawable.addGLEventListener(this);
          init();
      }
      void init() {
          nVbos=4;
          vertexBufferIndices=new int[nVbos];
          for(int i=0;i&lt;vertexBufferIndices.length;i++)
              vertexBufferIndices[i]=-1;
          numberOFVertices=new int[nVbos];
          // drawAxes=true;
          MyDataObject.pieces=new MyDataObject[nVbos];
          for(int i=0;i&lt;nVbos;i++) {
              Point2D offset=new Point.Double(min(0,signum(cos(PI/4+i*PI/2))),min(0,signum(sin(PI/4+i*PI/2))));
              MyDataObject.pieces[i]=new MyDataObject(MyDataObject.randomPoints(random,offset),MyDataObject.colors[i%MyDataObject.colors.length]);
          }
      }
      static void setupFrame(Component component) {
          setupFrame(component,defaultFps);
      }
      static void setupFrame(Component component,int fps) {
          component.setPreferredSize(new Dimension(displayWidth,displayHeight));
          final FPSAnimator animator=new FPSAnimator((GLAutoDrawable)component,fps,true);
          final JFrame frame=new JFrame();
          frame.getContentPane().add(component);
          frame.addWindowListener(new WindowAdapter() {
              @Override public void windowClosing(WindowEvent e) {
                  new Thread() {
                      @Override public void run() {
                          if(animator.isStarted())
                              animator.stop();
                          System.exit(0);
                      }
                  }.start();
              }
          });
          frame.setTitle(TITLE);
          frame.pack();
          frame.setVisible(true);
          animator.start();
      }
      static void setup() {
          GLProfile glprofile=GLProfile.getDefault();
          GLCapabilities glcapabilities=new GLCapabilities(glprofile);
          GLJPanel panel=new GLJPanel(glcapabilities);
          new StandAlone(panel);
          setupFrame(panel,200);
      }
      public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
              @Override public void run() {
                  setup();
              }
          });
      }
      private void createVbo(GL2 gl2,int[] n,int index) {
          if(!gl2.isFunctionAvailable("glGenBuffers")||!gl2.isFunctionAvailable("glBindBuffer")||!gl2.isFunctionAvailable("glBufferData")||!gl2.isFunctionAvailable("glDeleteBuffers")) { throw new RuntimeException("Vertex buffer objects not supported."); }
          gl2.glGenBuffers(1,vertexBufferIndices,index);
          // create vertex buffer data store without initial copy
          gl2.glBindBuffer(GL_ARRAY_BUFFER,vertexBufferIndices[index]);
          gl2.glBufferData(GL_ARRAY_BUFFER,n[0]*3*Buffers.SIZEOF_FLOAT*2,null,GL.GL_DYNAMIC_DRAW);
      }
      private static void storeVerticesAndColors(FloatBuffer floatbuffer,MyDataObject w) {
          for(Point2D p:w.points) {
              floatbuffer.put((float)p.getX()).put((float)p.getY()).put(0);
              floatbuffer.put((float)(w.color.getRed()/255.));
              floatbuffer.put((float)(w.color.getGreen()/255.));
              floatbuffer.put((float)(w.color.getBlue()/255.));
          }
          floatbuffer.rewind();
      }
      private void fillVertexBuffer(GL2 gl2,MyDataObject piece,int index) {
          // map the buffer and write vertex and color data directly into it
          gl2.glBindBuffer(GL_ARRAY_BUFFER,vertexBufferIndices[index]);
          ByteBuffer bytebuffer=gl2.glMapBuffer(GL_ARRAY_BUFFER,GL_WRITE_ONLY);
          FloatBuffer floatbuffer=bytebuffer.order(ByteOrder.nativeOrder()).asFloatBuffer();
          storeVerticesAndColors(floatbuffer,piece);
          gl2.glUnmapBuffer(GL_ARRAY_BUFFER);
      }
      protected int createAndFillVertexBuffer(GL2 gl2,MyDataObject piece,int index) {
          int[] n=new int[]{piece.points.length};
          if(vertexBufferIndices[index]==-1)
              createVbo(gl2,n,index);
          fillVertexBuffer(gl2,piece,index);
          return n[0];
      }
      private void renderPiece(GLAutoDrawable drawable,int index) {
          final GL2 gl2=drawable.getGL().getGL2();
          gl2.glColorMaterial(GL_FRONT_AND_BACK,GLLightingFunc.GL_AMBIENT_AND_DIFFUSE);
          gl2.glEnable(GLLightingFunc.GL_COLOR_MATERIAL);
          // draw all objects in vertex buffer
          gl2.glBindBuffer(GL_ARRAY_BUFFER,vertexBufferIndices[index]);
          gl2.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
          gl2.glEnableClientState(GLPointerFunc.GL_COLOR_ARRAY);
          gl2.glVertexPointer(3,GL_FLOAT,6*Buffers.SIZEOF_FLOAT,0);
          gl2.glColorPointer(3,GL_FLOAT,6*Buffers.SIZEOF_FLOAT,3*Buffers.SIZEOF_FLOAT);
          gl2.glPolygonMode(GL_FRONT,GL_FILL);
          gl2.glDrawArrays(GL_POINTS,0,1*numberOFVertices[index]);
          // disable arrays once we're done
          gl2.glBindBuffer(GL_ARRAY_BUFFER,0);
          gl2.glDisableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
          gl2.glDisableClientState(GLPointerFunc.GL_COLOR_ARRAY);
          gl2.glDisable(GLLightingFunc.GL_COLOR_MATERIAL);
      }
      private void startTimeReporting() {
          t0=System.nanoTime();
          if(frame%reportPeriod==0)
              t0Frame=t0;
          if(frame&gt;1) {
              double dt=(System.nanoTime()-t0Display);
              double millis=dt/1000000.;
              hDisplay.add(millis);
          }
      }
      void endTimeReporting() {
          double dt=(System.nanoTime()-t0);
          double millis=dt/1000000.;
          hRender.add(millis);
          if(++frame%reportPeriod==0) {
              System.out.println("average render time: "+hRender.mean()+" ms., max fps="+1000./hRender.mean());
              double dtFrames=System.nanoTime()-t0Frame;
              System.out.println("average time between calls to display: "+hDisplay.mean()+" ms., actual fps="+reportPeriod/(dtFrames/1000000.)*1000.);
              hRender.clear();
          }
          t0Display=System.nanoTime();
      }
      void update() {
          angle+=1;
      }
      @Override public void reshape(GLAutoDrawable drawable,int x,int y,int width,int height) {
          System.out.println("super.reshape "+drawable);
          GL2 gl=drawable.getGL().getGL2();
          if(height==0)
              height=1;
          float aspect=(float)width/height;
          gl.glViewport(0,0,width,height);
          gl.glMatrixMode(GL_PROJECTION);
          gl.glLoadIdentity();
          // glu.gluPerspective(45.0,aspect,0.1,100.0);
          gl.glMatrixMode(GL_MODELVIEW);
          gl.glLoadIdentity();
      }
      @Override public void init(final GLAutoDrawable drawable) {
          GL2 gl=drawable.getGL().getGL2();
          glu=new GLU();
          glut=new GLUT();
          gl.glClearColor(0.0f,0.0f,0.0f,0.0f);
          gl.glClearDepth(1.0f);
          gl.glEnable(GL_DEPTH_TEST);
          gl.glDepthFunc(GL_LEQUAL);
          gl.glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
          gl.glShadeModel(GL_SMOOTH);
          for(int i=0;i&lt;nVbos;i++)
              numberOFVertices[i]=createAndFillVertexBuffer(drawable.getGL().getGL2(),MyDataObject.pieces[i],i);
      }
      @Override public void display(GLAutoDrawable drawable) {
          update();
          if(doTimeReporting)
              startTimeReporting();
          GL2 gl=drawable.getGL().getGL2();
          gl.glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
          gl.glLoadIdentity();
          gl.glRotated(angle,0,1,0);
          gl.glColor3d(1,1,1);
          for(int i=0;i&lt;nVbos;i++)
              renderPiece(drawable,i);
          if(doTimeReporting)
              endTimeReporting();
      }
      @Override public void dispose(GLAutoDrawable drawable) {}
      final GLAutoDrawable drawable;
      double angle;
      int nVbos;
      int[] vertexBufferIndices;
      int[] numberOFVertices;
      Random random=new Random();
      final int reportPeriod=100;
      boolean doTimeReporting=true;
      long t0,t0Frame,t0Display;
      int frame;
      Histogram hRender=new Histogram(10,0,10),hDisplay=new Histogram(10,0,100);
      int fps=defaultFps;
      protected GLU glu;
      protected GLUT glut;
      protected static String TITLE="JOGL 2.0 Setup (GLJPanel)";
      protected static final int displayWidth=1024;
      protected static final int displayHeight=1024;
      protected static final int defaultFps=60;
  }
  </code></pre>