Add assumeoverride feature option for Java directors to improve performance when it can be assumed that all methods are overridden by the Java derived classes
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@13606 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
fad95da7f5
commit
009c191430
6 changed files with 108 additions and 7 deletions
|
|
@ -5,6 +5,10 @@ See the RELEASENOTES file for a summary of changes in each release.
|
|||
Version 2.0.8 (in progress)
|
||||
===========================
|
||||
|
||||
2012-08-13: wsfulton
|
||||
[Java] Patch from David Baum to add the assumeoverride feature for Java directors to
|
||||
improve performance when all overridden methods can be assumed to be overridden.
|
||||
|
||||
2012-08-05: wsfulton
|
||||
[Python] #3530021 Fix unused variable warning.
|
||||
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@
|
|||
<li><a href="#Java_directors_overhead">Overhead and code bloat</a>
|
||||
<li><a href="#Java_directors_example">Simple directors example</a>
|
||||
<li><a href="#Java_directors_threading">Director threading issues</a>
|
||||
<li><a href="#Java_directors_performance">Director performance tuning</a>
|
||||
</ul>
|
||||
<li><a href="#Java_allprotected">Accessing protected members</a>
|
||||
<li><a href="#Java_common_customization">Common customization features</a>
|
||||
|
|
@ -3525,6 +3526,27 @@ Macros can be defined on the commandline when compiling your C++ code, or altern
|
|||
</pre>
|
||||
</div>
|
||||
|
||||
<H3><a name="Java_directors_performance"></a>24.5.6 Director performance tuning</H3>
|
||||
|
||||
<p>
|
||||
When a new instance of a director (or subclass) is created in Java, the C++ side of the director performs a runtime check per director method to determine if that particular method is overridden in Java or if it should invoke the C++ base implementation directly. Although this makes initialization slightly more expensive, it is generally a good overall tradeoff.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
However, if all director methods are expected to usually be overridden by Java subclasses, then initialization can be made faster by avoiding these checks via the <tt>assumeoverride</tt> attribute. For example:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%feature("director", assumeoverride=1) Foo;
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
The disadvantage is that invocation of director methods from C++ when Java doesn't actually override the method will require an additional call up into Java and back to C++. As such, this option is only useful when overrides are extremely common and instantiation is frequent enough that its performance is critical.
|
||||
</p>
|
||||
|
||||
|
||||
<H2><a name="Java_allprotected"></a>24.6 Accessing protected members</H2>
|
||||
|
||||
|
||||
|
|
@ -7862,4 +7884,3 @@ Many of these have runtime tests in the java subdirectory.
|
|||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ CPP_TEST_CASES += \
|
|||
destructor_reprotected \
|
||||
director_abstract \
|
||||
director_alternating \
|
||||
director_assumeoverride \
|
||||
director_basic \
|
||||
director_binary_string \
|
||||
director_classes \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
import java_director_assumeoverride.*;
|
||||
|
||||
public class java_director_assumeoverride_runme {
|
||||
|
||||
static {
|
||||
try {
|
||||
System.loadLibrary("java_director_assumeoverride");
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static class MyOverrideMe extends OverrideMe {
|
||||
}
|
||||
|
||||
public static void main(String argv[]) {
|
||||
OverrideMe overrideMe = new MyOverrideMe();
|
||||
|
||||
// MyOverrideMe doesn't actually override func(), but because assumeoverride
|
||||
// was set to true, the C++ side will believe it was overridden.
|
||||
if (!java_director_assumeoverride.isFuncOverridden(overrideMe)) {
|
||||
throw new RuntimeException ( "isFuncOverridden()" );
|
||||
}
|
||||
}
|
||||
}
|
||||
30
Examples/test-suite/java_director_assumeoverride.i
Normal file
30
Examples/test-suite/java_director_assumeoverride.i
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
%module(directors="1") java_director_assumeoverride
|
||||
#pragma SWIG nowarn=SWIGWARN_TYPEMAP_THREAD_UNSAFE,SWIGWARN_TYPEMAP_DIRECTOROUT_PTR
|
||||
|
||||
%{
|
||||
class OverrideMe {
|
||||
public:
|
||||
virtual ~OverrideMe() {}
|
||||
virtual void func() {};
|
||||
};
|
||||
|
||||
#include "java_director_assumeoverride_wrap.h"
|
||||
bool isFuncOverridden(OverrideMe* f) {
|
||||
SwigDirector_OverrideMe* director = dynamic_cast<SwigDirector_OverrideMe*>(f);
|
||||
if (!director) {
|
||||
return false;
|
||||
}
|
||||
return director->swig_overrides(0);
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%feature("director", assumeoverride=1) OverrideMe;
|
||||
|
||||
class OverrideMe {
|
||||
public:
|
||||
virtual ~OverrideMe();
|
||||
virtual void func();
|
||||
};
|
||||
|
||||
bool isFuncOverridden(OverrideMe* f);
|
||||
|
|
@ -4318,12 +4318,30 @@ public:
|
|||
Printf(w->code, " methods[i].base_methid = jenv->GetMethodID(baseclass, methods[i].mname, methods[i].mdesc);\n");
|
||||
Printf(w->code, " if (!methods[i].base_methid) return;\n");
|
||||
Printf(w->code, " }\n");
|
||||
Printf(w->code, " swig_override[i] = false;\n");
|
||||
Printf(w->code, " if (derived) {\n");
|
||||
Printf(w->code, " jmethodID methid = jenv->GetMethodID(jcls, methods[i].mname, methods[i].mdesc);\n");
|
||||
Printf(w->code, " swig_override[i] = (methid != methods[i].base_methid);\n");
|
||||
Printf(w->code, " jenv->ExceptionClear();\n");
|
||||
Printf(w->code, " }\n");
|
||||
// Generally, derived classes have a mix of overridden and
|
||||
// non-overridden methods and it is worth making a GetMethodID
|
||||
// check during initialization to determine if each method is
|
||||
// overridden, thus avoiding unnecessary calls into Java.
|
||||
//
|
||||
// On the other hand, when derived classes are
|
||||
// expected to override all director methods then the
|
||||
// GetMethodID calls are inefficient, and it is better to let
|
||||
// the director unconditionally call up into Java. The resulting code
|
||||
// will still behave correctly (though less efficiently) when Java
|
||||
// code doesn't override a given method.
|
||||
//
|
||||
// The assumeoverride feature on a director controls whether or not
|
||||
// overrides are assumed.
|
||||
if (GetFlag(n, "feature:director:assumeoverride")) {
|
||||
Printf(w->code, " swig_override[i] = derived;\n");
|
||||
} else {
|
||||
Printf(w->code, " swig_override[i] = false;\n");
|
||||
Printf(w->code, " if (derived) {\n");
|
||||
Printf(w->code, " jmethodID methid = jenv->GetMethodID(jcls, methods[i].mname, methods[i].mdesc);\n");
|
||||
Printf(w->code, " swig_override[i] = (methid != methods[i].base_methid);\n");
|
||||
Printf(w->code, " jenv->ExceptionClear();\n");
|
||||
Printf(w->code, " }\n");
|
||||
}
|
||||
Printf(w->code, "}\n");
|
||||
} else {
|
||||
Printf(f_directors_h, "public:\n");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue