Changeset 212c87f


Ignore:
Timestamp:
Jan 9, 2011 1:02:17 AM (9 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
9a63be8
Parents:
6cfb2ba
Message:
  • DataHelper?: Speed up and annotate sortStructures()
  • RouterInfo?:
    • Don't cache byteified data by default, to save ~1.5 MB
    • Don't create empty peers Set, to save ~100KB
Location:
core/java/src/net/i2p/data
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • core/java/src/net/i2p/data/DataHelper.java

    r6cfb2ba r212c87f  
    3232import java.util.Collection;
    3333import java.util.Collections;
     34import java.util.Comparator;
    3435import java.util.Date;
    3536import java.util.Iterator;
     
    10411042
    10421043    /**
    1043      *  Sort based on the Hash of the DataStructure
     1044     *  Sort based on the Hash of the DataStructure.
    10441045     *  Warning - relatively slow.
    1045      *  Only used by RouterInfo
    1046      *  Why? Just because it has to be consistent so signing will work?
     1046     *  WARNING - this sort order must be consistent network-wide, so while the order is arbitrary,
     1047     *  it cannot be changed.
     1048     *  Why? Just because it has to be consistent so signing will work.
    10471049     *  How to spec as returning the same type as the param?
     1050     *  DEPRECATED - Only used by RouterInfo.
    10481051     */
    10491052    public static List<? extends DataStructure> sortStructures(Collection<? extends DataStructure> dataStructures) {
    10501053        if (dataStructures == null) return Collections.EMPTY_LIST;
    1051         ArrayList<DataStructure> rv = new ArrayList(dataStructures.size());
    1052         TreeMap<String, DataStructure> tm = new TreeMap();
    1053         for (DataStructure struct : dataStructures) {
    1054             tm.put(struct.calculateHash().toString(), struct);
    1055         }
    1056         for (DataStructure struct : tm.values()) {
    1057             rv.add(struct);
    1058         }
     1054
     1055        // This used to use Hash.toString(), which is insane, since a change to toString()
     1056        // would break the whole network. Now use Hash.toBase64().
     1057        // Note that the Base64 sort order is NOT the same as the raw byte sort order,
     1058        // despite what you may read elsewhere.
     1059
     1060        //ArrayList<DataStructure> rv = new ArrayList(dataStructures.size());
     1061        //TreeMap<String, DataStructure> tm = new TreeMap();
     1062        //for (DataStructure struct : dataStructures) {
     1063        //    tm.put(struct.calculateHash().toString(), struct);
     1064        //}
     1065        //for (DataStructure struct : tm.values()) {
     1066        //    rv.add(struct);
     1067        //}
     1068        ArrayList<DataStructure> rv = new ArrayList(dataStructures);
     1069        Collections.sort(rv, new DataStructureComparator());
    10591070        return rv;
     1071    }
     1072
     1073    /**
     1074     * See sortStructures() comments.
     1075     * @since 0.8.3
     1076     */
     1077    private static class DataStructureComparator implements Comparator<DataStructure> {
     1078        public int compare(DataStructure l, DataStructure r) {
     1079            return l.calculateHash().toBase64().compareTo(r.calculateHash().toBase64());
     1080        }
    10601081    }
    10611082
  • core/java/src/net/i2p/data/RouterAddress.java

    r6cfb2ba r212c87f  
    132132    }
    133133   
    134     /** the style should be sufficient, for speed */
     134    /**
     135     * Just use style and hashCode for speed (expiration is always null).
     136     * If we add multiple addresses of the same style, this may need to be changed.
     137     */
    135138    @Override
    136139    public int hashCode() {
    137         return DataHelper.hashCode(_transportStyle);
     140        return DataHelper.hashCode(_transportStyle) ^ _cost;
    138141    }
    139142   
  • core/java/src/net/i2p/data/RouterInfo.java

    r6cfb2ba r212c87f  
    1515import java.io.OutputStream;
    1616import java.util.Collection;
     17import java.util.Collections;
    1718import java.util.Date;
    1819import java.util.HashSet;
     
    4041    private volatile long _published;
    4142    private final Set<RouterAddress> _addresses;
    42     private final Set<Hash> _peers;
     43    /** may be null to save memory, no longer final */
     44    private Set<Hash> _peers;
    4345    private /* FIXME final FIXME */ Properties _options;
    4446    private volatile boolean _validated;
     
    4850    private volatile int _hashCode;
    4951    private volatile boolean _hashCodeInitialized;
     52    /** should we cache the byte and string versions _byteified ? **/
     53    private boolean _shouldCache;
     54    /** maybe we should check if we are floodfill? */
     55    private static final boolean CACHE_ALL = Runtime.getRuntime().maxMemory() > 128*1024*1024l;
    5056
    5157    public static final String PROP_NETWORK_ID = "netId";
     
    5965    public RouterInfo() {
    6066        _addresses = new HashSet(2);
    61         _peers = new HashSet(0);
    6267        _options = new OrderedProperties();
    6368    }
     
    7176        setOptions(old.getOptions());
    7277        setSignature(old.getSignature());
     78        // copy over _byteified?
    7379    }
    7480
     
    106112        _identity = ident;
    107113        resetCache();
     114        // We only want to cache the bytes for our own RI, which is frequently written.
     115        // To cache for all RIs doubles the RI memory usage.
     116        // setIdentity() is only called when we are creating our own RI.
     117        // Otherwise, the data is populated with readBytes().
     118        _shouldCache = true;
    108119    }
    109120
     
    160171     */
    161172    public Set<Hash> getPeers() {
     173        if (_peers == null)
     174            return Collections.EMPTY_SET;
    162175        return _peers;
    163176    }
     
    170183     */
    171184    public void setPeers(Set<Hash> peers) {
     185        if (peers == null || peers.isEmpty()) {
     186            _peers = null;
     187            return;
     188        }
     189        if (_peers == null)
     190            _peers = new HashSet(2);
    172191        synchronized (_peers) {
    173192            _peers.clear();
    174             if (peers != null) _peers.addAll(peers);
     193            _peers.addAll(peers);
    175194        }
    176195        resetCache();
     
    224243        if (_identity == null) throw new DataFormatException("Router identity isn't set? wtf!");
    225244        if (_addresses == null) throw new DataFormatException("Router addressess isn't set? wtf!");
    226         if (_peers == null) throw new DataFormatException("Router peers isn't set? wtf!");
    227245        if (_options == null) throw new DataFormatException("Router options isn't set? wtf!");
    228246
     
    240258                Collection<RouterAddress> addresses = _addresses;
    241259                if (sz > 1)
     260                    // WARNING this sort algorithm cannot be changed, as it must be consistent
     261                    // network-wide. The signature is not checked at readin time, but only
     262                    // later, and the addresses are stored in a Set, not a List.
    242263                    addresses = (Collection<RouterAddress>) DataHelper.sortStructures(addresses);
    243264                for (RouterAddress addr : addresses) {
     
    249270            //         method of trusted links, which isn't implemented in the router
    250271            //         at the moment, and may not be later.
    251             // fixme to reduce objects - allow _peers == null
    252             int psz = _peers.size();
     272            int psz = _peers == null ? 0 : _peers.size();
    253273            DataHelper.writeLong(out, 1, psz);
    254274            if (psz > 0) {
    255275                Collection<Hash> peers = _peers;
    256276                if (psz > 1)
     277                    // WARNING this sort algorithm cannot be changed, as it must be consistent
     278                    // network-wide. The signature is not checked at readin time, but only
     279                    // later, and the hashes are stored in a Set, not a List.
    257280                    peers = (Collection<Hash>) DataHelper.sortStructures(peers);
    258281                for (Hash peerHash : peers) {
     
    267290        long after = Clock.getInstance().now();
    268291        _log.debug("getBytes()  took " + (after - before) + "ms");
    269         _byteified = data;
     292        if (CACHE_ALL || _shouldCache)
     293            _byteified = data;
    270294        return data;
    271295    }
     
    467491        }
    468492        int numPeers = (int) DataHelper.readLong(in, 1);
    469         for (int i = 0; i < numPeers; i++) {
    470             Hash peerIdentityHash = new Hash();
    471             peerIdentityHash.readBytes(in);
    472             _peers.add(peerIdentityHash);
     493        if (numPeers == 0) {
     494            _peers = null;
     495        } else {
     496            _peers = new HashSet(numPeers);
     497            for (int i = 0; i < numPeers; i++) {
     498                Hash peerIdentityHash = new Hash();
     499                peerIdentityHash.readBytes(in);
     500                _peers.add(peerIdentityHash);
     501            }
    473502        }
    474503        _options = DataHelper.readProperties(in);
     
    505534               && DataHelper.eq(_addresses, info.getAddresses())
    506535               && DataHelper.eq(_options, info.getOptions())
    507                && DataHelper.eq(_peers, info.getPeers());
     536               && DataHelper.eq(getPeers(), info.getPeers());
    508537    }
    509538   
     
    531560            buf.append("\n\t\tAddress: ").append(addr);
    532561        }
    533         Set peers = _peers; // getPeers()
     562        Set peers = getPeers();
    534563        buf.append("\n\tPeers: #: ").append(peers.size());
    535564        for (Iterator iter = peers.iterator(); iter.hasNext();) {
Note: See TracChangeset for help on using the changeset viewer.