[java-gnome-hackers] String reuse
Brought to you by:
afcowie
From: Andrew C. <an...@op...> - 2009-04-16 02:22:49
|
When you have a TextBuffer, and do something like: buffer.insert(iter, "Hello World"); this causes TextBuffer.InsertText to be emitted (as this is where GTK actually carries out the textual insertion, as it happens). if you've meanwhile connected to that signal, ie buffer.connect(new TextBuffer.InsertText() { public void onInsertText(TextBuffer source, TreeIter where, String text) { // ... } }); the text String you get will, of course, have the same "Hello World" content, but it will be a different String object [since it is created with NewStringUTF() in bindings_java_signal.c as the signal emission is marshalled and and the GClosure invoked]. This is fine. Except that it's a bit wasteful to have our JNI layer to have to create a new String when we know full well that a String with equivalent data already exists. And worse, that we *just* passed such a String across to the JNI layer where the char[] was converted (copied) into a UTF-8 gchar*. So while everyone knows that two Strings have to be checked by equals() rather than by reference ==, the whole point of Strings is that they are immutable and reusable. The number of arraycopy() that happens on char[] in the Sun Java library to preserve the immutable String character is already staggering and a common hot spot in profiling. So I'm wondering if we couldn't connive to at least not make it worse. If we convey the same String to a signal handler as was passed in by the initiating method, we could save a lot of copying. The thought I had was to keep a tiny (last 8 or so, though even last 1 would do) cache of gchar* to jstring mappings when we pass Strings across to JNI. Then during signal emission we could check the last 1 (or 8 or whatever) mappings to see if we've already got a String for that gchar* there, and if so just return it rather than creating a new one. Weak references, of course. It might seem minor, but right now I'm doing a lot of "insert huge block of text into a TextView, then ignore the InsertText signal because I know I just inserted it programmatically" .... but I have to ignore the signal _in_ the handler, and that's after the String copy has been created for the parameter. So I'm creating lots of Strings that are being ignored and rapidly thrown away. And while this falls squarely into the "premature optimization" category (the app is responsive), it's the sort of thing you like not to do if you can help it. Anyway, String reuse in general is an issue I'm thinking about. A variation on the theme is the possibility of using Direct ByteBuffers created JNI side and a view to a wrap piece of a native gchar*, rather than copying the thing into a String all the time with JNI NewStringUTF(). That would be wizard, except that we can't subclass or replace java.lang.String. So I'm not sure what good it would actually do given all our API is String, naturally. Discussion welcome. AfC Sydney -- Andrew Frederick Cowie Operational Dynamics is an operations and engineering consultancy focusing on IT strategy, organizational architecture, systems review, and effective procedures for change management: enabling successful deployment of mission critical information technology in enterprises, worldwide. http://www.operationaldynamics.com/ Sydney New York Toronto London |