Home | History | Annotate | Download | only in worker
      1 /*
      2  * Copyright (C) 2013 Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.google.caliper.worker;
     17 
     18 import com.google.common.base.Joiner;
     19 import com.google.common.base.Objects;
     20 import com.google.common.collect.ImmutableList;
     21 import com.google.common.collect.Interner;
     22 import com.google.common.collect.Interners;
     23 
     24 import java.util.Collection;
     25 import java.util.List;
     26 
     27 /**
     28  * Data about a particular allocation performed by a benchmark.  This tracks a human readable
     29  * description of the allocation (e.g. 'int[23]', 'java.lang.Integer', or 'java.util.ArrayList'),
     30  * the total size of the allocation in bytes and the location, which is a stringified stack trace of
     31  * the allocation.
     32  */
     33 final class Allocation {
     34   // While particular lists of STEs can have a lot of variety within a benchmark there don't tend
     35   // to be many individually unique STEs.  This can save a lot of memory.
     36   // Within a benchmark the code paths should be fairly uniform so it should be safe to just store
     37   // these forever.
     38   private static final Interner<StackTraceElement> steInterner = Interners.newWeakInterner();
     39   private static final Interner<String> descriptionInterner = Interners.newWeakInterner();
     40 
     41   /** Returns the sum of the {@link #size sizes} of the allocations. */
     42   static long getTotalSize(Collection<Allocation> allocations) {
     43     long totalSize = 0;
     44     for (Allocation allocation : allocations) {
     45       totalSize += allocation.size;
     46     }
     47     return totalSize;
     48   }
     49 
     50   private final String description;
     51   private final long size;
     52   private final ImmutableList<StackTraceElement> location;
     53 
     54   Allocation(String description, long size, List<StackTraceElement> location) {
     55     this.description = descriptionInterner.intern(description);
     56     this.size = size;
     57     ImmutableList.Builder<StackTraceElement> locationBuilder = ImmutableList.builder();
     58     for (StackTraceElement ste : location) {
     59       locationBuilder.add(steInterner.intern(ste));
     60     }
     61     this.location = locationBuilder.build();
     62   }
     63 
     64   @Override public boolean equals(Object obj) {
     65     if (obj instanceof Allocation) {
     66       Allocation other = (Allocation) obj;
     67       return other.description.equals(description)
     68           && other.size == size
     69           && other.location.equals(location);
     70 
     71     }
     72     return false;
     73   }
     74 
     75   public String getDescription() {
     76     return description;
     77   }
     78 
     79   public long getSize() {
     80     return size;
     81   }
     82 
     83   @Override public int hashCode() {
     84     return Objects.hashCode(description, size, location);
     85   }
     86 
     87   @Override public String toString() {
     88     StringBuilder builder = new StringBuilder();
     89     builder.append(description).append(" (").append(size).append(" bytes)\n\tat ");
     90     Joiner.on("\n\tat ").appendTo(builder, location);
     91     return builder.toString();
     92   }
     93 }