private float estimateSearchParams(SearchParamsBase searchParams) {
		int nn = 1;
		int SAMPLE_COUNT = 1000;

		assert (bestIndex != null);

		float speedup = 0;

		int samples = Math.min(data.length / 10, SAMPLE_COUNT);

		if (samples > 0) {
			double[][] testDataset = Utils.randomSample(data, samples, false);
			int[][] gtMatches = new int[testDataset.length][1];
			StopWatch timer = new StopWatch();
			int repeats = 0;
			timer.reset();
			while (timer.getTime() / 1000.0f < 0.2) {
				repeats++;
				timer.start();
				// computeGroundTruth(data, testDataset, gtMatches, 1, metric);
				timer.stop();
			}
			float linear = timer.getTime() / 1000.0f / repeats;
			int[] checks = new int[1];
			float searchTime;
			float cbIndex;
			if (bestIndex.getType() == IndexBase.IndexFLANN.KMEANS) {
				IndexKMeans kmeans = (IndexKMeans) bestIndex;
				float bestSearchTime = -1;
				float bestCbIndex = -1;
				int bestChecks = -1;
				for (cbIndex = 0; cbIndex < 1.1f; cbIndex += 0.2f) {
					kmeans.setCbIndex(cbIndex);
					IndexTesting testing = new IndexTesting();
					searchTime = testing.testIndexPrecision(kmeans, data,
							testDataset, gtMatches, targetPrecision, checks,
							metric, nn, 1);
					if (searchTime < bestSearchTime || bestSearchTime == -1) {
						bestSearchTime = searchTime;
						bestCbIndex = cbIndex;
						bestChecks = checks[0];
					}
				}
				searchTime = bestSearchTime;
				cbIndex = bestCbIndex;
				checks[0] = bestChecks;
				kmeans.setCbIndex(cbIndex);
				bestSearchParams.cbIndex = cbIndex;
			} else {
				IndexTesting testing = new IndexTesting();
				searchTime = testing.testIndexPrecision(bestIndex, data,
						testDataset, gtMatches, targetPrecision, checks,
						metric, nn, 1);
			}

			searchParams.checks = checks[0];
			speedup = linear / searchTime;
		}

		return speedup;
	}