Edoardo Luppi
06/10/2024, 3:42 PMSomeApi
! See the SomeApi_instance = new SomeApi();
bit
function FunctionCallBenchmark() {
this.re_1 = 0;
}
protoOf(FunctionCallBenchmark).se = function (bh) {
// Inline function 'kotlinx.benchmark.Blackhole.consume' call
var i = freeFunction(0);
bh.pe(i);
};
protoOf(FunctionCallBenchmark).te = function (bh) {
// Inline function 'kotlinx.benchmark.Blackhole.consume' call
var i = SomeApi_instance.callOnObject(0);
bh.pe(i);
};
function SomeApi() {
}
protoOf(SomeApi).callOnObject = function (x) {
return imul(x, 2);
};
var SomeApi_instance;
function SomeApi_getInstance() {
return SomeApi_instance;
}
function freeFunction(x) {
return imul(x, 2);
}
//region block: init
SomeApi_instance = new SomeApi();
//endregion
//region block: exports
function $jsExportAll$(_) {
var $org = _.org || (_.org = {});
var $org$example = $org.example || ($org.example = {});
defineProp($org$example, 'SomeApi', SomeApi_getInstance);
$org$example.freeFunction = freeFunction;
}
$jsExportAll$(_);
_.$jsExportAll$ = $jsExportAll$;
_.$_$ = _.$_$ || {};
_.$_$.a = FunctionCallBenchmark;
//endregion
return _;
Edoardo Luppi
06/10/2024, 4:01 PMfunction CharCodes_getInstance() {
if (CharCodes_instance === VOID)
new CharCodes();
return CharCodes_instance;
}
Edoardo Luppi
06/10/2024, 4:06 PMinternal
. Don't ask me why as this is totally new to me.
These are my results now.
batchSize: 10000
Benchmark Mode Cnt Score Error Units
FunctionCallBenchmark.freeFunctionCall avgt 10 10.838 ± 1.161 ns/op
FunctionCallBenchmark.objectFunctionCall avgt 10 14.302 ± 1.748 ns/op
batchSize: 5000
Benchmark Mode Cnt Score Error Units
FunctionCallBenchmark.freeFunctionCall avgt 10 9.747 ± 0.518 ns/op
FunctionCallBenchmark.objectFunctionCall avgt 10 13.119 ± 1.718 ns/op
Edoardo Luppi
06/10/2024, 4:07 PMpublic
, we might not incur in the performance penalty.Filipp Zhinkin
06/11/2024, 9:09 AMinternal
(generated JS code still initializes it eagerly). I'll check what affects lazy initializationEdoardo Luppi
06/11/2024, 9:20 AMobject SomeApi {
val test = IntRange(1, 20)
fun callOnObject(x: Int): Int = x * 2
}
Note the val test = IntRange(1, 20)
Property that instantiate a class > lazy init
Property with primitive type > no lazy init
internal or public doesn't change the result.Edoardo Luppi
06/11/2024, 9:23 AMEdoardo Luppi
06/11/2024, 9:24 AMFilipp Zhinkin
06/11/2024, 9:51 AMThe initialization of an object declaration is thread-safe and done on first access.The way "stateless" objects are initialized is an optimization (applied to objects with so called "pure" initializers), while getters with lazy initialization represents default behavior.
Edoardo Luppi
06/11/2024, 10:01 AMUnsafeBufferOperations
is an optimization, but is it guaranteed to be always done by the language specification, or some day we'll find out it's not applied anymore?Filipp Zhinkin
06/11/2024, 10:11 AMUnsafeBufferOperations
), that's where the optimization kicks in and initializes an object eagerly.Edoardo Luppi
06/11/2024, 10:20 AM