public static int GetNext() {
		// Sequential search
		ThreadLocalRandom tlr = ThreadLocalRandom.current();
		long rank = tlr.nextLong(_obj_rank_min, _obj_rank_max + 1);

		// Return the upper bound (, which is smaller than the lower bound)
		if (_GETNEXT_METHOD == 'U') {
			// A sequential search from the end. Won't be too bad. It might be better than the
			// binary search since most of the random numbers will fall in the
			// buckets toward the end.
			int _ornrs_size = _ornrs.size();
			double num_reqs = -1.0;
			for (int i = _ornrs_size - 1; i >= 0; i --) {
				if (_ornrs.get(i).obj_rank <= rank) {
					if (i == _ornrs_size - 1) {
						num_reqs = _ornrs.get(i).num_reqs;
					} else {
						num_reqs = _ornrs.get(i+1).num_reqs;
					}
					//Cons.P(String.format("%d %f %d", rank, num_reqs, Math.round(num_reqs)));

					// Cast to float to call int round(float a);
					return Math.round((float) num_reqs);
				}
			}
		}
		// Interpolate between lower and upper bound
		else if (_GETNEXT_METHOD == 'I') {
			int _ornrs_size = _ornrs.size();
			double num_reqs = -1.0;
			for (int i = _ornrs_size - 1; i >= 0; i --) {
				if (_ornrs.get(i).obj_rank <= rank) {
					if (i == _ornrs_size - 1) {
						num_reqs = _ornrs.get(i).num_reqs;
					} else {
						// rank is always != _ornrs[i+1].obj_rank, since the same rank is
						// filtered out when loading the file
						num_reqs = (_ornrs.get(i+1).num_reqs - _ornrs.get(i).num_reqs)
							* (rank - _ornrs.get(i).obj_rank) / (_ornrs.get(i+1).obj_rank - _ornrs.get(i).obj_rank)
							+ _ornrs.get(i).num_reqs;
						//Cons.P(String.format("rank=%d i=%d num_reqs=%f %d | %d %d %f %f"
						//			, rank, i, num_reqs, Math.round(num_reqs)
						//			, _ornrs.get(i).obj_rank, _ornrs.get(i+1).obj_rank
						//			, _ornrs.get(i).num_reqs, _ornrs.get(i+1).num_reqs));
					}
					return Math.round((float) num_reqs);
				}
			}
		}

		throw new RuntimeException(
				String.format("Unexpected rank=%d _obj_rank_min=%d _obj_rank_max=%d",
					rank, _obj_rank_min, _obj_rank_max));
	}
Example #2
0
  /**
   * Indicate that a non-root node is most recently used. Root node is not managed in usage list and
   * cannot be evicted. Caller must hold any latch on node. Latch is never released by this method,
   * even if an exception is thrown.
   */
  void used(final Node node, final ThreadLocalRandom rnd) {
    // Moving the node in the usage list is expensive for several reasons. First is the
    // rapid rate at which shared memory is written to. This creates memory access
    // contention between CPU cores. Second is the garbage collector. The G1 collector in
    // particular appears to be very sensitive to old generation objects being shuffled
    // around too much. Finally, latch acquisition itself can cause contention. If the node
    // is popular, it will get more chances to be identified as most recently used. This
    // strategy works well enough because cache eviction is always a best-guess approach.

    if ((rnd.nextLong() & mUsedRate) == 0 && tryAcquireExclusive()) {
      doUsed(node);
    }
  }