koffi 2.1.0-beta.3 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ChangeLog.md +2 -1
- package/build/qemu/2.1.0/koffi_darwin_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_linux_arm32hf.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_openbsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_openbsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_win32_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0/koffi_win32_x64.tar.gz +0 -0
- package/doc/benchmarks.md +14 -14
- package/doc/benchmarks.xlsx +0 -0
- package/doc/index.rst +2 -2
- package/doc/static/perf_linux_20220812.png +0 -0
- package/doc/static/perf_windows_20220812.png +0 -0
- package/doc/types.md +10 -12
- package/package.json +2 -2
- package/qemu/registry/machines.json +2 -2
- package/qemu/registry/sha256sum.txt +2 -2
- package/src/abi_arm32.cc +23 -55
- package/src/abi_arm64.cc +22 -54
- package/src/abi_riscv64.cc +20 -52
- package/src/abi_x64_sysv.cc +20 -52
- package/src/abi_x64_win.cc +20 -52
- package/src/abi_x86.cc +24 -56
- package/src/call.cc +117 -143
- package/src/call.hh +4 -4
- package/src/ffi.cc +16 -4
- package/src/util.hh +0 -20
- package/test/callbacks.js +3 -3
- package/test/misc.c +2 -2
- package/test/sync.js +2 -2
- package/vendor/libcc/libcc.cc +75 -55
- package/vendor/libcc/libcc.hh +306 -255
- package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj +226 -0
- package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.filters +10 -0
- package/vendor/raylib/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.user +4 -0
- package/vendor/raylib/projects/VS2019-Android/raylib_android.sln +75 -0
- package/vendor/raylib/projects/VS2022/examples/audio_module_playing.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/audio_multichannel_sound.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/audio_music_stream.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/audio_raw_stream.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/audio_sound_loading.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/audio_stream_effects.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_2d_camera.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_2d_camera_mouse_zoom.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_2d_camera_platformer.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_3d_camera_first_person.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_3d_camera_free.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_3d_camera_mode.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_3d_picking.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_basic_screen_manager.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_basic_window.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_custom_frame_control.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_custom_logging.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_drop_files.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_input_gamepad.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_input_gestures.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_input_keys.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_input_mouse.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_input_mouse_wheel.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_input_multitouch.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_loading_thread.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_random_values.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_scissor_test.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_split_screen.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_storage_values.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_vr_simulator.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_window_flags.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_window_letterbox.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/core_window_should_close.vcxproj +390 -0
- package/vendor/raylib/projects/VS2022/examples/core_world_screen.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/easings_testbed.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/embedded_files_loading.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_animation.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_billboard.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_box_collisions.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_cubicmap.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_first_person_maze.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_geometric_shapes.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_heightmap.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_loading.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_loading_gltf.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_loading_vox.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_mesh_generation.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_mesh_picking.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_orthographic_projection.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_rlgl_solar_system.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_skybox.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_waving_cubes.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/models_yaw_pitch_roll.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/rlgl_compute_shaders.vcxproj +391 -0
- package/vendor/raylib/projects/VS2022/examples/rlgl_standalone.vcxproj +391 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_basic_lighting.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_custom_uniform.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_eratosthenes.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_fog.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_hot_reloading.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_julia_set.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_mesh_instancing.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_model_shader.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_multi_sample2d.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_palette_switch.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_postprocessing.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_raymarching.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_shapes_textures.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_simple_mask.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_spotlight.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_texture_drawing.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shaders_texture_waves.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_basic_shapes.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_bouncing_ball.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_collision_area.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_colors_palette.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_draw_circle_sector.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_draw_rectangle_rounded.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_draw_ring.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_easings_ball_anim.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_easings_box_anim.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_easings_rectangle_array.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_following_eyes.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_lines_bezier.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_logo_raylib.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_logo_raylib_anim.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/shapes_rectangle_scaling.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_codepoints_loading.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_draw_3d.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_font_filters.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_font_loading.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_font_sdf.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_font_spritefont.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_format_text.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_input_box.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_raylib_fonts.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_rectangle_bounds.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_unicode.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/text_writing_anim.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_background_scrolling.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_blend_modes.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_bunnymark.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_draw_tiled.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_fog_of_war.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_gif_player.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_image_drawing.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_image_generation.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_image_loading.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_image_processing.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_image_text.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_logo_raylib.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_mouse_painting.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_npatch_drawing.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_particles_blending.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_polygon.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_raw_data.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_sprite_anim.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_sprite_button.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_sprite_explosion.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_srcrec_dstrec.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/examples/textures_to_image.vcxproj +387 -0
- package/vendor/raylib/projects/VS2022/raylib/raylib.vcxproj +340 -0
- package/vendor/raylib/projects/VS2022/raylib.sln +2347 -0
- package/build/qemu/2.1.0-beta.3/koffi_darwin_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_linux_arm32hf.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_openbsd_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_openbsd_x64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_win32_arm64.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/2.1.0-beta.3/koffi_win32_x64.tar.gz +0 -0
- package/doc/dist/doctrees/benchmarks.doctree +0 -0
- package/doc/dist/doctrees/changes.doctree +0 -0
- package/doc/dist/doctrees/contribute.doctree +0 -0
- package/doc/dist/doctrees/environment.pickle +0 -0
- package/doc/dist/doctrees/functions.doctree +0 -0
- package/doc/dist/doctrees/index.doctree +0 -0
- package/doc/dist/doctrees/memory.doctree +0 -0
- package/doc/dist/doctrees/platforms.doctree +0 -0
- package/doc/dist/doctrees/start.doctree +0 -0
- package/doc/dist/doctrees/types.doctree +0 -0
- package/doc/dist/html/.buildinfo +0 -4
- package/doc/dist/html/_sources/benchmarks.md.txt +0 -137
- package/doc/dist/html/_sources/changes.md.txt +0 -161
- package/doc/dist/html/_sources/contribute.md.txt +0 -127
- package/doc/dist/html/_sources/functions.md.txt +0 -421
- package/doc/dist/html/_sources/index.rst.txt +0 -39
- package/doc/dist/html/_sources/memory.md.txt +0 -32
- package/doc/dist/html/_sources/platforms.md.txt +0 -31
- package/doc/dist/html/_sources/start.md.txt +0 -100
- package/doc/dist/html/_sources/types.md.txt +0 -541
- package/doc/dist/html/_static/_sphinx_javascript_frameworks_compat.js +0 -134
- package/doc/dist/html/_static/basic.css +0 -932
- package/doc/dist/html/_static/bench_linux.png +0 -0
- package/doc/dist/html/_static/bench_windows.png +0 -0
- package/doc/dist/html/_static/custom.css +0 -22
- package/doc/dist/html/_static/debug.css +0 -69
- package/doc/dist/html/_static/doctools.js +0 -264
- package/doc/dist/html/_static/documentation_options.js +0 -14
- package/doc/dist/html/_static/file.png +0 -0
- package/doc/dist/html/_static/jquery-3.6.0.js +0 -10881
- package/doc/dist/html/_static/jquery.js +0 -2
- package/doc/dist/html/_static/language_data.js +0 -199
- package/doc/dist/html/_static/minus.png +0 -0
- package/doc/dist/html/_static/perf_linux_20220623.png +0 -0
- package/doc/dist/html/_static/perf_linux_20220623_2.png +0 -0
- package/doc/dist/html/_static/perf_linux_20220627.png +0 -0
- package/doc/dist/html/_static/perf_linux_20220628.png +0 -0
- package/doc/dist/html/_static/perf_windows_20220623.png +0 -0
- package/doc/dist/html/_static/perf_windows_20220623_2.png +0 -0
- package/doc/dist/html/_static/perf_windows_20220627.png +0 -0
- package/doc/dist/html/_static/perf_windows_20220628.png +0 -0
- package/doc/dist/html/_static/plus.png +0 -0
- package/doc/dist/html/_static/pygments.css +0 -252
- package/doc/dist/html/_static/scripts/furo-extensions.js +0 -0
- package/doc/dist/html/_static/scripts/furo.js +0 -3
- package/doc/dist/html/_static/scripts/furo.js.LICENSE.txt +0 -7
- package/doc/dist/html/_static/scripts/furo.js.map +0 -1
- package/doc/dist/html/_static/searchtools.js +0 -531
- package/doc/dist/html/_static/skeleton.css +0 -296
- package/doc/dist/html/_static/styles/furo-extensions.css +0 -2
- package/doc/dist/html/_static/styles/furo-extensions.css.map +0 -1
- package/doc/dist/html/_static/styles/furo.css +0 -2
- package/doc/dist/html/_static/styles/furo.css.map +0 -1
- package/doc/dist/html/_static/underscore-1.13.1.js +0 -2042
- package/doc/dist/html/_static/underscore.js +0 -6
- package/doc/dist/html/benchmarks.html +0 -571
- package/doc/dist/html/changes.html +0 -686
- package/doc/dist/html/contribute.html +0 -403
- package/doc/dist/html/functions.html +0 -718
- package/doc/dist/html/genindex.html +0 -253
- package/doc/dist/html/index.html +0 -359
- package/doc/dist/html/memory.html +0 -346
- package/doc/dist/html/objects.inv +0 -0
- package/doc/dist/html/platforms.html +0 -371
- package/doc/dist/html/search.html +0 -261
- package/doc/dist/html/searchindex.js +0 -1
- package/doc/dist/html/start.html +0 -384
- package/doc/dist/html/types.html +0 -1061
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
!function(n,r){"object"==typeof exports&&"undefined"!=typeof module?module.exports=r():"function"==typeof define&&define.amd?define("underscore",r):(n="undefined"!=typeof globalThis?globalThis:n||self,function(){var t=n._,e=n._=r();e.noConflict=function(){return n._=t,e}}())}(this,(function(){
|
|
2
|
-
// Underscore.js 1.13.1
|
|
3
|
-
// https://underscorejs.org
|
|
4
|
-
// (c) 2009-2021 Jeremy Ashkenas, Julian Gonggrijp, and DocumentCloud and Investigative Reporters & Editors
|
|
5
|
-
// Underscore may be freely distributed under the MIT license.
|
|
6
|
-
var n="1.13.1",r="object"==typeof self&&self.self===self&&self||"object"==typeof global&&global.global===global&&global||Function("return this")()||{},t=Array.prototype,e=Object.prototype,u="undefined"!=typeof Symbol?Symbol.prototype:null,o=t.push,i=t.slice,a=e.toString,f=e.hasOwnProperty,c="undefined"!=typeof ArrayBuffer,l="undefined"!=typeof DataView,s=Array.isArray,p=Object.keys,v=Object.create,h=c&&ArrayBuffer.isView,y=isNaN,d=isFinite,g=!{toString:null}.propertyIsEnumerable("toString"),b=["valueOf","isPrototypeOf","toString","propertyIsEnumerable","hasOwnProperty","toLocaleString"],m=Math.pow(2,53)-1;function j(n,r){return r=null==r?n.length-1:+r,function(){for(var t=Math.max(arguments.length-r,0),e=Array(t),u=0;u<t;u++)e[u]=arguments[u+r];switch(r){case 0:return n.call(this,e);case 1:return n.call(this,arguments[0],e);case 2:return n.call(this,arguments[0],arguments[1],e)}var o=Array(r+1);for(u=0;u<r;u++)o[u]=arguments[u];return o[r]=e,n.apply(this,o)}}function _(n){var r=typeof n;return"function"===r||"object"===r&&!!n}function w(n){return void 0===n}function A(n){return!0===n||!1===n||"[object Boolean]"===a.call(n)}function x(n){var r="[object "+n+"]";return function(n){return a.call(n)===r}}var S=x("String"),O=x("Number"),M=x("Date"),E=x("RegExp"),B=x("Error"),N=x("Symbol"),I=x("ArrayBuffer"),T=x("Function"),k=r.document&&r.document.childNodes;"function"!=typeof/./&&"object"!=typeof Int8Array&&"function"!=typeof k&&(T=function(n){return"function"==typeof n||!1});var D=T,R=x("Object"),F=l&&R(new DataView(new ArrayBuffer(8))),V="undefined"!=typeof Map&&R(new Map),P=x("DataView");var q=F?function(n){return null!=n&&D(n.getInt8)&&I(n.buffer)}:P,U=s||x("Array");function W(n,r){return null!=n&&f.call(n,r)}var z=x("Arguments");!function(){z(arguments)||(z=function(n){return W(n,"callee")})}();var L=z;function $(n){return O(n)&&y(n)}function C(n){return function(){return n}}function K(n){return function(r){var t=n(r);return"number"==typeof t&&t>=0&&t<=m}}function J(n){return function(r){return null==r?void 0:r[n]}}var G=J("byteLength"),H=K(G),Q=/\[object ((I|Ui)nt(8|16|32)|Float(32|64)|Uint8Clamped|Big(I|Ui)nt64)Array\]/;var X=c?function(n){return h?h(n)&&!q(n):H(n)&&Q.test(a.call(n))}:C(!1),Y=J("length");function Z(n,r){r=function(n){for(var r={},t=n.length,e=0;e<t;++e)r[n[e]]=!0;return{contains:function(n){return r[n]},push:function(t){return r[t]=!0,n.push(t)}}}(r);var t=b.length,u=n.constructor,o=D(u)&&u.prototype||e,i="constructor";for(W(n,i)&&!r.contains(i)&&r.push(i);t--;)(i=b[t])in n&&n[i]!==o[i]&&!r.contains(i)&&r.push(i)}function nn(n){if(!_(n))return[];if(p)return p(n);var r=[];for(var t in n)W(n,t)&&r.push(t);return g&&Z(n,r),r}function rn(n,r){var t=nn(r),e=t.length;if(null==n)return!e;for(var u=Object(n),o=0;o<e;o++){var i=t[o];if(r[i]!==u[i]||!(i in u))return!1}return!0}function tn(n){return n instanceof tn?n:this instanceof tn?void(this._wrapped=n):new tn(n)}function en(n){return new Uint8Array(n.buffer||n,n.byteOffset||0,G(n))}tn.VERSION=n,tn.prototype.value=function(){return this._wrapped},tn.prototype.valueOf=tn.prototype.toJSON=tn.prototype.value,tn.prototype.toString=function(){return String(this._wrapped)};var un="[object DataView]";function on(n,r,t,e){if(n===r)return 0!==n||1/n==1/r;if(null==n||null==r)return!1;if(n!=n)return r!=r;var o=typeof n;return("function"===o||"object"===o||"object"==typeof r)&&function n(r,t,e,o){r instanceof tn&&(r=r._wrapped);t instanceof tn&&(t=t._wrapped);var i=a.call(r);if(i!==a.call(t))return!1;if(F&&"[object Object]"==i&&q(r)){if(!q(t))return!1;i=un}switch(i){case"[object RegExp]":case"[object String]":return""+r==""+t;case"[object Number]":return+r!=+r?+t!=+t:0==+r?1/+r==1/t:+r==+t;case"[object Date]":case"[object Boolean]":return+r==+t;case"[object Symbol]":return u.valueOf.call(r)===u.valueOf.call(t);case"[object ArrayBuffer]":case un:return n(en(r),en(t),e,o)}var f="[object Array]"===i;if(!f&&X(r)){if(G(r)!==G(t))return!1;if(r.buffer===t.buffer&&r.byteOffset===t.byteOffset)return!0;f=!0}if(!f){if("object"!=typeof r||"object"!=typeof t)return!1;var c=r.constructor,l=t.constructor;if(c!==l&&!(D(c)&&c instanceof c&&D(l)&&l instanceof l)&&"constructor"in r&&"constructor"in t)return!1}o=o||[];var s=(e=e||[]).length;for(;s--;)if(e[s]===r)return o[s]===t;if(e.push(r),o.push(t),f){if((s=r.length)!==t.length)return!1;for(;s--;)if(!on(r[s],t[s],e,o))return!1}else{var p,v=nn(r);if(s=v.length,nn(t).length!==s)return!1;for(;s--;)if(p=v[s],!W(t,p)||!on(r[p],t[p],e,o))return!1}return e.pop(),o.pop(),!0}(n,r,t,e)}function an(n){if(!_(n))return[];var r=[];for(var t in n)r.push(t);return g&&Z(n,r),r}function fn(n){var r=Y(n);return function(t){if(null==t)return!1;var e=an(t);if(Y(e))return!1;for(var u=0;u<r;u++)if(!D(t[n[u]]))return!1;return n!==hn||!D(t[cn])}}var cn="forEach",ln="has",sn=["clear","delete"],pn=["get",ln,"set"],vn=sn.concat(cn,pn),hn=sn.concat(pn),yn=["add"].concat(sn,cn,ln),dn=V?fn(vn):x("Map"),gn=V?fn(hn):x("WeakMap"),bn=V?fn(yn):x("Set"),mn=x("WeakSet");function jn(n){for(var r=nn(n),t=r.length,e=Array(t),u=0;u<t;u++)e[u]=n[r[u]];return e}function _n(n){for(var r={},t=nn(n),e=0,u=t.length;e<u;e++)r[n[t[e]]]=t[e];return r}function wn(n){var r=[];for(var t in n)D(n[t])&&r.push(t);return r.sort()}function An(n,r){return function(t){var e=arguments.length;if(r&&(t=Object(t)),e<2||null==t)return t;for(var u=1;u<e;u++)for(var o=arguments[u],i=n(o),a=i.length,f=0;f<a;f++){var c=i[f];r&&void 0!==t[c]||(t[c]=o[c])}return t}}var xn=An(an),Sn=An(nn),On=An(an,!0);function Mn(n){if(!_(n))return{};if(v)return v(n);var r=function(){};r.prototype=n;var t=new r;return r.prototype=null,t}function En(n){return _(n)?U(n)?n.slice():xn({},n):n}function Bn(n){return U(n)?n:[n]}function Nn(n){return tn.toPath(n)}function In(n,r){for(var t=r.length,e=0;e<t;e++){if(null==n)return;n=n[r[e]]}return t?n:void 0}function Tn(n,r,t){var e=In(n,Nn(r));return w(e)?t:e}function kn(n){return n}function Dn(n){return n=Sn({},n),function(r){return rn(r,n)}}function Rn(n){return n=Nn(n),function(r){return In(r,n)}}function Fn(n,r,t){if(void 0===r)return n;switch(null==t?3:t){case 1:return function(t){return n.call(r,t)};case 3:return function(t,e,u){return n.call(r,t,e,u)};case 4:return function(t,e,u,o){return n.call(r,t,e,u,o)}}return function(){return n.apply(r,arguments)}}function Vn(n,r,t){return null==n?kn:D(n)?Fn(n,r,t):_(n)&&!U(n)?Dn(n):Rn(n)}function Pn(n,r){return Vn(n,r,1/0)}function qn(n,r,t){return tn.iteratee!==Pn?tn.iteratee(n,r):Vn(n,r,t)}function Un(){}function Wn(n,r){return null==r&&(r=n,n=0),n+Math.floor(Math.random()*(r-n+1))}tn.toPath=Bn,tn.iteratee=Pn;var zn=Date.now||function(){return(new Date).getTime()};function Ln(n){var r=function(r){return n[r]},t="(?:"+nn(n).join("|")+")",e=RegExp(t),u=RegExp(t,"g");return function(n){return n=null==n?"":""+n,e.test(n)?n.replace(u,r):n}}var $n={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},Cn=Ln($n),Kn=Ln(_n($n)),Jn=tn.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g},Gn=/(.)^/,Hn={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},Qn=/\\|'|\r|\n|\u2028|\u2029/g;function Xn(n){return"\\"+Hn[n]}var Yn=/^\s*(\w|\$)+\s*$/;var Zn=0;function nr(n,r,t,e,u){if(!(e instanceof r))return n.apply(t,u);var o=Mn(n.prototype),i=n.apply(o,u);return _(i)?i:o}var rr=j((function(n,r){var t=rr.placeholder,e=function(){for(var u=0,o=r.length,i=Array(o),a=0;a<o;a++)i[a]=r[a]===t?arguments[u++]:r[a];for(;u<arguments.length;)i.push(arguments[u++]);return nr(n,e,this,this,i)};return e}));rr.placeholder=tn;var tr=j((function(n,r,t){if(!D(n))throw new TypeError("Bind must be called on a function");var e=j((function(u){return nr(n,e,r,this,t.concat(u))}));return e})),er=K(Y);function ur(n,r,t,e){if(e=e||[],r||0===r){if(r<=0)return e.concat(n)}else r=1/0;for(var u=e.length,o=0,i=Y(n);o<i;o++){var a=n[o];if(er(a)&&(U(a)||L(a)))if(r>1)ur(a,r-1,t,e),u=e.length;else for(var f=0,c=a.length;f<c;)e[u++]=a[f++];else t||(e[u++]=a)}return e}var or=j((function(n,r){var t=(r=ur(r,!1,!1)).length;if(t<1)throw new Error("bindAll must be passed function names");for(;t--;){var e=r[t];n[e]=tr(n[e],n)}return n}));var ir=j((function(n,r,t){return setTimeout((function(){return n.apply(null,t)}),r)})),ar=rr(ir,tn,1);function fr(n){return function(){return!n.apply(this,arguments)}}function cr(n,r){var t;return function(){return--n>0&&(t=r.apply(this,arguments)),n<=1&&(r=null),t}}var lr=rr(cr,2);function sr(n,r,t){r=qn(r,t);for(var e,u=nn(n),o=0,i=u.length;o<i;o++)if(r(n[e=u[o]],e,n))return e}function pr(n){return function(r,t,e){t=qn(t,e);for(var u=Y(r),o=n>0?0:u-1;o>=0&&o<u;o+=n)if(t(r[o],o,r))return o;return-1}}var vr=pr(1),hr=pr(-1);function yr(n,r,t,e){for(var u=(t=qn(t,e,1))(r),o=0,i=Y(n);o<i;){var a=Math.floor((o+i)/2);t(n[a])<u?o=a+1:i=a}return o}function dr(n,r,t){return function(e,u,o){var a=0,f=Y(e);if("number"==typeof o)n>0?a=o>=0?o:Math.max(o+f,a):f=o>=0?Math.min(o+1,f):o+f+1;else if(t&&o&&f)return e[o=t(e,u)]===u?o:-1;if(u!=u)return(o=r(i.call(e,a,f),$))>=0?o+a:-1;for(o=n>0?a:f-1;o>=0&&o<f;o+=n)if(e[o]===u)return o;return-1}}var gr=dr(1,vr,yr),br=dr(-1,hr);function mr(n,r,t){var e=(er(n)?vr:sr)(n,r,t);if(void 0!==e&&-1!==e)return n[e]}function jr(n,r,t){var e,u;if(r=Fn(r,t),er(n))for(e=0,u=n.length;e<u;e++)r(n[e],e,n);else{var o=nn(n);for(e=0,u=o.length;e<u;e++)r(n[o[e]],o[e],n)}return n}function _r(n,r,t){r=qn(r,t);for(var e=!er(n)&&nn(n),u=(e||n).length,o=Array(u),i=0;i<u;i++){var a=e?e[i]:i;o[i]=r(n[a],a,n)}return o}function wr(n){var r=function(r,t,e,u){var o=!er(r)&&nn(r),i=(o||r).length,a=n>0?0:i-1;for(u||(e=r[o?o[a]:a],a+=n);a>=0&&a<i;a+=n){var f=o?o[a]:a;e=t(e,r[f],f,r)}return e};return function(n,t,e,u){var o=arguments.length>=3;return r(n,Fn(t,u,4),e,o)}}var Ar=wr(1),xr=wr(-1);function Sr(n,r,t){var e=[];return r=qn(r,t),jr(n,(function(n,t,u){r(n,t,u)&&e.push(n)})),e}function Or(n,r,t){r=qn(r,t);for(var e=!er(n)&&nn(n),u=(e||n).length,o=0;o<u;o++){var i=e?e[o]:o;if(!r(n[i],i,n))return!1}return!0}function Mr(n,r,t){r=qn(r,t);for(var e=!er(n)&&nn(n),u=(e||n).length,o=0;o<u;o++){var i=e?e[o]:o;if(r(n[i],i,n))return!0}return!1}function Er(n,r,t,e){return er(n)||(n=jn(n)),("number"!=typeof t||e)&&(t=0),gr(n,r,t)>=0}var Br=j((function(n,r,t){var e,u;return D(r)?u=r:(r=Nn(r),e=r.slice(0,-1),r=r[r.length-1]),_r(n,(function(n){var o=u;if(!o){if(e&&e.length&&(n=In(n,e)),null==n)return;o=n[r]}return null==o?o:o.apply(n,t)}))}));function Nr(n,r){return _r(n,Rn(r))}function Ir(n,r,t){var e,u,o=-1/0,i=-1/0;if(null==r||"number"==typeof r&&"object"!=typeof n[0]&&null!=n)for(var a=0,f=(n=er(n)?n:jn(n)).length;a<f;a++)null!=(e=n[a])&&e>o&&(o=e);else r=qn(r,t),jr(n,(function(n,t,e){((u=r(n,t,e))>i||u===-1/0&&o===-1/0)&&(o=n,i=u)}));return o}function Tr(n,r,t){if(null==r||t)return er(n)||(n=jn(n)),n[Wn(n.length-1)];var e=er(n)?En(n):jn(n),u=Y(e);r=Math.max(Math.min(r,u),0);for(var o=u-1,i=0;i<r;i++){var a=Wn(i,o),f=e[i];e[i]=e[a],e[a]=f}return e.slice(0,r)}function kr(n,r){return function(t,e,u){var o=r?[[],[]]:{};return e=qn(e,u),jr(t,(function(r,u){var i=e(r,u,t);n(o,r,i)})),o}}var Dr=kr((function(n,r,t){W(n,t)?n[t].push(r):n[t]=[r]})),Rr=kr((function(n,r,t){n[t]=r})),Fr=kr((function(n,r,t){W(n,t)?n[t]++:n[t]=1})),Vr=kr((function(n,r,t){n[t?0:1].push(r)}),!0),Pr=/[^\ud800-\udfff]|[\ud800-\udbff][\udc00-\udfff]|[\ud800-\udfff]/g;function qr(n,r,t){return r in t}var Ur=j((function(n,r){var t={},e=r[0];if(null==n)return t;D(e)?(r.length>1&&(e=Fn(e,r[1])),r=an(n)):(e=qr,r=ur(r,!1,!1),n=Object(n));for(var u=0,o=r.length;u<o;u++){var i=r[u],a=n[i];e(a,i,n)&&(t[i]=a)}return t})),Wr=j((function(n,r){var t,e=r[0];return D(e)?(e=fr(e),r.length>1&&(t=r[1])):(r=_r(ur(r,!1,!1),String),e=function(n,t){return!Er(r,t)}),Ur(n,e,t)}));function zr(n,r,t){return i.call(n,0,Math.max(0,n.length-(null==r||t?1:r)))}function Lr(n,r,t){return null==n||n.length<1?null==r||t?void 0:[]:null==r||t?n[0]:zr(n,n.length-r)}function $r(n,r,t){return i.call(n,null==r||t?1:r)}var Cr=j((function(n,r){return r=ur(r,!0,!0),Sr(n,(function(n){return!Er(r,n)}))})),Kr=j((function(n,r){return Cr(n,r)}));function Jr(n,r,t,e){A(r)||(e=t,t=r,r=!1),null!=t&&(t=qn(t,e));for(var u=[],o=[],i=0,a=Y(n);i<a;i++){var f=n[i],c=t?t(f,i,n):f;r&&!t?(i&&o===c||u.push(f),o=c):t?Er(o,c)||(o.push(c),u.push(f)):Er(u,f)||u.push(f)}return u}var Gr=j((function(n){return Jr(ur(n,!0,!0))}));function Hr(n){for(var r=n&&Ir(n,Y).length||0,t=Array(r),e=0;e<r;e++)t[e]=Nr(n,e);return t}var Qr=j(Hr);function Xr(n,r){return n._chain?tn(r).chain():r}function Yr(n){return jr(wn(n),(function(r){var t=tn[r]=n[r];tn.prototype[r]=function(){var n=[this._wrapped];return o.apply(n,arguments),Xr(this,t.apply(tn,n))}})),tn}jr(["pop","push","reverse","shift","sort","splice","unshift"],(function(n){var r=t[n];tn.prototype[n]=function(){var t=this._wrapped;return null!=t&&(r.apply(t,arguments),"shift"!==n&&"splice"!==n||0!==t.length||delete t[0]),Xr(this,t)}})),jr(["concat","join","slice"],(function(n){var r=t[n];tn.prototype[n]=function(){var n=this._wrapped;return null!=n&&(n=r.apply(n,arguments)),Xr(this,n)}}));var Zr=Yr({__proto__:null,VERSION:n,restArguments:j,isObject:_,isNull:function(n){return null===n},isUndefined:w,isBoolean:A,isElement:function(n){return!(!n||1!==n.nodeType)},isString:S,isNumber:O,isDate:M,isRegExp:E,isError:B,isSymbol:N,isArrayBuffer:I,isDataView:q,isArray:U,isFunction:D,isArguments:L,isFinite:function(n){return!N(n)&&d(n)&&!isNaN(parseFloat(n))},isNaN:$,isTypedArray:X,isEmpty:function(n){if(null==n)return!0;var r=Y(n);return"number"==typeof r&&(U(n)||S(n)||L(n))?0===r:0===Y(nn(n))},isMatch:rn,isEqual:function(n,r){return on(n,r)},isMap:dn,isWeakMap:gn,isSet:bn,isWeakSet:mn,keys:nn,allKeys:an,values:jn,pairs:function(n){for(var r=nn(n),t=r.length,e=Array(t),u=0;u<t;u++)e[u]=[r[u],n[r[u]]];return e},invert:_n,functions:wn,methods:wn,extend:xn,extendOwn:Sn,assign:Sn,defaults:On,create:function(n,r){var t=Mn(n);return r&&Sn(t,r),t},clone:En,tap:function(n,r){return r(n),n},get:Tn,has:function(n,r){for(var t=(r=Nn(r)).length,e=0;e<t;e++){var u=r[e];if(!W(n,u))return!1;n=n[u]}return!!t},mapObject:function(n,r,t){r=qn(r,t);for(var e=nn(n),u=e.length,o={},i=0;i<u;i++){var a=e[i];o[a]=r(n[a],a,n)}return o},identity:kn,constant:C,noop:Un,toPath:Bn,property:Rn,propertyOf:function(n){return null==n?Un:function(r){return Tn(n,r)}},matcher:Dn,matches:Dn,times:function(n,r,t){var e=Array(Math.max(0,n));r=Fn(r,t,1);for(var u=0;u<n;u++)e[u]=r(u);return e},random:Wn,now:zn,escape:Cn,unescape:Kn,templateSettings:Jn,template:function(n,r,t){!r&&t&&(r=t),r=On({},r,tn.templateSettings);var e=RegExp([(r.escape||Gn).source,(r.interpolate||Gn).source,(r.evaluate||Gn).source].join("|")+"|$","g"),u=0,o="__p+='";n.replace(e,(function(r,t,e,i,a){return o+=n.slice(u,a).replace(Qn,Xn),u=a+r.length,t?o+="'+\n((__t=("+t+"))==null?'':_.escape(__t))+\n'":e?o+="'+\n((__t=("+e+"))==null?'':__t)+\n'":i&&(o+="';\n"+i+"\n__p+='"),r})),o+="';\n";var i,a=r.variable;if(a){if(!Yn.test(a))throw new Error("variable is not a bare identifier: "+a)}else o="with(obj||{}){\n"+o+"}\n",a="obj";o="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+o+"return __p;\n";try{i=new Function(a,"_",o)}catch(n){throw n.source=o,n}var f=function(n){return i.call(this,n,tn)};return f.source="function("+a+"){\n"+o+"}",f},result:function(n,r,t){var e=(r=Nn(r)).length;if(!e)return D(t)?t.call(n):t;for(var u=0;u<e;u++){var o=null==n?void 0:n[r[u]];void 0===o&&(o=t,u=e),n=D(o)?o.call(n):o}return n},uniqueId:function(n){var r=++Zn+"";return n?n+r:r},chain:function(n){var r=tn(n);return r._chain=!0,r},iteratee:Pn,partial:rr,bind:tr,bindAll:or,memoize:function(n,r){var t=function(e){var u=t.cache,o=""+(r?r.apply(this,arguments):e);return W(u,o)||(u[o]=n.apply(this,arguments)),u[o]};return t.cache={},t},delay:ir,defer:ar,throttle:function(n,r,t){var e,u,o,i,a=0;t||(t={});var f=function(){a=!1===t.leading?0:zn(),e=null,i=n.apply(u,o),e||(u=o=null)},c=function(){var c=zn();a||!1!==t.leading||(a=c);var l=r-(c-a);return u=this,o=arguments,l<=0||l>r?(e&&(clearTimeout(e),e=null),a=c,i=n.apply(u,o),e||(u=o=null)):e||!1===t.trailing||(e=setTimeout(f,l)),i};return c.cancel=function(){clearTimeout(e),a=0,e=u=o=null},c},debounce:function(n,r,t){var e,u,o,i,a,f=function(){var c=zn()-u;r>c?e=setTimeout(f,r-c):(e=null,t||(i=n.apply(a,o)),e||(o=a=null))},c=j((function(c){return a=this,o=c,u=zn(),e||(e=setTimeout(f,r),t&&(i=n.apply(a,o))),i}));return c.cancel=function(){clearTimeout(e),e=o=a=null},c},wrap:function(n,r){return rr(r,n)},negate:fr,compose:function(){var n=arguments,r=n.length-1;return function(){for(var t=r,e=n[r].apply(this,arguments);t--;)e=n[t].call(this,e);return e}},after:function(n,r){return function(){if(--n<1)return r.apply(this,arguments)}},before:cr,once:lr,findKey:sr,findIndex:vr,findLastIndex:hr,sortedIndex:yr,indexOf:gr,lastIndexOf:br,find:mr,detect:mr,findWhere:function(n,r){return mr(n,Dn(r))},each:jr,forEach:jr,map:_r,collect:_r,reduce:Ar,foldl:Ar,inject:Ar,reduceRight:xr,foldr:xr,filter:Sr,select:Sr,reject:function(n,r,t){return Sr(n,fr(qn(r)),t)},every:Or,all:Or,some:Mr,any:Mr,contains:Er,includes:Er,include:Er,invoke:Br,pluck:Nr,where:function(n,r){return Sr(n,Dn(r))},max:Ir,min:function(n,r,t){var e,u,o=1/0,i=1/0;if(null==r||"number"==typeof r&&"object"!=typeof n[0]&&null!=n)for(var a=0,f=(n=er(n)?n:jn(n)).length;a<f;a++)null!=(e=n[a])&&e<o&&(o=e);else r=qn(r,t),jr(n,(function(n,t,e){((u=r(n,t,e))<i||u===1/0&&o===1/0)&&(o=n,i=u)}));return o},shuffle:function(n){return Tr(n,1/0)},sample:Tr,sortBy:function(n,r,t){var e=0;return r=qn(r,t),Nr(_r(n,(function(n,t,u){return{value:n,index:e++,criteria:r(n,t,u)}})).sort((function(n,r){var t=n.criteria,e=r.criteria;if(t!==e){if(t>e||void 0===t)return 1;if(t<e||void 0===e)return-1}return n.index-r.index})),"value")},groupBy:Dr,indexBy:Rr,countBy:Fr,partition:Vr,toArray:function(n){return n?U(n)?i.call(n):S(n)?n.match(Pr):er(n)?_r(n,kn):jn(n):[]},size:function(n){return null==n?0:er(n)?n.length:nn(n).length},pick:Ur,omit:Wr,first:Lr,head:Lr,take:Lr,initial:zr,last:function(n,r,t){return null==n||n.length<1?null==r||t?void 0:[]:null==r||t?n[n.length-1]:$r(n,Math.max(0,n.length-r))},rest:$r,tail:$r,drop:$r,compact:function(n){return Sr(n,Boolean)},flatten:function(n,r){return ur(n,r,!1)},without:Kr,uniq:Jr,unique:Jr,union:Gr,intersection:function(n){for(var r=[],t=arguments.length,e=0,u=Y(n);e<u;e++){var o=n[e];if(!Er(r,o)){var i;for(i=1;i<t&&Er(arguments[i],o);i++);i===t&&r.push(o)}}return r},difference:Cr,unzip:Hr,transpose:Hr,zip:Qr,object:function(n,r){for(var t={},e=0,u=Y(n);e<u;e++)r?t[n[e]]=r[e]:t[n[e][0]]=n[e][1];return t},range:function(n,r,t){null==r&&(r=n||0,n=0),t||(t=r<n?-1:1);for(var e=Math.max(Math.ceil((r-n)/t),0),u=Array(e),o=0;o<e;o++,n+=t)u[o]=n;return u},chunk:function(n,r){if(null==r||r<1)return[];for(var t=[],e=0,u=n.length;e<u;)t.push(i.call(n,e,e+=r));return t},mixin:Yr,default:tn});return Zr._=Zr,Zr}));
|
|
@@ -1,571 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html class="no-js" lang="en">
|
|
3
|
-
<head><meta charset="utf-8"/>
|
|
4
|
-
<meta name="viewport" content="width=device-width,initial-scale=1"/>
|
|
5
|
-
<meta name="color-scheme" content="light dark"><meta name="generator" content="Docutils 0.18.1: http://docutils.sourceforge.net/" />
|
|
6
|
-
<link rel="index" title="Index" href="genindex" /><link rel="search" title="Search" href="search" /><link rel="next" title="Contributing" href="contribute" /><link rel="prev" title="Memory usage" href="memory" />
|
|
7
|
-
|
|
8
|
-
<meta name="generator" content="sphinx-5.0.1, furo 2022.06.04.1"/>
|
|
9
|
-
<title>Benchmarks - Koffi</title>
|
|
10
|
-
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
|
11
|
-
<link rel="stylesheet" type="text/css" href="_static/styles/furo.css?digest=40978830699223671f4072448e654b5958f38b89" />
|
|
12
|
-
<link rel="stylesheet" type="text/css" href="_static/styles/furo-extensions.css?digest=30d1aed668e5c3a91c3e3bf6a60b675221979f0e" />
|
|
13
|
-
<link rel="stylesheet" type="text/css" href="_static/custom.css" />
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
<style>
|
|
19
|
-
body {
|
|
20
|
-
--color-code-background: #f8f8f8;
|
|
21
|
-
--color-code-foreground: black;
|
|
22
|
-
--color-brand-primary: #FF6600;
|
|
23
|
-
--color-brand-content: #FF6600;
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
@media not print {
|
|
27
|
-
body[data-theme="dark"] {
|
|
28
|
-
--color-code-background: #202020;
|
|
29
|
-
--color-code-foreground: #d0d0d0;
|
|
30
|
-
--color-brand-primary: #FF6600;
|
|
31
|
-
--color-brand-content: #FF6600;
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
@media (prefers-color-scheme: dark) {
|
|
35
|
-
body:not([data-theme="light"]) {
|
|
36
|
-
--color-code-background: #202020;
|
|
37
|
-
--color-code-foreground: #d0d0d0;
|
|
38
|
-
--color-brand-primary: #FF6600;
|
|
39
|
-
--color-brand-content: #FF6600;
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
</style></head>
|
|
45
|
-
<body>
|
|
46
|
-
|
|
47
|
-
<script>
|
|
48
|
-
document.body.dataset.theme = localStorage.getItem("theme") || "auto";
|
|
49
|
-
</script>
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
|
|
53
|
-
<symbol id="svg-toc" viewBox="0 0 24 24">
|
|
54
|
-
<title>Contents</title>
|
|
55
|
-
<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 1024 1024">
|
|
56
|
-
<path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM115.4 518.9L271.7 642c5.8 4.6 14.4.5 14.4-6.9V388.9c0-7.4-8.5-11.5-14.4-6.9L115.4 505.1a8.74 8.74 0 0 0 0 13.8z"/>
|
|
57
|
-
</svg>
|
|
58
|
-
</symbol>
|
|
59
|
-
<symbol id="svg-menu" viewBox="0 0 24 24">
|
|
60
|
-
<title>Menu</title>
|
|
61
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
62
|
-
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-menu">
|
|
63
|
-
<line x1="3" y1="12" x2="21" y2="12"></line>
|
|
64
|
-
<line x1="3" y1="6" x2="21" y2="6"></line>
|
|
65
|
-
<line x1="3" y1="18" x2="21" y2="18"></line>
|
|
66
|
-
</svg>
|
|
67
|
-
</symbol>
|
|
68
|
-
<symbol id="svg-arrow-right" viewBox="0 0 24 24">
|
|
69
|
-
<title>Expand</title>
|
|
70
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
71
|
-
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather-chevron-right">
|
|
72
|
-
<polyline points="9 18 15 12 9 6"></polyline>
|
|
73
|
-
</svg>
|
|
74
|
-
</symbol>
|
|
75
|
-
<symbol id="svg-sun" viewBox="0 0 24 24">
|
|
76
|
-
<title>Light mode</title>
|
|
77
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
78
|
-
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="feather-sun">
|
|
79
|
-
<circle cx="12" cy="12" r="5"></circle>
|
|
80
|
-
<line x1="12" y1="1" x2="12" y2="3"></line>
|
|
81
|
-
<line x1="12" y1="21" x2="12" y2="23"></line>
|
|
82
|
-
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
|
83
|
-
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
|
84
|
-
<line x1="1" y1="12" x2="3" y2="12"></line>
|
|
85
|
-
<line x1="21" y1="12" x2="23" y2="12"></line>
|
|
86
|
-
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
|
87
|
-
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
|
88
|
-
</svg>
|
|
89
|
-
</symbol>
|
|
90
|
-
<symbol id="svg-moon" viewBox="0 0 24 24">
|
|
91
|
-
<title>Dark mode</title>
|
|
92
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
93
|
-
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-moon">
|
|
94
|
-
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
|
95
|
-
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z" />
|
|
96
|
-
</svg>
|
|
97
|
-
</symbol>
|
|
98
|
-
<symbol id="svg-sun-half" viewBox="0 0 24 24">
|
|
99
|
-
<title>Auto light/dark mode</title>
|
|
100
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
101
|
-
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="icon-tabler-shadow">
|
|
102
|
-
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
|
103
|
-
<circle cx="12" cy="12" r="9" />
|
|
104
|
-
<path d="M13 12h5" />
|
|
105
|
-
<path d="M13 15h4" />
|
|
106
|
-
<path d="M13 18h1" />
|
|
107
|
-
<path d="M13 9h4" />
|
|
108
|
-
<path d="M13 6h1" />
|
|
109
|
-
</svg>
|
|
110
|
-
</symbol>
|
|
111
|
-
</svg>
|
|
112
|
-
|
|
113
|
-
<input type="checkbox" class="sidebar-toggle" name="__navigation" id="__navigation">
|
|
114
|
-
<input type="checkbox" class="sidebar-toggle" name="__toc" id="__toc">
|
|
115
|
-
<label class="overlay sidebar-overlay" for="__navigation">
|
|
116
|
-
<div class="visually-hidden">Hide navigation sidebar</div>
|
|
117
|
-
</label>
|
|
118
|
-
<label class="overlay toc-overlay" for="__toc">
|
|
119
|
-
<div class="visually-hidden">Hide table of contents sidebar</div>
|
|
120
|
-
</label>
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
<div class="page">
|
|
125
|
-
<header class="mobile-header">
|
|
126
|
-
<div class="header-left">
|
|
127
|
-
<label class="nav-overlay-icon" for="__navigation">
|
|
128
|
-
<div class="visually-hidden">Toggle site navigation sidebar</div>
|
|
129
|
-
<i class="icon"><svg><use href="#svg-menu"></use></svg></i>
|
|
130
|
-
</label>
|
|
131
|
-
</div>
|
|
132
|
-
<div class="header-center">
|
|
133
|
-
<a href="index"><div class="brand">Koffi</div></a>
|
|
134
|
-
</div>
|
|
135
|
-
<div class="header-right">
|
|
136
|
-
<div class="theme-toggle-container theme-toggle-header">
|
|
137
|
-
<button class="theme-toggle">
|
|
138
|
-
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
|
|
139
|
-
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
|
|
140
|
-
<svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
|
|
141
|
-
<svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
|
|
142
|
-
</button>
|
|
143
|
-
</div>
|
|
144
|
-
<label class="toc-overlay-icon toc-header-icon" for="__toc">
|
|
145
|
-
<div class="visually-hidden">Toggle table of contents sidebar</div>
|
|
146
|
-
<i class="icon"><svg><use href="#svg-toc"></use></svg></i>
|
|
147
|
-
</label>
|
|
148
|
-
</div>
|
|
149
|
-
</header>
|
|
150
|
-
<aside class="sidebar-drawer">
|
|
151
|
-
<div class="sidebar-container">
|
|
152
|
-
|
|
153
|
-
<div class="sidebar-sticky"><a class="sidebar-brand" href="index">
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
<span class="sidebar-brand-text">Koffi</span>
|
|
157
|
-
|
|
158
|
-
</a><form class="sidebar-search-container" method="get" action="search" role="search">
|
|
159
|
-
<input class="sidebar-search" placeholder=Search name="q" aria-label="Search">
|
|
160
|
-
<input type="hidden" name="check_keywords" value="yes">
|
|
161
|
-
<input type="hidden" name="area" value="default">
|
|
162
|
-
</form>
|
|
163
|
-
<div id="searchbox"></div><div class="sidebar-scroll"><div class="sidebar-tree">
|
|
164
|
-
<ul class="current">
|
|
165
|
-
<li class="toctree-l1"><a class="reference internal" href="platforms">Requirements</a></li>
|
|
166
|
-
<li class="toctree-l1"><a class="reference internal" href="start">Quick start</a></li>
|
|
167
|
-
<li class="toctree-l1"><a class="reference internal" href="types">Data types</a></li>
|
|
168
|
-
<li class="toctree-l1"><a class="reference internal" href="functions">Functions</a></li>
|
|
169
|
-
<li class="toctree-l1"><a class="reference internal" href="memory">Memory usage</a></li>
|
|
170
|
-
<li class="toctree-l1 current current-page"><a class="current reference internal" href="#">Benchmarks</a></li>
|
|
171
|
-
<li class="toctree-l1"><a class="reference internal" href="contribute">Contributing</a></li>
|
|
172
|
-
<li class="toctree-l1"><a class="reference internal" href="changes">Changelog</a></li>
|
|
173
|
-
</ul>
|
|
174
|
-
|
|
175
|
-
</div>
|
|
176
|
-
<div style="text-align: center; margin-top: 2em;">
|
|
177
|
-
<a href="https://www.npmjs.com/package/koffi"><img src="https://img.shields.io/badge/NPM-2.O.1-brightgreen" alt="NPM"/></a>
|
|
178
|
-
<a href="https://github.com/Koromix/luigi/tree/master/koffi"><img src="https://img.shields.io/badge/GitHub-Koffi-ff6600" alt="GitHub"/></a>
|
|
179
|
-
</div></div>
|
|
180
|
-
|
|
181
|
-
</div>
|
|
182
|
-
|
|
183
|
-
</div>
|
|
184
|
-
</aside>
|
|
185
|
-
<div class="main">
|
|
186
|
-
<div class="content">
|
|
187
|
-
<div class="article-container">
|
|
188
|
-
<a href="#" class="back-to-top muted-link">
|
|
189
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
|
190
|
-
<path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12z"></path>
|
|
191
|
-
</svg>
|
|
192
|
-
<span>Back to top</span>
|
|
193
|
-
</a>
|
|
194
|
-
<div class="content-icon-container">
|
|
195
|
-
<div class="theme-toggle-container theme-toggle-content">
|
|
196
|
-
<button class="theme-toggle">
|
|
197
|
-
<div class="visually-hidden">Toggle Light / Dark / Auto color theme</div>
|
|
198
|
-
<svg class="theme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
|
|
199
|
-
<svg class="theme-icon-when-dark"><use href="#svg-moon"></use></svg>
|
|
200
|
-
<svg class="theme-icon-when-light"><use href="#svg-sun"></use></svg>
|
|
201
|
-
</button>
|
|
202
|
-
</div>
|
|
203
|
-
<label class="toc-overlay-icon toc-content-icon" for="__toc">
|
|
204
|
-
<div class="visually-hidden">Toggle table of contents sidebar</div>
|
|
205
|
-
<i class="icon"><svg><use href="#svg-toc"></use></svg></i>
|
|
206
|
-
</label>
|
|
207
|
-
</div>
|
|
208
|
-
<article role="main">
|
|
209
|
-
<section id="benchmarks">
|
|
210
|
-
<h1>Benchmarks<a class="headerlink" href="#benchmarks" title="Permalink to this heading">#</a></h1>
|
|
211
|
-
<section id="overview">
|
|
212
|
-
<h2>Overview<a class="headerlink" href="#overview" title="Permalink to this heading">#</a></h2>
|
|
213
|
-
<p>Here is a quick overview of the execution time of Koffi calls on three benchmarks, where it is compared to a theoretical ideal FFI implementation (approximated with pre-compiled static N-API glue code):</p>
|
|
214
|
-
<ul class="simple">
|
|
215
|
-
<li><p>The first benchmark is based on <code class="docutils literal notranslate"><span class="pre">rand()</span></code> calls</p></li>
|
|
216
|
-
<li><p>The second benchmark is based on <code class="docutils literal notranslate"><span class="pre">atoi()</span></code> calls</p></li>
|
|
217
|
-
<li><p>The third benchmark is based on <a class="reference external" href="https://www.raylib.com/">Raylib</a></p></li>
|
|
218
|
-
</ul>
|
|
219
|
-
<table style="margin: 0 auto;">
|
|
220
|
-
<tr>
|
|
221
|
-
<td><a href="_static/perf_linux_20220628.png" target="_blank"><img src="_static/perf_linux_20220628.png" alt="Linux x86_64 performance" style="width: 350px;"/></a></td>
|
|
222
|
-
<td><a href="_static/perf_windows_20220628.png" target="_blank"><img src="_static/perf_windows_20220628.png" alt="Windows x86_64 performance" style="width: 350px;"/></a></td>
|
|
223
|
-
</tr>
|
|
224
|
-
</table>
|
|
225
|
-
<p>These results are detailed and explained below, and compared to node-ffi/node-ffi-napi.</p>
|
|
226
|
-
</section>
|
|
227
|
-
<section id="linux-x86-64">
|
|
228
|
-
<h2>Linux x86_64<a class="headerlink" href="#linux-x86-64" title="Permalink to this heading">#</a></h2>
|
|
229
|
-
<p>The results presented below were measured on my x86_64 Linux machine (Intel® Core™ i5-4460).</p>
|
|
230
|
-
<section id="rand-results">
|
|
231
|
-
<h3>rand results<a class="headerlink" href="#rand-results" title="Permalink to this heading">#</a></h3>
|
|
232
|
-
<p>This test is based around repeated calls to a simple standard C function atoi, and has three implementations:</p>
|
|
233
|
-
<ul class="simple">
|
|
234
|
-
<li><p>the first one is the reference, it calls atoi through an N-API module, and is close to the theoretical limit of a perfect (no overhead) Node.js > C FFI implementation (pre-compiled static glue code)</p></li>
|
|
235
|
-
<li><p>the second one calls atoi through Koffi</p></li>
|
|
236
|
-
<li><p>the third one uses the official Node.js FFI implementation, node-ffi-napi</p></li>
|
|
237
|
-
</ul>
|
|
238
|
-
<div class="table-wrapper colwidths-auto docutils container">
|
|
239
|
-
<table class="docutils align-default">
|
|
240
|
-
<thead>
|
|
241
|
-
<tr class="row-odd"><th class="head"><p>Benchmark</p></th>
|
|
242
|
-
<th class="head"><p>Iteration time</p></th>
|
|
243
|
-
<th class="head"><p>Relative performance</p></th>
|
|
244
|
-
<th class="head"><p>Overhead</p></th>
|
|
245
|
-
</tr>
|
|
246
|
-
</thead>
|
|
247
|
-
<tbody>
|
|
248
|
-
<tr class="row-even"><td><p>rand_napi</p></td>
|
|
249
|
-
<td><p>644 ns</p></td>
|
|
250
|
-
<td><p>x1.00</p></td>
|
|
251
|
-
<td><p>(ref)</p></td>
|
|
252
|
-
</tr>
|
|
253
|
-
<tr class="row-odd"><td><p>rand_koffi</p></td>
|
|
254
|
-
<td><p>950 ns</p></td>
|
|
255
|
-
<td><p>x0.68</p></td>
|
|
256
|
-
<td><p>+48%</p></td>
|
|
257
|
-
</tr>
|
|
258
|
-
<tr class="row-even"><td><p>rand_node_ffi</p></td>
|
|
259
|
-
<td><p>30350 ns</p></td>
|
|
260
|
-
<td><p>x0.02</p></td>
|
|
261
|
-
<td><p>+4613%</p></td>
|
|
262
|
-
</tr>
|
|
263
|
-
</tbody>
|
|
264
|
-
</table>
|
|
265
|
-
</div>
|
|
266
|
-
<p>Because rand is a pretty small function, the FFI overhead is clearly visible.</p>
|
|
267
|
-
</section>
|
|
268
|
-
<section id="atoi-results">
|
|
269
|
-
<h3>atoi results<a class="headerlink" href="#atoi-results" title="Permalink to this heading">#</a></h3>
|
|
270
|
-
<p>This test is similar to the rand one, but it is based on atoi, which takes a string parameter. Javascript (V8) to C string conversion is relatively slow and heavy.</p>
|
|
271
|
-
<div class="table-wrapper colwidths-auto docutils container">
|
|
272
|
-
<table class="docutils align-default">
|
|
273
|
-
<thead>
|
|
274
|
-
<tr class="row-odd"><th class="head"><p>Benchmark</p></th>
|
|
275
|
-
<th class="head"><p>Iteration time</p></th>
|
|
276
|
-
<th class="head"><p>Relative performance</p></th>
|
|
277
|
-
<th class="head"><p>Overhead</p></th>
|
|
278
|
-
</tr>
|
|
279
|
-
</thead>
|
|
280
|
-
<tbody>
|
|
281
|
-
<tr class="row-even"><td><p>atoi_napi</p></td>
|
|
282
|
-
<td><p>1104 ns</p></td>
|
|
283
|
-
<td><p>x1.00</p></td>
|
|
284
|
-
<td><p>(ref)</p></td>
|
|
285
|
-
</tr>
|
|
286
|
-
<tr class="row-odd"><td><p>atoi_koffi</p></td>
|
|
287
|
-
<td><p>1778 ns</p></td>
|
|
288
|
-
<td><p>x0.62</p></td>
|
|
289
|
-
<td><p>+61%</p></td>
|
|
290
|
-
</tr>
|
|
291
|
-
<tr class="row-even"><td><p>atoi_node_ffi</p></td>
|
|
292
|
-
<td><p>125300 ns</p></td>
|
|
293
|
-
<td><p>x0.009</p></td>
|
|
294
|
-
<td><p>+11250%</p></td>
|
|
295
|
-
</tr>
|
|
296
|
-
</tbody>
|
|
297
|
-
</table>
|
|
298
|
-
</div>
|
|
299
|
-
<p>Because atoi is a pretty small function, the FFI overhead is clearly visible.</p>
|
|
300
|
-
</section>
|
|
301
|
-
<section id="raylib-results">
|
|
302
|
-
<h3>Raylib results<a class="headerlink" href="#raylib-results" title="Permalink to this heading">#</a></h3>
|
|
303
|
-
<p>This benchmark uses the CPU-based image drawing functions in Raylib. The calls are much heavier than in the atoi benchmark, thus the FFI overhead is reduced. In this implementation, Koffi is compared to:</p>
|
|
304
|
-
<ul class="simple">
|
|
305
|
-
<li><p>Baseline: Full C++ version of the code (no JS)</p></li>
|
|
306
|
-
<li><p><a class="reference external" href="https://github.com/RobLoach/node-raylib">node-raylib</a>: This is a native wrapper implemented with N-API</p></li>
|
|
307
|
-
</ul>
|
|
308
|
-
<div class="table-wrapper colwidths-auto docutils container">
|
|
309
|
-
<table class="docutils align-default">
|
|
310
|
-
<thead>
|
|
311
|
-
<tr class="row-odd"><th class="head"><p>Benchmark</p></th>
|
|
312
|
-
<th class="head"><p>Iteration time</p></th>
|
|
313
|
-
<th class="head"><p>Relative performance</p></th>
|
|
314
|
-
<th class="head"><p>Overhead</p></th>
|
|
315
|
-
</tr>
|
|
316
|
-
</thead>
|
|
317
|
-
<tbody>
|
|
318
|
-
<tr class="row-even"><td><p>raylib_cc</p></td>
|
|
319
|
-
<td><p>215.7 µs</p></td>
|
|
320
|
-
<td><p>x1.20</p></td>
|
|
321
|
-
<td><p>-17%</p></td>
|
|
322
|
-
</tr>
|
|
323
|
-
<tr class="row-odd"><td><p>raylib_node_raylib</p></td>
|
|
324
|
-
<td><p>258.9 µs</p></td>
|
|
325
|
-
<td><p>x1.00</p></td>
|
|
326
|
-
<td><p>(ref)</p></td>
|
|
327
|
-
</tr>
|
|
328
|
-
<tr class="row-even"><td><p>raylib_koffi</p></td>
|
|
329
|
-
<td><p>311.6 µs</p></td>
|
|
330
|
-
<td><p>x0.83</p></td>
|
|
331
|
-
<td><p>+20%</p></td>
|
|
332
|
-
</tr>
|
|
333
|
-
<tr class="row-odd"><td><p>raylib_node_ffi</p></td>
|
|
334
|
-
<td><p>928.4 µs</p></td>
|
|
335
|
-
<td><p>x0.28</p></td>
|
|
336
|
-
<td><p>+259%</p></td>
|
|
337
|
-
</tr>
|
|
338
|
-
</tbody>
|
|
339
|
-
</table>
|
|
340
|
-
</div>
|
|
341
|
-
</section>
|
|
342
|
-
</section>
|
|
343
|
-
<section id="windows-x86-64">
|
|
344
|
-
<h2>Windows x86_64<a class="headerlink" href="#windows-x86-64" title="Permalink to this heading">#</a></h2>
|
|
345
|
-
<p>The results presented below were measured on my x86_64 Windows machine (Intel® Core™ i5-4460).</p>
|
|
346
|
-
<section id="id1">
|
|
347
|
-
<h3>rand results<a class="headerlink" href="#id1" title="Permalink to this heading">#</a></h3>
|
|
348
|
-
<p>This test is based around repeated calls to a simple standard C function atoi, and has three implementations:</p>
|
|
349
|
-
<ul class="simple">
|
|
350
|
-
<li><p>the first one is the reference, it calls atoi through an N-API module, and is close to the theoretical limit of a perfect (no overhead) Node.js > C FFI implementation (pre-compiled static glue code)</p></li>
|
|
351
|
-
<li><p>the second one calls atoi through Koffi</p></li>
|
|
352
|
-
<li><p>the third one uses the official Node.js FFI implementation, node-ffi-napi</p></li>
|
|
353
|
-
</ul>
|
|
354
|
-
<div class="table-wrapper colwidths-auto docutils container">
|
|
355
|
-
<table class="docutils align-default">
|
|
356
|
-
<thead>
|
|
357
|
-
<tr class="row-odd"><th class="head"><p>Benchmark</p></th>
|
|
358
|
-
<th class="head"><p>Iteration time</p></th>
|
|
359
|
-
<th class="head"><p>Relative performance</p></th>
|
|
360
|
-
<th class="head"><p>Overhead</p></th>
|
|
361
|
-
</tr>
|
|
362
|
-
</thead>
|
|
363
|
-
<tbody>
|
|
364
|
-
<tr class="row-even"><td><p>rand_napi</p></td>
|
|
365
|
-
<td><p>965 ns</p></td>
|
|
366
|
-
<td><p>x1.00</p></td>
|
|
367
|
-
<td><p>(ref)</p></td>
|
|
368
|
-
</tr>
|
|
369
|
-
<tr class="row-odd"><td><p>rand_koffi</p></td>
|
|
370
|
-
<td><p>1248 ns</p></td>
|
|
371
|
-
<td><p>x0.77</p></td>
|
|
372
|
-
<td><p>+29%</p></td>
|
|
373
|
-
</tr>
|
|
374
|
-
<tr class="row-even"><td><p>rand_node_ffi</p></td>
|
|
375
|
-
<td><p>41500 ns</p></td>
|
|
376
|
-
<td><p>x0.02</p></td>
|
|
377
|
-
<td><p>+4203%</p></td>
|
|
378
|
-
</tr>
|
|
379
|
-
</tbody>
|
|
380
|
-
</table>
|
|
381
|
-
</div>
|
|
382
|
-
<p>Because rand is a pretty small function, the FFI overhead is clearly visible.</p>
|
|
383
|
-
</section>
|
|
384
|
-
<section id="id2">
|
|
385
|
-
<h3>atoi results<a class="headerlink" href="#id2" title="Permalink to this heading">#</a></h3>
|
|
386
|
-
<p>This test is similar to the rand one, but it is based on atoi, which takes a string parameter. Javascript (V8) to C string conversion is relatively slow and heavy.</p>
|
|
387
|
-
<p>The results below were measured on my x86_64 Windows machine (Intel® Core™ i5-4460):</p>
|
|
388
|
-
<div class="table-wrapper colwidths-auto docutils container">
|
|
389
|
-
<table class="docutils align-default">
|
|
390
|
-
<thead>
|
|
391
|
-
<tr class="row-odd"><th class="head"><p>Benchmark</p></th>
|
|
392
|
-
<th class="head"><p>Iteration time</p></th>
|
|
393
|
-
<th class="head"><p>Relative performance</p></th>
|
|
394
|
-
<th class="head"><p>Overhead</p></th>
|
|
395
|
-
</tr>
|
|
396
|
-
</thead>
|
|
397
|
-
<tbody>
|
|
398
|
-
<tr class="row-even"><td><p>atoi_napi</p></td>
|
|
399
|
-
<td><p>1393 ns</p></td>
|
|
400
|
-
<td><p>x1.00</p></td>
|
|
401
|
-
<td><p>(ref)</p></td>
|
|
402
|
-
</tr>
|
|
403
|
-
<tr class="row-odd"><td><p>atoi_koffi</p></td>
|
|
404
|
-
<td><p>2246 ns</p></td>
|
|
405
|
-
<td><p>x0.62</p></td>
|
|
406
|
-
<td><p>+61%</p></td>
|
|
407
|
-
</tr>
|
|
408
|
-
<tr class="row-even"><td><p>atoi_node_ffi</p></td>
|
|
409
|
-
<td><p>157550 ns</p></td>
|
|
410
|
-
<td><p>x0.009</p></td>
|
|
411
|
-
<td><p>+11210%</p></td>
|
|
412
|
-
</tr>
|
|
413
|
-
</tbody>
|
|
414
|
-
</table>
|
|
415
|
-
</div>
|
|
416
|
-
<p>Because atoi is a pretty small function, the FFI overhead is clearly visible.</p>
|
|
417
|
-
</section>
|
|
418
|
-
<section id="id3">
|
|
419
|
-
<h3>Raylib results<a class="headerlink" href="#id3" title="Permalink to this heading">#</a></h3>
|
|
420
|
-
<p>This benchmark uses the CPU-based image drawing functions in Raylib. The calls are much heavier than in the atoi benchmark, thus the FFI overhead is reduced. In this implementation, Koffi is compared to:</p>
|
|
421
|
-
<ul class="simple">
|
|
422
|
-
<li><p><a class="reference external" href="https://github.com/RobLoach/node-raylib">node-raylib</a> (baseline): This is a native wrapper implemented with N-API</p></li>
|
|
423
|
-
<li><p>raylib_cc: C++ implementation of the benchmark, without any Javascript</p></li>
|
|
424
|
-
</ul>
|
|
425
|
-
<div class="table-wrapper colwidths-auto docutils container">
|
|
426
|
-
<table class="docutils align-default">
|
|
427
|
-
<thead>
|
|
428
|
-
<tr class="row-odd"><th class="head"><p>Benchmark</p></th>
|
|
429
|
-
<th class="head"><p>Iteration time</p></th>
|
|
430
|
-
<th class="head"><p>Relative performance</p></th>
|
|
431
|
-
<th class="head"><p>Overhead</p></th>
|
|
432
|
-
</tr>
|
|
433
|
-
</thead>
|
|
434
|
-
<tbody>
|
|
435
|
-
<tr class="row-even"><td><p>raylib_cc</p></td>
|
|
436
|
-
<td><p>211.8 µs</p></td>
|
|
437
|
-
<td><p>x1.25</p></td>
|
|
438
|
-
<td><p>-20%</p></td>
|
|
439
|
-
</tr>
|
|
440
|
-
<tr class="row-odd"><td><p>raylib_node_raylib</p></td>
|
|
441
|
-
<td><p>264.4 µs</p></td>
|
|
442
|
-
<td><p>x1.00</p></td>
|
|
443
|
-
<td><p>(ref)</p></td>
|
|
444
|
-
</tr>
|
|
445
|
-
<tr class="row-even"><td><p>raylib_koffi</p></td>
|
|
446
|
-
<td><p>318.9 µs</p></td>
|
|
447
|
-
<td><p>x0.83</p></td>
|
|
448
|
-
<td><p>+21%</p></td>
|
|
449
|
-
</tr>
|
|
450
|
-
<tr class="row-odd"><td><p>raylib_node_ffi</p></td>
|
|
451
|
-
<td><p>1146.2 µs</p></td>
|
|
452
|
-
<td><p>x0.23</p></td>
|
|
453
|
-
<td><p>+334%</p></td>
|
|
454
|
-
</tr>
|
|
455
|
-
</tbody>
|
|
456
|
-
</table>
|
|
457
|
-
</div>
|
|
458
|
-
<p>Please note that in order to get fair numbers for raylib_node_raylib, it was recompiled with clang-cl before running the benchmark with the following commands:</p>
|
|
459
|
-
<div class="highlight-batch notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span><span class="k">cd</span> node_modules\raylib
|
|
460
|
-
<span class="linenos">2</span><span class="k">rmdir</span> /S /Q bin build
|
|
461
|
-
<span class="linenos">3</span>npx cmake-js compile -t ClangCL
|
|
462
|
-
</pre></div>
|
|
463
|
-
</div>
|
|
464
|
-
</section>
|
|
465
|
-
</section>
|
|
466
|
-
<section id="running-benchmarks">
|
|
467
|
-
<h2>Running benchmarks<a class="headerlink" href="#running-benchmarks" title="Permalink to this heading">#</a></h2>
|
|
468
|
-
<p>Open a console, go to <code class="docutils literal notranslate"><span class="pre">koffi/benchmark</span></code> and run <code class="docutils literal notranslate"><span class="pre">../../cnoke/cnoke.js</span></code> (or <code class="docutils literal notranslate"><span class="pre">node</span> <span class="pre">..\..\cnoke\cnoke.js</span></code> on Windows) before doing anything else.</p>
|
|
469
|
-
<p>Please note that all benchmark results are made with Clang-built binaries.</p>
|
|
470
|
-
<div class="highlight-sh notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span><span class="nb">cd</span> koffi/benchmark
|
|
471
|
-
<span class="linenos">2</span>node ../../cnoke/cnoke.js --prefer-clang
|
|
472
|
-
</pre></div>
|
|
473
|
-
</div>
|
|
474
|
-
<p>Once everything is built and ready, run:</p>
|
|
475
|
-
<div class="highlight-sh notranslate"><div class="highlight"><pre><span></span><span class="linenos">1</span>node benchmark.js
|
|
476
|
-
</pre></div>
|
|
477
|
-
</div>
|
|
478
|
-
</section>
|
|
479
|
-
</section>
|
|
480
|
-
|
|
481
|
-
</article>
|
|
482
|
-
</div>
|
|
483
|
-
<footer>
|
|
484
|
-
|
|
485
|
-
<div class="related-pages">
|
|
486
|
-
<a class="next-page" href="contribute">
|
|
487
|
-
<div class="page-info">
|
|
488
|
-
<div class="context">
|
|
489
|
-
<span>Next</span>
|
|
490
|
-
</div>
|
|
491
|
-
<div class="title">Contributing</div>
|
|
492
|
-
</div>
|
|
493
|
-
<svg><use href="#svg-arrow-right"></use></svg>
|
|
494
|
-
</a>
|
|
495
|
-
<a class="prev-page" href="memory">
|
|
496
|
-
<svg><use href="#svg-arrow-right"></use></svg>
|
|
497
|
-
<div class="page-info">
|
|
498
|
-
<div class="context">
|
|
499
|
-
<span>Previous</span>
|
|
500
|
-
</div>
|
|
501
|
-
|
|
502
|
-
<div class="title">Memory usage</div>
|
|
503
|
-
|
|
504
|
-
</div>
|
|
505
|
-
</a>
|
|
506
|
-
</div>
|
|
507
|
-
<div class="bottom-of-page">
|
|
508
|
-
<div class="left-details">
|
|
509
|
-
<div class="copyright">
|
|
510
|
-
Copyright © 2022, Niels Martignène
|
|
511
|
-
</div>
|
|
512
|
-
Made with <a href="https://www.sphinx-doc.org/">Sphinx</a> and <a class="muted-link" href="https://pradyunsg.me">@pradyunsg</a>'s
|
|
513
|
-
|
|
514
|
-
<a href="https://github.com/pradyunsg/furo">Furo</a>
|
|
515
|
-
|
|
516
|
-
</div>
|
|
517
|
-
<div class="right-details">
|
|
518
|
-
<div class="icons">
|
|
519
|
-
|
|
520
|
-
</div>
|
|
521
|
-
</div>
|
|
522
|
-
</div>
|
|
523
|
-
|
|
524
|
-
</footer>
|
|
525
|
-
</div>
|
|
526
|
-
<aside class="toc-drawer">
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
<div class="toc-sticky toc-scroll">
|
|
530
|
-
<div class="toc-title-container">
|
|
531
|
-
<span class="toc-title">
|
|
532
|
-
Contents
|
|
533
|
-
</span>
|
|
534
|
-
</div>
|
|
535
|
-
<div class="toc-tree-container">
|
|
536
|
-
<div class="toc-tree">
|
|
537
|
-
<ul>
|
|
538
|
-
<li><a class="reference internal" href="#">Benchmarks</a><ul>
|
|
539
|
-
<li><a class="reference internal" href="#overview">Overview</a></li>
|
|
540
|
-
<li><a class="reference internal" href="#linux-x86-64">Linux x86_64</a><ul>
|
|
541
|
-
<li><a class="reference internal" href="#rand-results">rand results</a></li>
|
|
542
|
-
<li><a class="reference internal" href="#atoi-results">atoi results</a></li>
|
|
543
|
-
<li><a class="reference internal" href="#raylib-results">Raylib results</a></li>
|
|
544
|
-
</ul>
|
|
545
|
-
</li>
|
|
546
|
-
<li><a class="reference internal" href="#windows-x86-64">Windows x86_64</a><ul>
|
|
547
|
-
<li><a class="reference internal" href="#id1">rand results</a></li>
|
|
548
|
-
<li><a class="reference internal" href="#id2">atoi results</a></li>
|
|
549
|
-
<li><a class="reference internal" href="#id3">Raylib results</a></li>
|
|
550
|
-
</ul>
|
|
551
|
-
</li>
|
|
552
|
-
<li><a class="reference internal" href="#running-benchmarks">Running benchmarks</a></li>
|
|
553
|
-
</ul>
|
|
554
|
-
</li>
|
|
555
|
-
</ul>
|
|
556
|
-
|
|
557
|
-
</div>
|
|
558
|
-
</div>
|
|
559
|
-
</div>
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
</aside>
|
|
563
|
-
</div>
|
|
564
|
-
</div><script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
|
|
565
|
-
<script src="_static/jquery.js"></script>
|
|
566
|
-
<script src="_static/underscore.js"></script>
|
|
567
|
-
<script src="_static/_sphinx_javascript_frameworks_compat.js"></script>
|
|
568
|
-
<script src="_static/doctools.js"></script>
|
|
569
|
-
<script src="_static/scripts/furo.js"></script>
|
|
570
|
-
</body>
|
|
571
|
-
</html>
|