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)); }
/** * 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); } }