From e3a3dccdfcb0f7390f8bf30ec1af0f9d9fb69496 Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Sun, 3 Feb 2013 13:11:11 +0100 Subject: [PATCH] Use SHA-256 hashes for fingerprinting. The fingerprint for my Sone was a string that occupied more than 3 MB in memory alone. That is completely unnecessary. --- .../java/net/pterodactylus/sone/data/Album.java | 30 +++++++++-------- .../java/net/pterodactylus/sone/data/Image.java | 17 ++++++---- .../java/net/pterodactylus/sone/data/Profile.java | 31 ++++++++++-------- .../java/net/pterodactylus/sone/data/Sone.java | 38 ++++++++++++---------- 4 files changed, 63 insertions(+), 53 deletions(-) diff --git a/src/main/java/net/pterodactylus/sone/data/Album.java b/src/main/java/net/pterodactylus/sone/data/Album.java index c1ae267..7103871 100644 --- a/src/main/java/net/pterodactylus/sone/data/Album.java +++ b/src/main/java/net/pterodactylus/sone/data/Album.java @@ -32,6 +32,8 @@ import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.base.Predicates; import com.google.common.collect.Collections2; +import com.google.common.hash.Hasher; +import com.google.common.hash.Hashing; /** * Container for images that can also contain nested {@link Album}s. @@ -436,33 +438,33 @@ public class Album implements Fingerprintable { */ @Override public String getFingerprint() { - StringBuilder fingerprint = new StringBuilder(); - fingerprint.append("Album("); - fingerprint.append("ID(").append(id).append(')'); - fingerprint.append("Title(").append(title).append(')'); - fingerprint.append("Description(").append(description).append(')'); + Hasher hash = Hashing.sha256().newHasher(); + hash.putString("Album("); + hash.putString("ID(").putString(id).putString(")"); + hash.putString("Title(").putString(title).putString(")"); + hash.putString("Description(").putString(description).putString(")"); if (albumImage != null) { - fingerprint.append("AlbumImage(").append(albumImage).append(')'); + hash.putString("AlbumImage(").putString(albumImage).putString(")"); } /* add nested albums. */ - fingerprint.append("Albums("); + hash.putString("Albums("); for (Album album : albums) { - fingerprint.append(album.getFingerprint()); + hash.putString(album.getFingerprint()); } - fingerprint.append(')'); + hash.putString(")"); /* add images. */ - fingerprint.append("Images("); + hash.putString("Images("); for (Image image : getImages()) { if (image.isInserted()) { - fingerprint.append(image.getFingerprint()); + hash.putString(image.getFingerprint()); } } - fingerprint.append(')'); + hash.putString(")"); - fingerprint.append(')'); - return fingerprint.toString(); + hash.putString(")"); + return hash.hash().toString(); } // diff --git a/src/main/java/net/pterodactylus/sone/data/Image.java b/src/main/java/net/pterodactylus/sone/data/Image.java index e50405f..952d540 100644 --- a/src/main/java/net/pterodactylus/sone/data/Image.java +++ b/src/main/java/net/pterodactylus/sone/data/Image.java @@ -23,6 +23,9 @@ import static com.google.common.base.Preconditions.checkState; import java.util.UUID; +import com.google.common.hash.Hasher; +import com.google.common.hash.Hashing; + /** * Container for image metadata. * @@ -296,13 +299,13 @@ public class Image implements Fingerprintable { */ @Override public String getFingerprint() { - StringBuilder fingerprint = new StringBuilder(); - fingerprint.append("Image("); - fingerprint.append("ID(").append(id).append(')'); - fingerprint.append("Title(").append(title).append(')'); - fingerprint.append("Description(").append(description).append(')'); - fingerprint.append(')'); - return fingerprint.toString(); + Hasher hash = Hashing.sha256().newHasher(); + hash.putString("Image("); + hash.putString("ID(").putString(id).putString(")"); + hash.putString("Title(").putString(title).putString(")"); + hash.putString("Description(").putString(description).putString(")"); + hash.putString(")"); + return hash.hash().toString(); } // diff --git a/src/main/java/net/pterodactylus/sone/data/Profile.java b/src/main/java/net/pterodactylus/sone/data/Profile.java index 57b54c6..5a4fde0 100644 --- a/src/main/java/net/pterodactylus/sone/data/Profile.java +++ b/src/main/java/net/pterodactylus/sone/data/Profile.java @@ -26,6 +26,9 @@ import java.util.Collections; import java.util.List; import java.util.UUID; +import com.google.common.hash.Hasher; +import com.google.common.hash.Hashing; + /** * A profile stores personal information about a {@link Sone}. All information * is optional and can be {@code null}. @@ -401,37 +404,37 @@ public class Profile implements Fingerprintable { */ @Override public String getFingerprint() { - StringBuilder fingerprint = new StringBuilder(); - fingerprint.append("Profile("); + Hasher hash = Hashing.sha256().newHasher(); + hash.putString("Profile("); if (firstName != null) { - fingerprint.append("FirstName(").append(firstName).append(')'); + hash.putString("FirstName(").putString(firstName).putString(")"); } if (middleName != null) { - fingerprint.append("MiddleName(").append(middleName).append(')'); + hash.putString("MiddleName(").putString(middleName).putString(")"); } if (lastName != null) { - fingerprint.append("LastName(").append(lastName).append(')'); + hash.putString("LastName(").putString(lastName).putString(")"); } if (birthDay != null) { - fingerprint.append("BirthDay(").append(birthDay).append(')'); + hash.putString("BirthDay(").putInt(birthDay).putString(")"); } if (birthMonth != null) { - fingerprint.append("BirthMonth(").append(birthMonth).append(')'); + hash.putString("BirthMonth(").putInt(birthMonth).putString(")"); } if (birthYear != null) { - fingerprint.append("BirthYear(").append(birthYear).append(')'); + hash.putString("BirthYear(").putInt(birthYear).putString(")"); } if (avatar != null) { - fingerprint.append("Avatar(").append(avatar).append(')'); + hash.putString("Avatar(").putString(avatar).putString(")"); } - fingerprint.append("ContactInformation("); + hash.putString("ContactInformation("); for (Field field : fields) { - fingerprint.append(field.getName()).append('(').append(field.getValue()).append(')'); + hash.putString(field.getName()).putString("(").putString(field.getValue()).putString(")"); } - fingerprint.append(")"); - fingerprint.append(")"); + hash.putString(")"); + hash.putString(")"); - return fingerprint.toString(); + return hash.hash().toString(); } /** diff --git a/src/main/java/net/pterodactylus/sone/data/Sone.java b/src/main/java/net/pterodactylus/sone/data/Sone.java index a609982..a3e872b 100644 --- a/src/main/java/net/pterodactylus/sone/data/Sone.java +++ b/src/main/java/net/pterodactylus/sone/data/Sone.java @@ -38,6 +38,8 @@ import net.pterodactylus.sone.template.SoneAccessor; import net.pterodactylus.util.logging.Logging; import com.google.common.base.Predicate; +import com.google.common.hash.Hasher; +import com.google.common.hash.Hashing; import freenet.keys.FreenetURI; @@ -915,46 +917,46 @@ public class Sone implements Fingerprintable, Comparable { */ @Override public synchronized String getFingerprint() { - StringBuilder fingerprint = new StringBuilder(); - fingerprint.append(profile.getFingerprint()); + Hasher hash = Hashing.sha256().newHasher(); + hash.putString(profile.getFingerprint()); - fingerprint.append("Posts("); + hash.putString("Posts("); for (Post post : getPosts()) { - fingerprint.append("Post(").append(post.getId()).append(')'); + hash.putString("Post(").putString(post.getId()).putString(")"); } - fingerprint.append(")"); + hash.putString(")"); List replies = new ArrayList(getReplies()); Collections.sort(replies, Reply.TIME_COMPARATOR); - fingerprint.append("Replies("); + hash.putString("Replies("); for (PostReply reply : replies) { - fingerprint.append("Reply(").append(reply.getId()).append(')'); + hash.putString("Reply(").putString(reply.getId()).putString(")"); } - fingerprint.append(')'); + hash.putString(")"); List likedPostIds = new ArrayList(getLikedPostIds()); Collections.sort(likedPostIds); - fingerprint.append("LikedPosts("); + hash.putString("LikedPosts("); for (String likedPostId : likedPostIds) { - fingerprint.append("Post(").append(likedPostId).append(')'); + hash.putString("Post(").putString(likedPostId).putString(")"); } - fingerprint.append(')'); + hash.putString(")"); List likedReplyIds = new ArrayList(getLikedReplyIds()); Collections.sort(likedReplyIds); - fingerprint.append("LikedReplies("); + hash.putString("LikedReplies("); for (String likedReplyId : likedReplyIds) { - fingerprint.append("Reply(").append(likedReplyId).append(')'); + hash.putString("Reply(").putString(likedReplyId).putString(")"); } - fingerprint.append(')'); + hash.putString(")"); - fingerprint.append("Albums("); + hash.putString("Albums("); for (Album album : albums) { - fingerprint.append(album.getFingerprint()); + hash.putString(album.getFingerprint()); } - fingerprint.append(')'); + hash.putString(")"); - return fingerprint.toString(); + return hash.hash().toString(); } // -- 2.7.4