Skip to content

Commit

Permalink
Make JSStringToSTLString 23x faster (#26955)
Browse files Browse the repository at this point in the history
Summary:
In my app I have a case where I need to pass a very large string (45MB) between JS and native. This is obviously suboptimal, but… this is where I'm at.

The main bottleneck to doing this turned out to be `jsi`'s `JSStringToSTLString()`, which was extremely slow. In my case, 4.7s to execute. After this change, 204ms.

I don't really know C++, so I'm not sure this code is 100% correct and safe, and I bet it could be done even better by avoiding the extra memory allocation (would shave off another 70ms).

## Changelog

[General] [Changed] - Make JSStringToSTLString 23x faster
Pull Request resolved: #26955

Reviewed By: shergin

Differential Revision: D19578728

Pulled By: motiz88

fbshipit-source-id: 2fbce83166953ce928f0a6aa36eed710bfe05383
  • Loading branch information
radex authored and facebook-github-bot committed Jan 28, 2020
1 parent 142c66f commit 733532e
Showing 1 changed file with 15 additions and 3 deletions.
18 changes: 15 additions & 3 deletions ReactCommon/jsi/JSCRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include <JavaScriptCore/JavaScript.h>
#include <atomic>
#include <array>
#include <condition_variable>
#include <cstdlib>
#include <jsi/jsilib.h>
Expand Down Expand Up @@ -285,10 +286,21 @@ class JSCRuntime : public jsi::Runtime {
// JSStringRef utilities
namespace {
std::string JSStringToSTLString(JSStringRef str) {
// Small string optimization: Avoid one heap allocation for strings that fit
// in stackBuffer.size() bytes of UTF-8 (including the null terminator).
std::array<char, 20> stackBuffer;
std::unique_ptr<char[]> heapBuffer;
char *buffer;
size_t maxBytes = JSStringGetMaximumUTF8CStringSize(str);
std::vector<char> buffer(maxBytes);
JSStringGetUTF8CString(str, buffer.data(), maxBytes);
return std::string(buffer.data());
if (maxBytes <= stackBuffer.size()) {
buffer = stackBuffer.data();
} else {
heapBuffer = std::make_unique<char[]>(maxBytes);
buffer = heapBuffer.get();
}
size_t actualBytes = JSStringGetUTF8CString(str, buffer, maxBytes);
// NOTE: By definition, maxBytes >= actualBytes >= 1.
return std::string(buffer, actualBytes - 1);
}

JSStringRef getLengthString() {
Expand Down

0 comments on commit 733532e

Please sign in to comment.