Dlaczego natywne funkcje w Dart są tak ciężkie w porównaniu z funkcjami „DEFINE NATIVE ENTRY”, które są bardzo lekkie?
Nie mogę zrozumieć: „Dlaczego ta pewność?”.
Jest to opakowanie dla niestandardowej funkcji natywnej zdart/runtime/vm/native_entry.cc
:
Przeznaczony dla programistów Dart, którzy chcą pisaćnative extensions
.
void NativeEntry::NativeCallWrapper(Dart_NativeArguments args,
Dart_NativeFunction func) {
CHECK_STACK_ALIGNMENT;
VERIFY_ON_TRANSITION;
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
Isolate* isolate = arguments->isolate();
ApiState* state = isolate->api_state();
ASSERT(state != NULL);
ApiLocalScope* current_top_scope = state->top_scope();
ApiLocalScope* scope = state->reusable_scope();
TRACE_NATIVE_CALL("0x%" Px "", reinterpret_cast<uintptr_t>(func));
if (scope == NULL) {
scope = new ApiLocalScope(current_top_scope,
isolate->top_exit_frame_info());
ASSERT(scope != NULL);
} else {
scope->Reinit(isolate,
current_top_scope,
isolate->top_exit_frame_info());
state->set_reusable_scope(NULL);
}
state->set_top_scope(scope); // New scope is now the top scope.
func(args);
ASSERT(current_top_scope == scope->previous());
state->set_top_scope(current_top_scope); // Reset top scope to previous.
if (state->reusable_scope() == NULL) {
scope->Reset(isolate); // Reset the old scope which we just exited.
state->set_reusable_scope(scope);
} else {
ASSERT(state->reusable_scope() != scope);
delete scope;
}
DEOPTIMIZE_ALOT;
VERIFY_ON_TRANSITION;
}
Ten wrapper ze wszystkimi niepotrzebnymi kontrolami, które wykonuje przy każdym wywołaniu funkcji wrapped native sprawia, że funkcje te są niekonkurencyjne w porównaniu z tym, co używa programistów dla siebie.
To jest MACRO do definiowania funkcji natywnejdart/runtime/vm/native_entry.h
:
#define DEFINE_NATIVE_ENTRY(name, argument_count) \
static RawObject* DN_Helper##name(Isolate* isolate, \
NativeArguments* arguments); \
void NATIVE_ENTRY_FUNCTION(name)(Dart_NativeArguments args) { \
CHECK_STACK_ALIGNMENT; \
VERIFY_ON_TRANSITION; \
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); \
ASSERT(arguments->NativeArgCount() == argument_count); \
TRACE_NATIVE_CALL("%s", ""#name); \
{ \
StackZone zone(arguments->isolate()); \
SET_NATIVE_RETVAL(arguments, \
DN_Helper##name(arguments->isolate(), arguments)); \
DEOPTIMIZE_ALOT; \
} \
VERIFY_ON_TRANSITION; \
} \
static RawObject* DN_Helper##name(Isolate* isolate, \
NativeArguments* arguments)
Wiem, że działa bezpośrednio zRawObject
. To normalne.
Ale nie mogę znaleźć w nim wszystkich tych testów, które są wykonywane przy każdym wywołaniu, jak w powyższym opakowaniu.
Tracę serce, gdy widzę, że moje funkcje działają na 3000% wolniej niż analogi zdefiniowane przezDEFINE_NATIVE_ENTRY
.
P.S.
Mójnative function
to robiNOTHING
i niereturns ANYTHING
działa na 500% wolniej niż (na przykład) tej funkcji.
#define TYPED_DATA_GETTER(getter, object, access_size) \
DEFINE_NATIVE_ENTRY(TypedData_##getter, 2) { \
GET_NON_NULL_NATIVE_ARGUMENT(Instance, instance, arguments->NativeArgAt(0)); \
GET_NON_NULL_NATIVE_ARGUMENT(Smi, offsetInBytes, arguments->NativeArgAt(1)); \
if (instance.IsTypedData()) { \
const TypedData& array = TypedData::Cast(instance); \
RangeCheck(offsetInBytes.Value(), access_size, \
array.LengthInBytes(), access_size); \
return object::New(array.getter(offsetInBytes.Value())); \
} \
if (instance.IsExternalTypedData()) { \
const ExternalTypedData& array = ExternalTypedData::Cast(instance); \
RangeCheck(offsetInBytes.Value(), access_size, \
array.LengthInBytes(), access_size); \
return object::New(array.getter(offsetInBytes.Value())); \
} \
const String& error = String::Handle(String::NewFormatted( \
"Expected a TypedData object but found %s", instance.ToCString())); \
Exceptions::ThrowArgumentError(error); \
return object::null(); \
} \
Czy można napisać lekkie funkcje rodzime, które nie wymagają wszystkich tych funkcjiscope
?