Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Native StringBuilder/Concat in JS #837

Open
Ihromant opened this issue Oct 26, 2023 · 6 comments
Open

Native StringBuilder/Concat in JS #837

Ihromant opened this issue Oct 26, 2023 · 6 comments

Comments

@Ihromant
Copy link
Contributor

Hi @konsoletyper . Many thanks for native support for String in JS. Didn't try it yet because no 0.10-dev present.
I suppose that there is other place for improvement: native StringBuilder. AbstractStringBuilder is also nice place for replacing char[] -> native String object. In this case length field can be also dropped in JS case. Also then native Integer.toString #768 can be applied and in append case we can just concatenate it via common '+' in StringBuilder.
I understand that it could be performance degradation when we are replacing StringBuilder everywhere (should be measured by performance tests). So this change can be not implemented globally.
Still, in StringConcatFactory replacement, we can do the following: have private StringBuilder class (for instance ConcatStringBuilder) with native String inside which usually comes in case of following code:

private String json(int someInt, double someDouble) {
return "{ a: " + someInt + ", b: " + someDouble + "}";
}

in case of other platforms it will be replaced with common StringBuilder, in case of JS it will be transformed to

function json(someInt, someDouble) {
var csb = ConcatStringBuilder_init(); // internally s = "";
csb.append("{ a: "); // s = s + "{ a: "
csb.append(someInt); // s = s + someInt
csb.append(", b: "); // s = s + ", b: " and so on
csb.append(jl_Double_toString(someDouble));
csb.append("}");
return csb.s;
}

With this change it will be possible come closer to the desired

div.style.width = w + "px";

flattened code in JS for

div.getStyle().setAttribute("width", w + "px");
@konsoletyper
Copy link
Owner

StringBuilder can't be implemented via native JS string, since StringBuilder should support replacement/deletion, while strings don't. As for your example, there can be optimization to improve this. However, this optimization requires to do a lot before I can start working on it.

@konsoletyper
Copy link
Owner

Also, if you have bottleneck in you code that works with strings, you can just rewrite relevant parts in JSO. I know that you can have multi-platform code, but this is solvable by providing separate code for JS and Java. And usually there's a rule: 1% of code works 99%, so I believe you don't have to rewrite only small part.

@Ihromant
Copy link
Contributor Author

Ihromant commented Oct 26, 2023

Great, if optimization can be implemented eventually - it will work as well.
Also I highlighted most important use-case: String concat. In this case StringBuilder usage is the following:

return new StringBuilder("{ a: ").append(someInt).append(", b: ").append(someDouble).toString();

without any replacements/deletions/insertions somewhere in the middle.
This chain can be implemented the way above or even:

var sb = new Array(4);
sb.push("{ a: ");
sb.push(someInt);
sb.push(", b: ");
sb.push(jl_Double_toString(someDuble));
return sb.join('');

Still, from my perspective, according to different performance tests + contatenation works faster than join concatenation from around middle of 2021.

@konsoletyper
Copy link
Owner

without any replacements/deletions/insertions somewhere in the middle.

Yes, but what if one uses something of these? You can't guarantee. In some special cases when everything is exactly within one method, you can optimize things. As I explained, it's just what needs to be done, but not soon. In any a bit more complicated case, when StringBuilder leaves methods, you can't guarantee that such optimization would work.

Well, there could be one solution: to use both native string and char[] inside StringBuilder implementation. When user first uses operation like replacement/deletion/insertion, string could be converted to char[] under the hood and all further operation would go over slow path. However, this requires to check every time which storage are we using - this may have performance impact.

@McMurat
Copy link

McMurat commented Dec 1, 2023

Maybe this could be implemented for the invokedynamic String concatenations in recent Java versions which already cover many cases and are simpler as those can always be translated to JS concatenations without any replace/deletions...

@konsoletyper
Copy link
Owner

@McMurat I'm afraid it won't be any easier than to just support general StringBuilder case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants