public static void Bench() {
    Session session = null;
    FullTextSession fullTextSession = null;
    SessionFactory sessionFactory = null;
    try {

      sessionFactory =
          new Configuration().configure(hibernateConfigurationFile).buildSessionFactory();

      session = sessionFactory.openSession();
      session.beginTransaction();
      fullTextSession = Search.getFullTextSession(session);

      long gridTotalDuration = 0;
      long spatialTotalDuration = 0;
      long doubleRangeTotalDuration = 0;
      long distanceDoubleRangeTotalDuration = 0;

      long gridDocsFetched = 0;
      long spatialDocsFetched = 0;
      long doubleRangeDocsFetched = 0;
      long distanceDoubleRangeDocsFetched = 0;

      org.apache.lucene.search.Query luceneQuery;
      long startTime, endTime, duration;
      FullTextQuery hibQuery;
      List gridResults, rangeResults;
      final QueryBuilder queryBuilder =
          fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(POI.class).get();
      org.apache.lucene.search.Query query;
      final Integer iterations = 2000;
      final Integer warmUp = 50;
      Random random = new Random(42);

      for (int i = 0; i < iterations; i++) {
        Point center = Point.fromDegrees(random.nextDouble() * 2 + 44, random.nextDouble() * 2 + 3);
        double radius = 25.0d;
        Rectangle boundingBox = Rectangle.fromBoundingCircle(center, radius);

        query =
            queryBuilder
                .bool()
                .must(
                    queryBuilder
                        .range()
                        .onField("latitude")
                        .from(boundingBox.getLowerLeft().getLatitude())
                        .to(boundingBox.getUpperRight().getLatitude())
                        .createQuery())
                .must(
                    queryBuilder
                        .range()
                        .onField("longitude")
                        .from(boundingBox.getLowerLeft().getLongitude())
                        .to(boundingBox.getUpperRight().getLongitude())
                        .createQuery())
                .createQuery();
        hibQuery = fullTextSession.createFullTextQuery(query, POI.class);
        hibQuery.setProjection("id", "name");
        startTime = System.nanoTime();
        try {
          doubleRangeDocsFetched += hibQuery.getResultSize();
        } finally {
          endTime = System.nanoTime();
        }
        duration = endTime - startTime;
        if (i > warmUp) {
          doubleRangeTotalDuration += duration;
        }
        session.clear();

        query =
            queryBuilder
                .bool()
                .must(
                    queryBuilder
                        .range()
                        .onField("latitude")
                        .from(boundingBox.getLowerLeft().getLatitude())
                        .to(boundingBox.getUpperRight().getLatitude())
                        .createQuery())
                .must(
                    queryBuilder
                        .range()
                        .onField("longitude")
                        .from(boundingBox.getLowerLeft().getLongitude())
                        .to(boundingBox.getUpperRight().getLongitude())
                        .createQuery())
                .createQuery();
        org.apache.lucene.search.Query filteredQuery =
            new ConstantScoreQuery(
                SpatialQueryBuilderFromPoint.buildDistanceFilter(
                    new QueryWrapperFilter(query), center, radius, "location"));
        hibQuery = fullTextSession.createFullTextQuery(filteredQuery, POI.class);
        hibQuery.setProjection("id", "name");
        startTime = System.nanoTime();
        try {
          distanceDoubleRangeDocsFetched += hibQuery.getResultSize();
        } finally {
          endTime = System.nanoTime();
        }
        duration = endTime - startTime;
        if (i > warmUp) {
          distanceDoubleRangeTotalDuration += duration;
        }
        rangeResults = hibQuery.list();
        session.clear();

        luceneQuery = SpatialQueryBuilderFromPoint.buildGridQuery(center, radius, "location");
        hibQuery = fullTextSession.createFullTextQuery(luceneQuery, POI.class);
        hibQuery.setProjection("id", "name");
        startTime = System.nanoTime();

        try {
          gridDocsFetched += hibQuery.getResultSize();
        } finally {
          endTime = System.nanoTime();
        }
        duration = endTime - startTime;
        if (i > warmUp) {
          gridTotalDuration += duration;
        }
        session.clear();

        luceneQuery =
            SpatialQueryBuilderFromPoint.buildSpatialQueryByGrid(center, radius, "location");
        hibQuery = fullTextSession.createFullTextQuery(luceneQuery, POI.class);
        hibQuery.setProjection("id", "name");
        startTime = System.nanoTime();

        try {
          spatialDocsFetched += hibQuery.getResultSize();
        } finally {
          endTime = System.nanoTime();
        }
        duration = endTime - startTime;
        if (i > warmUp) {
          spatialTotalDuration += duration;
        }
        gridResults = hibQuery.list();
        session.clear();

        if (rangeResults.size() != gridResults.size()) {
          luceneQuery = SpatialQueryBuilderFromPoint.buildDistanceQuery(center, radius, "location");
          hibQuery = fullTextSession.createFullTextQuery(luceneQuery, POI.class);
          hibQuery.setProjection("id", "name");

          System.out.println(
              ">>>>> Different numbers of documents fetched for point ("
                  + Double.toString(center.getLatitude())
                  + ","
                  + Double.toString(center.getLongitude())
                  + ") and radius "
                  + Double.toString(radius));
          System.out.println("Range results : " + rangeResults);
          System.out.println("Grid results : " + gridResults);
          System.out.println("Pure distance results : " + hibQuery.getResultSize());

          List<Integer> rangeIds = new ArrayList<Integer>();
          for (int index = 0; index < rangeResults.size(); index++) {
            rangeIds.add((Integer) ((Object[]) rangeResults.get(index))[0]);
          }
          List<Integer> gridIds = new ArrayList<Integer>();
          for (int index = 0; index < gridResults.size(); index++) {
            gridIds.add((Integer) ((Object[]) gridResults.get(index))[0]);
          }

          rangeIds.removeAll(gridIds);

          System.out.println("Missing Ids : " + rangeIds);
        }
      }
      session.getTransaction().commit();
      session.close();
      sessionFactory.close();

      System.out.println(
          "Mean time with Grid : "
              + Double.toString(
                  (double) gridTotalDuration * Math.pow(10, -6) / (iterations - warmUp))
              + " ms. Average number of docs  fetched : "
              + Double.toString(gridDocsFetched / ((iterations - warmUp) * 1.0d)));
      System.out.println(
          "Mean time with Grid + Distance filter : "
              + Double.toString(
                  (double) spatialTotalDuration * Math.pow(10, -6) / (iterations - warmUp))
              + " ms. Average number of docs  fetched : "
              + Double.toString(spatialDocsFetched / ((iterations - warmUp) * 1.0d)));
      System.out.println(
          "Mean time with DoubleRange : "
              + Double.toString(
                  (double) doubleRangeTotalDuration * Math.pow(10, -6) / (iterations - warmUp))
              + " ms. Average number of docs  fetched : "
              + Double.toString(doubleRangeDocsFetched / ((iterations - warmUp) * 1.0d)));
      System.out.println(
          "Mean time with DoubleRange + Distance filter : "
              + Double.toString(
                  (double) distanceDoubleRangeTotalDuration
                      * Math.pow(10, -6)
                      / (iterations - warmUp))
              + " ms. Average number of docs  fetched : "
              + Double.toString(distanceDoubleRangeDocsFetched / ((iterations - warmUp) * 1.0d)));

    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (fullTextSession != null && fullTextSession.isOpen()) {
        Transaction transaction = fullTextSession.getTransaction();
        if (transaction != null && transaction.isActive()) {
          transaction.rollback();
        }
        fullTextSession.close();
      }
      if (sessionFactory != null && !sessionFactory.isClosed()) {
        sessionFactory.close();
      }
    }
  }