public void runExtreme()

in Extremem/src/main/java/com/amazon/corretto/benchmark/extremem/CustomerThread.java [83:309]


  public void runExtreme() {
    while (true) {
      // If the simulation will have ended before we wake up, don't
      // even bother to sleep.
      if (next_release_time.compare(end_simulation_time) >= 0)
        break;

      AbsoluteTime now = next_release_time.sleep(this);
      Customer customer = all_customers.selectRandomCustomer(this);
      now.garbageFootprint(this);

      // In an earlier implementation, termination of the thread was
      // determined by comparing next_release_time against
      // end_simulation_time. In the case that the thread falls
      // hopelessly behind schedule, the thread takes "forever" to
      // terminate.
      if (now.compare(end_simulation_time) >= 0)
        break;

      Trace.msg(4, "CustomerThread ", label,
                ", random customer: ", customer.name(),
                ", id: ", Long.toString(customer.id()));

      // keywords, all, any are all treated as Ephemeral.
      String[] keywords = randomKeywords(config.KeywordSearchCount());
      Product[] all = all_products.lookupProductsMatchingAll(this, keywords);
      Product[] any = all_products.lookupProductsMatchingAny(this, keywords);
      
      int all_count = all.length;
      int any_count = any.length;

      if (Trace.enabled(3)) {
        for (int i = 0; i < keywords.length; i++)
          Trace.msg(4, "CustomerThread ", label,
                    " looking for keyword: ", keywords[i]);
        for (int i = 0; i < all.length; i++)
          Trace.msg(4, "CustomerThread ", label,
                    " matched all: ", all[i].name());
        for (int i = 0; i < any.length; i++)
          Trace.msg(4, "CustomerThread ", label,
                    " matched any: ", any[i].name());
      }

      // keywords array is now garbage
      Util.abandonEphemeralReferenceArray(this, keywords.length);

      Product[] scrutinize_list, garbage_list;
      if (all_count > 0) {
        scrutinize_list = all;
        garbage_list = any;
      } else {
        scrutinize_list = any;
        garbage_list = all;
      }
      all = any = null;
      // garbage_list is now garbage
      Util.abandonEphemeralReferenceArray(this, garbage_list.length);
      
      int candidate_cnt = scrutinize_list.length;
      // saved4laters is Ephemeral
      Product[] saved4laters = (
        customer.getAllSavedForLater(this, LifeSpan.Ephemeral));
      
      int saved_count = saved4laters.length;
      Product[] candidates;
      if (saved_count > 0) {
        int i;
        candidates = new Product[candidate_cnt + saved_count];
        Util.ephemeralReferenceArray(this, candidate_cnt + saved_count);
        for (i = 0; i < candidate_cnt; i++) 
          candidates[i] = scrutinize_list[i];
        for (int j = 0; j < saved_count; j++)
          candidates[i++] = saved4laters[j];
        candidate_cnt += saved_count;
        // scrutinize_list is now garbage.
        Util.abandonEphemeralReferenceArray(this, scrutinize_list.length);
      } else
        candidates = scrutinize_list;
      // saved4laters is now garbage.
      Util.abandonEphemeralReferenceArray(this, saved_count);
      
      // candidate_cnt represents length of candidates array.
      if (candidate_cnt > 0) {
        SalesTransaction[] prospects = new SalesTransaction[candidate_cnt];
        Util.referenceArray(this, LifeSpan.TransientShort, candidate_cnt);
        
        for (int i = 0; i < candidate_cnt; i++)
          prospects[i] = new SalesTransaction(this, LifeSpan.TransientShort,
                                              config, candidates[i],
                                              customer);
        // candidates is now garbage.
        Util.abandonEphemeralReferenceArray(this, prospects.length);

        String[] selectors = randomKeywords(config.SelectionCriteriaCount());
        Util.convertStringArray(this, LifeSpan.TransientShort,
                                selectors.length);

        AbsoluteTime end_think = (
          next_release_time.addRelative(this, config.CustomerThinkTime()));
        end_think.changeLifeSpan(this, LifeSpan.TransientShort);
        history.logPrepareToThink(this, next_release_time,
                                  all_count, any_count, saved_count);
        end_think.sleep(this);
        end_think.garbageFootprint(this);

        Trace.msg(4, "Customer Thread ", label,
                  ", woke from thinking @ ", end_think.toString(this),
                  ", candidates:");
        if (Trace.enabled(3)) {
          for (int i = 0; i < candidate_cnt; i++) {
            Trace.msg(4, " product id: ",
                      Long.toString(prospects[i].product().id()),
                      ", name: ", prospects[i].product().name());
          }
        }

        // rankings is ephemeral.
        float[] rankings = rankFuzzyMatches(selectors, prospects);
        int best_index = 0;
        float best_match = rankings [0];
        for (int i = 1; i < rankings.length; i++) {
          if (rankings [i] > best_match) {
            best_match = rankings [i];
            best_index = i;
          }
        }
        // Abandon rankings.
        Util.abandonEphemeralRSBArray(this,
                                      rankings.length, Util.SizeOfFloat);

        Trace.msg(4, "Customer Thread ", label, ", selected option ",
                  Integer.toString(best_index));

        SalesTransaction selected = prospects[best_index];
        // Other SalesTransactions and selection_criteria are now all garbage
        // (Some compilers/collectors may be better at discovering
        // this than others.)

        for (int i = 0; i < prospects.length; i++)
          if (i != best_index) prospects[i].garbageFootprint(this);
        // prospects is now garbage.
        Util.abandonReferenceArray(this, LifeSpan.TransientShort,
                                   prospects.length);
        // selectors is now garbage.
        Util.abandonStringArray(this,
                                LifeSpan.TransientShort, selectors.length);

        float coin = this.randomFloat();
        switch (interpretCoinToss(coin)) {

          case BuyProduct:
            Trace.msg(4, "Customer Thread ", label, ", chose buy");
            sales_queue.enqueue(selected);
            selected.changeLifeSpan(this, LifeSpan.TransientIntermediate);
            // Garbage collection of the selected object is the
            // "responsibility" of the ServerThread.  After the
            // ServerThread transacts a sale, it marks the selected
            // SalesTransaction object as garbage.  This is the same
            // process used even if the associated customer or product
            // becomes decommissioned before the sale is transacted.
            history.logPurchase(this, end_think);
            break;

          case SaveProductForLater:
            Trace.msg(4,
                      "Customer Thread ", label, ", chose save for later");
            Customer c = selected.customer();
            Product p = selected.product();
            // selected is now garbage.
            selected.garbageFootprint(this);

            AbsoluteTime expiration = AbsoluteTime.now(this);
            expiration.garbageFootprint(this);
            expiration = expiration.addRelative(this,
                                                config.BrowsingExpiration());
            BrowsingHistory h = new BrowsingHistory(this,
                                                    LifeSpan.
                                                    TransientLingering,
                                                    c, p, expiration,
                                                    browsing_queue);
            expiration.garbageFootprint(this);
            all_customers.addSaveForLater(c, this, h);
            browsing_queue.enqueue(h);
            // Garbage collection of the h BrowsingHistory object is
            // the "responsibility" of the ServerThread.  After the
            // ServerThread expires h because its expiration time has
            // been reached, it object h is marked as eligible for
            // garbage collection.  In the rare case that customer c
            // is decommissioned before BrowsingHistory h's expiration
            // has been reached, the memory belong to h will be marked
            // as eligible for garbage collection by the
            // Customer.prepareForDemise() method that executes when
            // the customer is decommissioned.
            history.log4Later(this, end_think);
            break;
            
          case AbandonProduct:
            // selected is garbage.
            selected.garbageFootprint(this);

            Trace.msg(4, "Customer Thread ", label, ", chose abandon");
            history.logAbandonment(this, end_think);
        }
      } else {
        // candidates, known to have length 0, is now garbage.
        Util.abandonEphemeralReferenceArray(this, 0);
        
        // else, search came up empty.  wait for next period.
        Trace.msg(4, "Customer Thread ", label, " matched no customers");
        history.logNoChoice(this, next_release_time);
      }
      next_release_time.garbageFootprint(this);
      next_release_time = next_release_time.addRelative(this,
                                                        config.
                                                        CustomerPeriod());
    }
    Trace.msg(2, "Customer thread ", label, " terminating.  Time is up.");

    // We accumulate accumulator even if reporting individual threads
    accumulator.accumulate(history);
    if (config.ReportIndividualThreads())
      this.report(this);
    else {
      alloc_accumulator.foldInto(memoryLog());
      garbage_accumulator.foldInto(garbageLog());
    }
  }