Skip to content
This repository has been archived by the owner on Oct 15, 2020. It is now read-only.

optimize StringUtf8::From #348

Merged
merged 1 commit into from
Jul 31, 2017
Merged

Conversation

kunalspathak
Copy link
Member

Optimize calls to JsCopyString by assuming the string we get is ascii.
Refs: chakra-core/ChakraCore#3433

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • commit message follows commit guidelines
Affected core subsystem(s)

chakrashim

@kunalspathak
Copy link
Member Author

@MSLaguana
Copy link
Contributor

Looks like windows arm CI is failing due to not finding unicode/ucnv.h for some reason. There's also some linter errors, and the ubuntu 16.04 build is failing due to CHECK_JSRT being given too many arguments, I believe.

@MSLaguana
Copy link
Contributor

Perhaps we should do this in 2 parts; first to update the calls to JsCopyString to use the new parameters, and then secondly to make the perf change?

@kunalspathak
Copy link
Member Author

kunalspathak commented Jul 28, 2017 via email


size_t written = 0;
size_t actualLength = 0;
CHECK_JSRT(JsCopyString(key, *buffer, strLength, &written, &actualLength), napi_string_expected);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be CHECK_JSRT_EXPECTED

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. Wondering why I didn't see these failures on my machine.

inline napi_status JsCopyUtf8Bytes(JsValueRef key,
char** buffer, size_t* copiedBytesCount) {
int strLength = 0;
CHECK_JSRT(JsGetStringLength(key, &strLength), napi_string_expected);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be CHECK_JSRT_EXPECTED

*buffer = reinterpret_cast<char*>(malloc(actualLength + 1));
CHAKRA_VERIFY(buffer != nullptr);

CHECK_JSRT(JsCopyString(key, *buffer, actualLength, &written, nullptr), napi_string_expected);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be CHECK_JSRT_EXPECTED

CHECK_JSRT(JsGetStringLength(key, &strLength), napi_string_expected);

// assume string contains ascii characters only
*buffer = reinterpret_cast<char*>(malloc(strLength + 1));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Memory leak on errors. Can we just use std::vector instead?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this different to the previous code which mallocs a buffer in StringUtf8::From?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly... Isn't it same pattern as before?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CHAKRA_VERIFY is a fast fail, CHECK_JSRT returns the error code. Memory leaks are less of an issue when the process is dying anyway.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, the function that calls JsCopyUtf8Bytes is going to leak the allocation in the new scheme, since the old code used the value locally and never passed it back out, while the new code will just leak.

// free previously allocated buffer
free(*buffer);

*buffer = reinterpret_cast<char*>(malloc(actualLength + 1));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, possible memory leak unless you use RAII.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep. I will re-work this a bit and update the PR. For now, I will send another PR that unblocks the build break because of signature change.

@kunalspathak
Copy link
Member Author

Updated the PR with RAII as @kfarnung suggested using StringUtf8.
CI - https://ci.nodejs.org/job/chakracore-test-pull-request/129/

free(_str);

_str = reinterpret_cast<char*>(malloc(actualLength + 1));
CHAKRA_VERIFY(_str != nullptr);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not be using CHAKRA_VERIFY in N-API.

CHAKRA_VERIFY(_str != nullptr);

CHECK_JSRT_EXPECTED(JsCopyString(strRef, _str, actualLength, &written, nullptr), napi_string_expected);
assert(actualLength == written);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just have this return an error?

char* buffer = reinterpret_cast<char*>(malloc(len+1));
CHAKRA_VERIFY(buffer != nullptr);
// assume string contains ascii characters only
_str = reinterpret_cast<char*>(malloc(strLength + 1));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably check the malloc return value for null and bail out like the code previously did?

IfJsErrorRet(JsCopyString(strRef, buffer, len, &written, nullptr));
size_t actualLength = 0;
IfJsErrorRet(JsCopyString(strRef, _str, strLength, &written, &actualLength));
CHAKRA_ASSERT(strLength == written);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't guaranteed to be true, if the buffer stops mid-multibyte character. E.g. if there is a 2 byte Utf8 character which would start at position strLength-1, then JsCopyString will omit all bytes for that codepoint from the buffer, I believe, so written will be strLength-1. Similarly if it ends at a 3 byte character, it can be strLength-2.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense. Moved it so this gets verified when actualLength == written.

@kunalspathak
Copy link
Member Author

size_t written = 0;
size_t actualLength = 0;
CHECK_JSRT_EXPECTED(
JsCopyString(strRef, _str, strLength, &written, &actualLength),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Can you indent continuation lines by four spaces here and below?


int strLength = 0;
CHECK_JSRT_EXPECTED(JsGetStringLength(strRef, &strLength),
napi_string_expected);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Can you line this up with the previous parameter?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure.

Optimize calls to JsCopyString API

PR-URL: nodejs#348
Reviewed-By: Kyle Farnung <[email protected]>
@kunalspathak kunalspathak merged commit 3fe3388 into nodejs:master Jul 31, 2017
kfarnung pushed a commit that referenced this pull request Aug 10, 2017
Optimize calls to JsCopyString API

PR-URL: #348
Reviewed-By: Kyle Farnung <[email protected]>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants