-
-
Notifications
You must be signed in to change notification settings - Fork 141
Marking mode none #829
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
Marking mode none #829
Conversation
6a17540
to
8447e71
Compare
|
||
public int getMarkingMode() { | ||
String mode = staticConfiguration == null || staticConfiguration.appConfig == null ? "full" : staticConfiguration.appConfig.getMarkingMode(); | ||
if ("none".equals(mode)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make enumeration with values of marking mode
m_numberOfGC(0), | ||
m_currentObjectId(0), | ||
m_cache(NewWeakGlobalRefCallback, DeleteWeakGlobalRefCallback, 1000, this), | ||
m_markingMode(JavaScriptMarkingMode::Full) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
get marking mode from java static configuration, don't set it as default here, because it's easier to change defaults only in one place
return dynamicConfig; | ||
} | ||
|
||
public int getMarkingMode() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add @RuntimeCallable
on method
jint markingMode = m_env.CallIntMethod(m_javaRuntimeObject, getMarkingModeMethodID); | ||
switch(markingMode) { | ||
case 1: | ||
m_markingMode = JavaScriptMarkingMode::None; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: this means every new thread will have this value reinitialized, so potentially values may differ between threads.
jsInfo = prototypeObject->GetInternalField(jsInfoIdx); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extract repeating code:
const int jsInfoIdx = static_cast<int>(MetadataNodeKeys::JsInfo);
auto jsInfo = object->GetInternalField(jsInfoIdx);
if (jsInfo->IsUndefined()) {
//Typescript object layout has an object instance as child of the actual registered instance. checking for that
auto prototypeObject = object->GetPrototype().As<Object>();
if (!prototypeObject.IsEmpty() && prototypeObject->IsObject()) {
DEBUG_WRITE("GetJSInstanceInfo: need to check prototype :%d", prototypeObject->GetIdentityHash());
if (IsJsRuntimeObject(prototypeObject)) {
jsInfo = prototypeObject->GetInternalField(jsInfoIdx);
}
}
}
used in ObjectManager::GetJSInstanceInfo
} | ||
} | ||
|
||
if (jsInfo.IsEmpty() || !jsInfo->IsExternal()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
!jsInfo->IsExternal()
check is redundant
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can be "undefined".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or at least it used to be before we augmented the previous PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok in that case leave IsEmpty
and IsUndefined
, but in both cases they implicitly imply !IsExternal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IDK, the whole thing got reorganised when I extracted a "GetJSInstanceInfoFromRuntimeObject" from the "GetJSInstanceInfo" and this one. Take a look now.
} | ||
|
||
if (jsInfo.IsEmpty() || !jsInfo->IsExternal()) { | ||
// The JavaScript instance has been forcefully disconnected from the Java instance. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please provide a better comment as this one implies we are setting jsInfo
to undefined or empty
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may add explicit "release()" method in future (although highly unlikely). But it also does some sanity check like for the preconditions that we have to check and you mention two lines below.
return; | ||
} | ||
|
||
auto external = jsInfo.As<External>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check !jsInfo.IsEmpty() || jsInfo->IsExternal())
before cast
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually the method 2 lines above does that check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
before the cast is made there needs to be explicit check for IsExternal
thisPtr->JSObjectFinalizer(isolate, callbackState); | ||
} | ||
|
||
void ObjectManager::JSObjectFinalizer(Isolate* isolate, ObjectWeakCallbackState* callbackState) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add Handle scope in the beginning of the method to take care of the local handles:
auto isolate = m_isolate;
HandleScope handleScope(isolate);
jboolean isJavaInstanceAlive = m_env.CallBooleanMethod(m_javaRuntimeObject, MAKE_INSTANCE_WEAK_AND_CHECK_IF_ALIVE_METHOD_ID, javaObjectID); | ||
if (isJavaInstanceAlive) { | ||
// If the Java instance is alive, keep the JavaScript instance alive. | ||
// TODO: Check should we really register the finalizer again? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if this TODO: is obsolete, remove it, if it's not let's check it out before it gets merged into master.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was added in the previous implementation in JSObjectWeakCallback
so I guess it should be there.
…to switch the memory management to one, that will not traverse the JS heap graph
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check out the comments
49d0556
to
0e6e7e3
Compare
0e6e7e3
to
052b28e
Compare
run ci |
💚 |
|
||
if (jsInfo.IsEmpty() || !jsInfo->IsExternal()) { | ||
// The JavaScript instance has been forcefully disconnected from the Java instance. | ||
if (!jsInstanceInfo) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in case jsInstanceInfo is nullptr
this check wont pass
please change check to: jsInstanceInfo != nullptr
Profiling, | ||
MarkingMode | ||
}; | ||
MarkingMode("markingMode", com.tns.MarkingMode.values()[0]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
com.tns.MarkingMode.full
as default value instead of com.tns.MarkingMode.values()[0]
return (String)values[KnownKeys.Profiling.ordinal()]; | ||
} | ||
public String getMarkingMode() { return (String)values[KnownKeys.MarkingMode.getIndex()]; } | ||
public MarkingMode getMarkingMode() { return (MarkingMode)values[KnownKeys.MarkingMode.ordinal()]; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for cast (MarkingMode)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The values is of type Object[], indexing it returns Object.
if (staticConfiguration != null && staticConfiguration.appConfig != null) { | ||
return staticConfiguration.appConfig.getMarkingMode().ordinal(); | ||
} else { | ||
return MarkingMode.values()[0].ordinal(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use KnownKeys.MarkingMode.getDefaultValue()
here, or if you don't want to expose KnownKeys
just expose API from app config that gets the default and current if any.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I exposed KnownKeys, I think it is fine.
try { | ||
String value = androidObject.getString(KnownKeys.MarkingMode.getName()); | ||
values[KnownKeys.MarkingMode.ordinal()] = MarkingMode.valueOf(value); | ||
} catch(Throwable e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- catch Exception instead of throwable here if you don't want to have a specific warning for each exception, otherwise catch the specific exceptions thrown my methods.
- don't leave catch block empty, please leave a warning that the default value will be used because we couldn't get the value for some reason
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Printed the stack trace and then a message with Log.v("JS", ... that the default will be used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check out comments.
ordinal() is a great addition.
f1d95b9
to
9f8bfcd
Compare
rootObject = FileSystem.readJSONFile(packageInfo); | ||
if (rootObject != null) { | ||
if (rootObject.has(KnownKeys.Profiling.getName())) { | ||
if (rootObject.has(KnownKeys.Profiling.name())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be getName()
9f8bfcd
to
49c7d77
Compare
49c7d77
to
1708cba
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After green build
run ci |
💚 |
Allows the MarkReachableObjects to be suppressed.
Setting:
Will completely disable the JavaScript heap traversal in MarkReachableObjects. This saves about 500ms. block on the main thread (we've seen it go up to 1350ms during navigation)
The memory management model changes drastically:
When a Java instance marshalled to a JavaScript type, the Java and JavaScript instances are bound,
When the JavaScript instance's finaliser is called (the JavaScript instance is not reachable)
This approach can lead to instances being prematurely collected, but doesn't involve long blocks on the main thread.
We want to run excessive testing on our apps so we can get a better understanding of the implications following from suppression MarkReachableObjects.