Last active
September 1, 2016 19:32
-
-
Save headius/59e19a3a4a45c63b06cc9876a8148e28 to your computer and use it in GitHub Desktop.
Memory improvement for #inspect, from jruby/jruby#4127
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/core/src/main/java/org/jruby/RubyBasicObject.java b/core/src/main/java/org/jruby/RubyBasicObject.java | |
index fc181c9..107146a 100644 | |
--- a/core/src/main/java/org/jruby/RubyBasicObject.java | |
+++ b/core/src/main/java/org/jruby/RubyBasicObject.java | |
@@ -69,6 +69,7 @@ import org.jruby.runtime.builtin.Variable; | |
import org.jruby.runtime.component.VariableEntry; | |
import org.jruby.runtime.marshal.CoreObjectType; | |
import org.jruby.util.ArraySupport; | |
+import org.jruby.util.ConvertBytes; | |
import org.jruby.util.IdUtil; | |
import org.jruby.util.TypeConverter; | |
import org.jruby.util.unsafe.UnsafeHolder; | |
@@ -78,6 +79,9 @@ import static org.jruby.runtime.invokedynamic.MethodNames.OP_EQUAL; | |
import static org.jruby.runtime.invokedynamic.MethodNames.OP_CMP; | |
import static org.jruby.runtime.invokedynamic.MethodNames.EQL; | |
import static org.jruby.runtime.invokedynamic.MethodNames.INSPECT; | |
+import static org.jruby.util.io.EncodingUtils.encStrBufCat; | |
+import static org.jruby.util.io.EncodingUtils.strBufCat; | |
+ | |
import org.jruby.runtime.ivars.VariableTableManager; | |
/** | |
@@ -1096,21 +1100,30 @@ public class RubyBasicObject implements Cloneable, IRubyObject, Serializable, Co | |
return to_s(); | |
} | |
+ private static final byte[] INSPECT_POUND_LT = "#<".getBytes(); | |
+ private static final byte[] INSPECT_COLON_ZERO_X = ":0x".getBytes(); | |
+ private static final byte[] INSPECT_SPACE_DOT_DOT_DOT_GT = " ...>".getBytes(); | |
+ private static final byte[] INSPECT_COMMA = ",".getBytes(); | |
+ private static final byte[] INSPECT_SPACE = " ".getBytes(); | |
+ private static final byte[] INSPECT_EQUALS = "=".getBytes(); | |
+ private static final byte[] INSPECT_GT = ">".getBytes(); | |
+ | |
public final IRubyObject hashyInspect() { | |
final Ruby runtime = getRuntime(); | |
- String cname = getMetaClass().getRealClass().getName(); | |
- StringBuilder part = new StringBuilder(2 + cname.length() + 3 + 8 + 1); // #<Object:0x5a1c0542> | |
- part.append("#<").append(cname).append(":0x"); | |
- part.append(Integer.toHexString(inspectHashCode())); | |
+ RubyString name = (RubyString) getMetaClass().getRealClass().name(); | |
+ RubyString part = RubyString.newStringLight(runtime, 2 + name.size() + 3 + 8 + 1); // #<Object:0x5a1c0542> | |
+ encStrBufCat(runtime, part, INSPECT_POUND_LT); | |
+ encStrBufCat(runtime, part, name.getByteList()); | |
+ encStrBufCat(runtime, part, INSPECT_COLON_ZERO_X); | |
+ encStrBufCat(runtime, part, ConvertBytes.longToCharBytes(inspectHashCode())); | |
if (runtime.isInspecting(this)) { | |
- /* 6:tags 16:addr 1:eos */ | |
- part.append(" ...>"); | |
- return RubyString.newString(runtime, part); | |
+ encStrBufCat(runtime, part, INSPECT_SPACE_DOT_DOT_DOT_GT); | |
+ return part; | |
} | |
try { | |
runtime.registerInspecting(this); | |
- return RubyString.newString(runtime, inspectObj(runtime, part)); | |
+ return inspectObj(runtime, part); | |
} finally { | |
runtime.unregisterInspecting(this); | |
} | |
@@ -1150,21 +1163,25 @@ public class RubyBasicObject implements Cloneable, IRubyObject, Serializable, Co | |
* The internal helper method that takes care of the part of the | |
* inspection that inspects instance variables. | |
*/ | |
- private StringBuilder inspectObj(final Ruby runtime, StringBuilder part) { | |
+ private RubyString inspectObj(final Ruby runtime, RubyString part) { | |
final ThreadContext context = runtime.getCurrentContext(); | |
- String sep = ""; | |
+ boolean first = true; | |
for (Map.Entry<String, VariableAccessor> entry : metaClass.getVariableTableManager().getVariableAccessorsForRead().entrySet()) { | |
Object value = entry.getValue().get(this); | |
if (!(value instanceof IRubyObject) || !IdUtil.isInstanceVariable(entry.getKey())) continue; | |
IRubyObject obj = (IRubyObject) value; | |
- part.append(sep).append(' ').append(entry.getKey()).append('='); | |
- part.append(sites(context).inspect.call(context, obj, obj)); | |
- sep = ","; | |
+ if (!first) encStrBufCat(runtime, part, INSPECT_COMMA); | |
+ encStrBufCat(runtime, part, INSPECT_SPACE); | |
+ encStrBufCat(runtime, part, entry.getKey().getBytes()); | |
+ encStrBufCat(runtime, part, INSPECT_EQUALS); | |
+ encStrBufCat(runtime, part, sites(context).inspect.call(context, obj, obj).convertToString().getByteList()); | |
+ | |
+ first = false; | |
} | |
- part.append('>'); | |
+ encStrBufCat(runtime, part, INSPECT_GT); | |
return part; | |
} | |
diff --git a/core/src/main/java/org/jruby/util/io/EncodingUtils.java b/core/src/main/java/org/jruby/util/io/EncodingUtils.java | |
index 9297b94..fa32383 100644 | |
--- a/core/src/main/java/org/jruby/util/io/EncodingUtils.java | |
+++ b/core/src/main/java/org/jruby/util/io/EncodingUtils.java | |
@@ -1625,6 +1625,12 @@ public class EncodingUtils { | |
str.modify(); | |
strBufCat(str.getByteList(), ptrBytes, ptr, len); | |
} | |
+ public static void strBufCat(ByteList str, ByteList ptr) { | |
+ strBufCat(str, ptr.getUnsafeBytes(), ptr.getBegin(), ptr.getRealSize()); | |
+ } | |
+ public static void strBufCat(ByteList str, byte[] ptrBytes) { | |
+ strBufCat(str, ptrBytes, 0, ptrBytes.length); | |
+ } | |
public static void strBufCat(ByteList str, byte[] ptrBytes, int ptr, int len) { | |
int total, off = -1; | |
@@ -1647,6 +1653,13 @@ public class EncodingUtils { | |
encCrStrBufCat(runtime, str, ptr.getUnsafeBytes(), ptr.getBegin(), ptr.getRealSize(), | |
enc, StringSupport.CR_UNKNOWN, null); | |
} | |
+ public static void encStrBufCat(Ruby runtime, RubyString str, ByteList ptr) { | |
+ encCrStrBufCat(runtime, str, ptr.getUnsafeBytes(), ptr.getBegin(), ptr.getRealSize(), | |
+ ptr.getEncoding(), StringSupport.CR_UNKNOWN, null); | |
+ } | |
+ public static void encStrBufCat(Ruby runtime, RubyString str, byte[] ptrBytes) { | |
+ encCrStrBufCat(runtime, str, ptrBytes, 0, ptrBytes.length, USASCIIEncoding.INSTANCE, StringSupport.CR_UNKNOWN, null); | |
+ } | |
public static void encStrBufCat(Ruby runtime, RubyString str, byte[] ptrBytes, int ptr, int len, Encoding enc) { | |
encCrStrBufCat(runtime, str, ptrBytes, ptr, len, | |
enc, StringSupport.CR_UNKNOWN, null); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment