koffi 1.2.4 → 1.3.0-rc.1

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.
Files changed (126) hide show
  1. package/README.md +7 -489
  2. package/benchmark/CMakeLists.txt +13 -9
  3. package/benchmark/raylib_node_raylib.js +67 -0
  4. package/build/qemu/1.3.0-rc.1/koffi_darwin_arm64.tar.gz +0 -0
  5. package/build/qemu/1.3.0-rc.1/koffi_darwin_x64.tar.gz +0 -0
  6. package/build/qemu/1.3.0-rc.1/koffi_freebsd_arm64.tar.gz +0 -0
  7. package/build/qemu/1.3.0-rc.1/koffi_freebsd_ia32.tar.gz +0 -0
  8. package/build/qemu/1.3.0-rc.1/koffi_freebsd_x64.tar.gz +0 -0
  9. package/build/qemu/1.3.0-rc.1/koffi_linux_arm32hf.tar.gz +0 -0
  10. package/build/qemu/1.3.0-rc.1/koffi_linux_arm64.tar.gz +0 -0
  11. package/build/qemu/1.3.0-rc.1/koffi_linux_ia32.tar.gz +0 -0
  12. package/build/qemu/1.3.0-rc.1/koffi_linux_riscv64hf64.tar.gz +0 -0
  13. package/build/qemu/1.3.0-rc.1/koffi_linux_x64.tar.gz +0 -0
  14. package/build/qemu/1.3.0-rc.1/koffi_openbsd_ia32.tar.gz +0 -0
  15. package/build/qemu/1.3.0-rc.1/koffi_openbsd_x64.tar.gz +0 -0
  16. package/build/qemu/1.3.0-rc.1/koffi_win32_arm64.tar.gz +0 -0
  17. package/build/qemu/1.3.0-rc.1/koffi_win32_ia32.tar.gz +0 -0
  18. package/build/qemu/1.3.0-rc.1/koffi_win32_x64.tar.gz +0 -0
  19. package/doc/Makefile +20 -0
  20. package/doc/_static/bench_linux.png +0 -0
  21. package/doc/_static/bench_windows.png +0 -0
  22. package/doc/_static/custom.css +22 -0
  23. package/doc/benchmarks.md +113 -0
  24. package/doc/benchmarks.xlsx +0 -0
  25. package/doc/conf.py +54 -0
  26. package/doc/contribute.md +115 -0
  27. package/doc/dist/doctrees/benchmarks.doctree +0 -0
  28. package/doc/dist/doctrees/contribute.doctree +0 -0
  29. package/doc/dist/doctrees/environment.pickle +0 -0
  30. package/doc/dist/doctrees/functions.doctree +0 -0
  31. package/doc/dist/doctrees/index.doctree +0 -0
  32. package/doc/dist/doctrees/memory.doctree +0 -0
  33. package/doc/dist/doctrees/platforms.doctree +0 -0
  34. package/doc/dist/doctrees/start.doctree +0 -0
  35. package/doc/dist/doctrees/types.doctree +0 -0
  36. package/doc/dist/html/.buildinfo +4 -0
  37. package/doc/dist/html/_sources/benchmarks.md.txt +113 -0
  38. package/doc/dist/html/_sources/contribute.md.txt +115 -0
  39. package/doc/dist/html/_sources/functions.md.txt +224 -0
  40. package/doc/dist/html/_sources/index.rst.txt +33 -0
  41. package/doc/dist/html/_sources/memory.md.txt +29 -0
  42. package/doc/dist/html/_sources/platforms.md.txt +17 -0
  43. package/doc/dist/html/_sources/start.md.txt +89 -0
  44. package/doc/dist/html/_sources/types.md.txt +514 -0
  45. package/doc/dist/html/_static/_sphinx_javascript_frameworks_compat.js +134 -0
  46. package/doc/dist/html/_static/basic.css +932 -0
  47. package/doc/dist/html/_static/bench_linux.png +0 -0
  48. package/doc/dist/html/_static/bench_windows.png +0 -0
  49. package/doc/dist/html/_static/custom.css +22 -0
  50. package/doc/dist/html/_static/debug.css +69 -0
  51. package/doc/dist/html/_static/doctools.js +264 -0
  52. package/doc/dist/html/_static/documentation_options.js +14 -0
  53. package/doc/dist/html/_static/file.png +0 -0
  54. package/doc/dist/html/_static/jquery-3.6.0.js +10881 -0
  55. package/doc/dist/html/_static/jquery.js +2 -0
  56. package/doc/dist/html/_static/language_data.js +199 -0
  57. package/doc/dist/html/_static/minus.png +0 -0
  58. package/doc/dist/html/_static/plus.png +0 -0
  59. package/doc/dist/html/_static/pygments.css +252 -0
  60. package/doc/dist/html/_static/scripts/furo-extensions.js +0 -0
  61. package/doc/dist/html/_static/scripts/furo.js +3 -0
  62. package/doc/dist/html/_static/scripts/furo.js.LICENSE.txt +7 -0
  63. package/doc/dist/html/_static/scripts/furo.js.map +1 -0
  64. package/doc/dist/html/_static/searchtools.js +531 -0
  65. package/doc/dist/html/_static/skeleton.css +296 -0
  66. package/doc/dist/html/_static/styles/furo-extensions.css +2 -0
  67. package/doc/dist/html/_static/styles/furo-extensions.css.map +1 -0
  68. package/doc/dist/html/_static/styles/furo.css +2 -0
  69. package/doc/dist/html/_static/styles/furo.css.map +1 -0
  70. package/doc/dist/html/_static/underscore-1.13.1.js +2042 -0
  71. package/doc/dist/html/_static/underscore.js +6 -0
  72. package/doc/dist/html/benchmarks.html +547 -0
  73. package/doc/dist/html/contribute.html +382 -0
  74. package/doc/dist/html/functions.html +530 -0
  75. package/doc/dist/html/genindex.html +249 -0
  76. package/doc/dist/html/index.html +342 -0
  77. package/doc/dist/html/memory.html +337 -0
  78. package/doc/dist/html/objects.inv +0 -0
  79. package/doc/dist/html/platforms.html +332 -0
  80. package/doc/dist/html/search.html +257 -0
  81. package/doc/dist/html/searchindex.js +1 -0
  82. package/doc/dist/html/start.html +367 -0
  83. package/doc/dist/html/types.html +1001 -0
  84. package/doc/functions.md +224 -0
  85. package/doc/index.rst +33 -0
  86. package/doc/make.bat +35 -0
  87. package/doc/memory.md +29 -0
  88. package/doc/platforms.md +17 -0
  89. package/doc/start.md +89 -0
  90. package/doc/types.md +514 -0
  91. package/package.json +5 -2
  92. package/qemu/qemu.js +41 -27
  93. package/qemu/registry/machines.json +59 -79
  94. package/qemu/registry/sha256sum.txt +4 -4
  95. package/src/abi_arm32.cc +20 -48
  96. package/src/abi_arm64.cc +18 -46
  97. package/src/abi_arm64_fwd.S +5 -0
  98. package/src/abi_riscv64.cc +19 -47
  99. package/src/abi_x64_sysv.cc +18 -46
  100. package/src/abi_x64_win.cc +19 -47
  101. package/src/abi_x86.cc +21 -49
  102. package/src/call.cc +505 -242
  103. package/src/call.hh +14 -7
  104. package/src/ffi.cc +47 -26
  105. package/src/ffi.hh +1 -1
  106. package/src/parser.cc +2 -20
  107. package/src/util.cc +50 -11
  108. package/src/util.hh +2 -0
  109. package/test/misc.c +31 -0
  110. package/test/sync.js +41 -4
  111. package/benchmark/atoi_cc.cc +0 -59
  112. package/build/qemu/1.2.4/koffi_darwin_arm64.tar.gz +0 -0
  113. package/build/qemu/1.2.4/koffi_darwin_x64.tar.gz +0 -0
  114. package/build/qemu/1.2.4/koffi_freebsd_arm64.tar.gz +0 -0
  115. package/build/qemu/1.2.4/koffi_freebsd_ia32.tar.gz +0 -0
  116. package/build/qemu/1.2.4/koffi_freebsd_x64.tar.gz +0 -0
  117. package/build/qemu/1.2.4/koffi_linux_arm.tar.gz +0 -0
  118. package/build/qemu/1.2.4/koffi_linux_arm64.tar.gz +0 -0
  119. package/build/qemu/1.2.4/koffi_linux_ia32.tar.gz +0 -0
  120. package/build/qemu/1.2.4/koffi_linux_riscv64.tar.gz +0 -0
  121. package/build/qemu/1.2.4/koffi_linux_x64.tar.gz +0 -0
  122. package/build/qemu/1.2.4/koffi_openbsd_ia32.tar.gz +0 -0
  123. package/build/qemu/1.2.4/koffi_openbsd_x64.tar.gz +0 -0
  124. package/build/qemu/1.2.4/koffi_win32_arm64.tar.gz +0 -0
  125. package/build/qemu/1.2.4/koffi_win32_ia32.tar.gz +0 -0
  126. package/build/qemu/1.2.4/koffi_win32_x64.tar.gz +0 -0
@@ -0,0 +1,22 @@
1
+ /* This program is free software: you can redistribute it and/or modify
2
+ it under the terms of the GNU Affero General Public License as published by
3
+ the Free Software Foundation, either version 3 of the License, or
4
+ (at your option) any later version.
5
+
6
+ This program is distributed in the hope that it will be useful,
7
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
8
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9
+ GNU Affero General Public License for more details.
10
+
11
+ You should have received a copy of the GNU Affero General Public License
12
+ along with this program. If not, see https://www.gnu.org/licenses/. */
13
+
14
+ aside.footnote {
15
+ display: flex;
16
+ margin-top: 6px;
17
+ }
18
+
19
+ aside.footnote > p {
20
+ margin: 0;
21
+ margin-left: 1rem;
22
+ }
@@ -0,0 +1,113 @@
1
+ # Benchmarks
2
+
3
+ Here is a quick overview of the execution time of Koffi calls on three test cases (one based around rand, one based on atoi and one based on Raylib) compared to theoretical ideal implementations.
4
+
5
+ <table style="margin: 0 auto;">
6
+ <tr>
7
+ <td><img src="_static/bench_linux.png" alt="Linux performance" style="width: 350px;"/></td>
8
+ <td><img src="_static/bench_windows.png" alt="Windows performance" style="width: 350px;"/></td>
9
+ </tr>
10
+ </table>
11
+
12
+ These results are detailed and explained below, and compared to node-ffi/node-ffi-napi.
13
+
14
+ ## rand results
15
+
16
+ This test is based around repeated calls to a simple standard C function atoi, and has three implementations:
17
+
18
+ - 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.
19
+ - the second one calls atoi through Koffi
20
+ - the third one uses the official Node.js FFI implementation, node-ffi-napi
21
+
22
+ Because rand is a pretty small function, the FFI overhead is clearly visible.
23
+
24
+ ### Linux x86_64
25
+
26
+ The results below were measured on my x86_64 Linux machine (AMD® Ryzen™ 7 4700U):
27
+
28
+ Benchmark | Iterations | Total time | Overhead
29
+ ------------- | ---------- | ----------- | ----------
30
+ rand_napi | 20000000 | 1.44s | (baseline)
31
+ rand_koffi | 20000000 | 2.60s | x1.81
32
+ rand_node_ffi | 20000000 | 107.58s | x75
33
+
34
+ ### Windows x86_64
35
+
36
+ The results below were measured on my x86_64 Windows machine (Intel® Core™ i5-4460):
37
+
38
+ Benchmark | Iterations | Total time | Overhead
39
+ ------------- | ---------- | ----------- | ----------
40
+ rand_napi | 20000000 | 2.10s | (baseline)
41
+ rand_koffi | 20000000 | 3.87s | x1.84
42
+ rand_node_ffi | 20000000 | 87.84s | x42
43
+
44
+ ## atoi results
45
+
46
+ 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.
47
+
48
+ Because rand is a pretty small function, the FFI overhead is clearly visible.
49
+
50
+ ### Linux x86_64
51
+
52
+ The results below were measured on my x86_64 Linux machine (AMD® Ryzen™ 7 4700U):
53
+
54
+ Benchmark | Iterations | Total time | Overhead
55
+ ------------- | ---------- | ----------- | ----------
56
+ atoi_napi | 20000000 | 2.97s | (baseline)
57
+ atoi_koffi | 20000000 | 5.07s | x1.71
58
+ atoi_node_ffi | 20000000 | 693.16s | x233
59
+
60
+ ### Windows x86_64
61
+
62
+ The results below were measured on my x86_64 Windows machine (Intel® Core™ i5-4460):
63
+
64
+ Benchmark | Iterations | Total time | Overhead
65
+ ------------- | ---------- | ----------- | ----------
66
+ atoi_napi | 20000000 | 2.97s | (baseline)
67
+ atoi_koffi | 20000000 | 5.91s | x1.99
68
+ atoi_node_ffi | 20000000 | 479.34s | x161
69
+
70
+ ## Raylib results
71
+
72
+ 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:
73
+
74
+ - Baseline: Full C++ version of the code (no JS)
75
+ - [node-raylib](https://github.com/RobLoach/node-raylib): This is a native wrapper implemented with N-API
76
+
77
+ ### Linux x86_64
78
+
79
+ The results below were measured on my x86_64 Linux machine (AMD® Ryzen™ 7 4700U):
80
+
81
+ Benchmark | Iterations | Total time | Overhead
82
+ --------------- | ---------- | ----------- | ----------
83
+ raylib_cc | 100 | 9.31s | (baseline)
84
+ raylib_node_raylib | 100 | 10.90s | x1.17
85
+ raylib_koffi | 100 | 12.86s | x1.38
86
+ raylib_node_ffi | 100 | 35.76s | x3.84
87
+
88
+ ### Windows x86_64
89
+
90
+ The results below were measured on my x86_64 Windows machine (Intel® Core™ i5-4460):
91
+
92
+ Benchmark | Iterations | Total time | Overhead
93
+ --------------- | ---------- | ----------- | ----------
94
+ raylib_cc | 100 | 10.67s | (baseline)
95
+ raylib_node_raylib | 100 | 12.05s | x1.13
96
+ raylib_koffi | 100 | 14.84s | x1.39
97
+ raylib_node_ffi | 100 | 44.63s | x4.18
98
+
99
+ ## Running benchmarks
100
+
101
+ Open a console, go to `koffi/benchmark` and run `../../cnoke/cnoke.js` (or `node ..\..\cnoke\cnoke.js` on Windows) before doing anything else.
102
+
103
+ ```sh
104
+ cd koffi/benchmark
105
+ node ../../cnoke/cnoke.js
106
+ ```
107
+
108
+ Once this is done, you can execute each implementation, e.g. `build/raylib_cc` or `node ./atoi_koffi.js`. You can optionally define a custom number of iterations, e.g. `node ./atoi_koffi.js 10000000`.
109
+
110
+ ```sh
111
+ node ./atoi_napi.js
112
+ node ./atoi_koffi.js
113
+ ```
Binary file
package/doc/conf.py ADDED
@@ -0,0 +1,54 @@
1
+ # -- Project information -----------------------------------------------------
2
+
3
+ project = 'Koffi'
4
+ copyright = '2022, Niels Martignène'
5
+ author = 'Niels Martignène'
6
+ version = '1.2.4'
7
+ revision = '1.2.4'
8
+
9
+ # -- General configuration ---------------------------------------------------
10
+
11
+ extensions = [
12
+ 'myst_parser',
13
+ 'sphinx.ext.autosectionlabel'
14
+ ]
15
+
16
+ # Add any paths that contain templates here, relative to this directory.
17
+ templates_path = ['_templates']
18
+
19
+ exclude_patterns = []
20
+
21
+ # -- Options for HTML output -------------------------------------------------
22
+
23
+ html_title = 'Koffi'
24
+
25
+ html_theme = 'furo'
26
+
27
+ html_static_path = ['_static']
28
+
29
+ html_theme_options = {
30
+ 'light_css_variables': {
31
+ 'color-brand-primary': '#FF6600',
32
+ 'color-brand-content': '#FF6600'
33
+ },
34
+ 'dark_css_variables': {
35
+ 'color-brand-primary': '#FF6600',
36
+ 'color-brand-content': '#FF6600'
37
+ }
38
+ }
39
+
40
+ html_link_suffix = ''
41
+
42
+ html_css_files = ['custom.css']
43
+
44
+ # -- MyST parser options -------------------------------------------------
45
+
46
+ myst_enable_extensions = [
47
+ 'linkify'
48
+ ]
49
+
50
+ myst_heading_anchors = 3
51
+
52
+ myst_linkify_fuzzy_links = False
53
+
54
+ myst_number_code_blocks = ['c', 'js']
@@ -0,0 +1,115 @@
1
+ # Contributing
2
+
3
+ ## Bugs and feature requests
4
+
5
+ Use the official repository (named Luigi, because this is a monorepo containing multiple projects) for bugs, ideas and features requests.
6
+
7
+ Go here: https://github.com/Koromix/luigi/issues
8
+
9
+ ## Build from source
10
+
11
+ We provide prebuilt binaries, packaged in the NPM archive, so in most cases it should be as simple as `npm install koffi`. If you want to hack Koffi or use a specific platform, follow the instructions below.
12
+
13
+ ### Windows
14
+
15
+ First, make sure the following dependencies are met:
16
+
17
+ - The "Desktop development with C++" workload from [Visual Studio 2022 or 2019](https://visualstudio.microsoft.com/downloads/) or the "C++ build tools" workload from the [Build Tools](https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022), with the default optional components.
18
+ - [CMake meta build system](https://cmake.org/)
19
+ - [Node.js](https://nodejs.org/) 12 or later
20
+
21
+ Once this is done, run this command _from the test or the benchmark directory_ (depending on what you want to build):
22
+
23
+ ```sh
24
+ cd koffi/test # or cd koffi/benchmark
25
+ node ../../cnoke/cnoke.js
26
+ ```
27
+
28
+ ### Other platforms
29
+
30
+ Make sure the following dependencies are met:
31
+
32
+ - `gcc` and `g++` >= 8.3 or newer
33
+ - GNU Make 3.81 or newer
34
+ - [CMake meta build system](https://cmake.org/)
35
+ - [Node.js](https://nodejs.org/) 12 or later
36
+
37
+ Once this is done, run this command _from the test or the benchmark directory_ (depending on what you want to build):
38
+
39
+ ```sh
40
+ cd koffi/test # or cd koffi/benchmark
41
+ node ../../cnoke/cnoke.js
42
+ ```
43
+
44
+ ## Running tests
45
+
46
+ Koffi is tested on multiple architectures using emulated (accelerated when possible) QEMU machines. First, you need to install qemu packages, such as `qemu-system` (or even `qemu-system-gui`) on Ubuntu.
47
+
48
+ These machines are not included directly in this repository (for license and size reasons), but they are available here: https://koromix.dev/files/machines/
49
+
50
+ For example, if you want to run the tests on Debian ARM64, run the following commands:
51
+
52
+ ```sh
53
+ cd luigi/koffi/qemu/
54
+ wget -q -O- https://koromix.dev/files/machines/qemu_debian_arm64.tar.zst | zstd -d | tar xv
55
+ sha256sum -c --ignore-missing registry/sha256sum.txt
56
+ ```
57
+
58
+ Note that the machine disk content may change each time the machine runs, so the checksum test will fail once a machine has been used at least once.
59
+
60
+ And now you can run the tests with:
61
+
62
+ ```sh
63
+ node qemu.js # Several options are available, use --help
64
+ ```
65
+
66
+ And be patient, this can be pretty slow for emulated machines. The Linux machines have and use ccache to build Koffi, so subsequent build steps will get much more tolerable.
67
+
68
+ By default, machines are started and stopped for each test. But you can start the machines ahead of time and run the tests multiple times instead:
69
+
70
+ ```sh
71
+ node qemu.js start # Start the machines
72
+ node qemu.js # Test (without shutting down)
73
+ node qemu.js # Test again
74
+ node qemu.js stop # Stop everything
75
+ ```
76
+
77
+ You can also restrict the test to a subset of machines:
78
+
79
+ ```sh
80
+ # Full test cycle
81
+ node qemu.js test debian_x64 debian_i386
82
+
83
+ # Separate start, test, shutdown
84
+ node qemu.js start debian_x64 debian_i386
85
+ node qemu.js test debian_x64 debian_i386
86
+ node qemu.js stop
87
+ ```
88
+
89
+ Finally, you can join a running machine with SSH with the following shortcut, if you need to do some debugging or any other manual procedure:
90
+
91
+ ```sh
92
+ node qemu.js ssh debian_i386
93
+ ```
94
+
95
+ Each machine is configured to run a VNC server available locally, which you can use to access the display, using KRDC or any other compatible viewer. Use the `info` command to get the VNC port.
96
+
97
+ ```sh
98
+ node qemu.js info debian_x64
99
+ ```
100
+
101
+ ## Todo list
102
+
103
+ After the release of version 1.3.0, the current priorities for the next major release are:
104
+
105
+ - Automate Windows/AArch64 (qemu) and macOS/AArch64 (how?) tests and builds
106
+ - Create a real-world example, using several libraries (Raylib, SQLite, libsodium) to illustrate how to work with various C API styles
107
+
108
+ The following features are also planned eventually, not necessarily in that order:
109
+
110
+ - Optimize passing of structs and arrays, with separate HFA-specific helper functions
111
+ - Add simple struct type parser
112
+ - Add more ways to manually encode and decode various types to and from byte arrays
113
+ - Add support for unions
114
+ - Provide better ways to automatically deal with caller/heap-allocated memory (strings, etc.)
115
+ - Port Koffi to PowerPC (POWER9+) ABI
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,4 @@
1
+ # Sphinx build info version 1
2
+ # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
3
+ config: 1029792c9b37058f12795e72139e7221
4
+ tags: 645f666f9bcd5a90fca523b33c5a78b7
@@ -0,0 +1,113 @@
1
+ # Benchmarks
2
+
3
+ Here is a quick overview of the execution time of Koffi calls on three test cases (one based around rand, one based on atoi and one based on Raylib) compared to theoretical ideal implementations.
4
+
5
+ <table style="margin: 0 auto;">
6
+ <tr>
7
+ <td><img src="_static/bench_linux.png" alt="Linux performance" style="width: 350px;"/></td>
8
+ <td><img src="_static/bench_windows.png" alt="Windows performance" style="width: 350px;"/></td>
9
+ </tr>
10
+ </table>
11
+
12
+ These results are detailed and explained below, and compared to node-ffi/node-ffi-napi.
13
+
14
+ ## rand results
15
+
16
+ This test is based around repeated calls to a simple standard C function atoi, and has three implementations:
17
+
18
+ - 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.
19
+ - the second one calls atoi through Koffi
20
+ - the third one uses the official Node.js FFI implementation, node-ffi-napi
21
+
22
+ Because rand is a pretty small function, the FFI overhead is clearly visible.
23
+
24
+ ### Linux x86_64
25
+
26
+ The results below were measured on my x86_64 Linux machine (AMD® Ryzen™ 7 4700U):
27
+
28
+ Benchmark | Iterations | Total time | Overhead
29
+ ------------- | ---------- | ----------- | ----------
30
+ rand_napi | 20000000 | 1.44s | (baseline)
31
+ rand_koffi | 20000000 | 2.60s | x1.81
32
+ rand_node_ffi | 20000000 | 107.58s | x75
33
+
34
+ ### Windows x86_64
35
+
36
+ The results below were measured on my x86_64 Windows machine (Intel® Core™ i5-4460):
37
+
38
+ Benchmark | Iterations | Total time | Overhead
39
+ ------------- | ---------- | ----------- | ----------
40
+ rand_napi | 20000000 | 2.10s | (baseline)
41
+ rand_koffi | 20000000 | 3.87s | x1.84
42
+ rand_node_ffi | 20000000 | 87.84s | x42
43
+
44
+ ## atoi results
45
+
46
+ 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.
47
+
48
+ Because rand is a pretty small function, the FFI overhead is clearly visible.
49
+
50
+ ### Linux x86_64
51
+
52
+ The results below were measured on my x86_64 Linux machine (AMD® Ryzen™ 7 4700U):
53
+
54
+ Benchmark | Iterations | Total time | Overhead
55
+ ------------- | ---------- | ----------- | ----------
56
+ atoi_napi | 20000000 | 2.97s | (baseline)
57
+ atoi_koffi | 20000000 | 5.07s | x1.71
58
+ atoi_node_ffi | 20000000 | 693.16s | x233
59
+
60
+ ### Windows x86_64
61
+
62
+ The results below were measured on my x86_64 Windows machine (Intel® Core™ i5-4460):
63
+
64
+ Benchmark | Iterations | Total time | Overhead
65
+ ------------- | ---------- | ----------- | ----------
66
+ atoi_napi | 20000000 | 2.97s | (baseline)
67
+ atoi_koffi | 20000000 | 5.91s | x1.99
68
+ atoi_node_ffi | 20000000 | 479.34s | x161
69
+
70
+ ## Raylib results
71
+
72
+ 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:
73
+
74
+ - Baseline: Full C++ version of the code (no JS)
75
+ - [node-raylib](https://github.com/RobLoach/node-raylib): This is a native wrapper implemented with N-API
76
+
77
+ ### Linux x86_64
78
+
79
+ The results below were measured on my x86_64 Linux machine (AMD® Ryzen™ 7 4700U):
80
+
81
+ Benchmark | Iterations | Total time | Overhead
82
+ --------------- | ---------- | ----------- | ----------
83
+ raylib_cc | 100 | 9.31s | (baseline)
84
+ raylib_node_raylib | 100 | 10.90s | x1.17
85
+ raylib_koffi | 100 | 12.86s | x1.38
86
+ raylib_node_ffi | 100 | 35.76s | x3.84
87
+
88
+ ### Windows x86_64
89
+
90
+ The results below were measured on my x86_64 Windows machine (Intel® Core™ i5-4460):
91
+
92
+ Benchmark | Iterations | Total time | Overhead
93
+ --------------- | ---------- | ----------- | ----------
94
+ raylib_cc | 100 | 10.67s | (baseline)
95
+ raylib_node_raylib | 100 | 12.05s | x1.13
96
+ raylib_koffi | 100 | 14.84s | x1.39
97
+ raylib_node_ffi | 100 | 44.63s | x4.18
98
+
99
+ ## Running benchmarks
100
+
101
+ Open a console, go to `koffi/benchmark` and run `../../cnoke/cnoke.js` (or `node ..\..\cnoke\cnoke.js` on Windows) before doing anything else.
102
+
103
+ ```sh
104
+ cd koffi/benchmark
105
+ node ../../cnoke/cnoke.js
106
+ ```
107
+
108
+ Once this is done, you can execute each implementation, e.g. `build/raylib_cc` or `node ./atoi_koffi.js`. You can optionally define a custom number of iterations, e.g. `node ./atoi_koffi.js 10000000`.
109
+
110
+ ```sh
111
+ node ./atoi_napi.js
112
+ node ./atoi_koffi.js
113
+ ```
@@ -0,0 +1,115 @@
1
+ # Contributing
2
+
3
+ ## Bugs and feature requests
4
+
5
+ Use the official repository (named Luigi, because this is a monorepo containing multiple projects) for bugs, ideas and features requests.
6
+
7
+ Go here: https://github.com/Koromix/luigi/issues
8
+
9
+ ## Build from source
10
+
11
+ We provide prebuilt binaries, packaged in the NPM archive, so in most cases it should be as simple as `npm install koffi`. If you want to hack Koffi or use a specific platform, follow the instructions below.
12
+
13
+ ### Windows
14
+
15
+ First, make sure the following dependencies are met:
16
+
17
+ - The "Desktop development with C++" workload from [Visual Studio 2022 or 2019](https://visualstudio.microsoft.com/downloads/) or the "C++ build tools" workload from the [Build Tools](https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022), with the default optional components.
18
+ - [CMake meta build system](https://cmake.org/)
19
+ - [Node.js](https://nodejs.org/) 12 or later
20
+
21
+ Once this is done, run this command _from the test or the benchmark directory_ (depending on what you want to build):
22
+
23
+ ```sh
24
+ cd koffi/test # or cd koffi/benchmark
25
+ node ../../cnoke/cnoke.js
26
+ ```
27
+
28
+ ### Other platforms
29
+
30
+ Make sure the following dependencies are met:
31
+
32
+ - `gcc` and `g++` >= 8.3 or newer
33
+ - GNU Make 3.81 or newer
34
+ - [CMake meta build system](https://cmake.org/)
35
+ - [Node.js](https://nodejs.org/) 12 or later
36
+
37
+ Once this is done, run this command _from the test or the benchmark directory_ (depending on what you want to build):
38
+
39
+ ```sh
40
+ cd koffi/test # or cd koffi/benchmark
41
+ node ../../cnoke/cnoke.js
42
+ ```
43
+
44
+ ## Running tests
45
+
46
+ Koffi is tested on multiple architectures using emulated (accelerated when possible) QEMU machines. First, you need to install qemu packages, such as `qemu-system` (or even `qemu-system-gui`) on Ubuntu.
47
+
48
+ These machines are not included directly in this repository (for license and size reasons), but they are available here: https://koromix.dev/files/machines/
49
+
50
+ For example, if you want to run the tests on Debian ARM64, run the following commands:
51
+
52
+ ```sh
53
+ cd luigi/koffi/qemu/
54
+ wget -q -O- https://koromix.dev/files/machines/qemu_debian_arm64.tar.zst | zstd -d | tar xv
55
+ sha256sum -c --ignore-missing registry/sha256sum.txt
56
+ ```
57
+
58
+ Note that the machine disk content may change each time the machine runs, so the checksum test will fail once a machine has been used at least once.
59
+
60
+ And now you can run the tests with:
61
+
62
+ ```sh
63
+ node qemu.js # Several options are available, use --help
64
+ ```
65
+
66
+ And be patient, this can be pretty slow for emulated machines. The Linux machines have and use ccache to build Koffi, so subsequent build steps will get much more tolerable.
67
+
68
+ By default, machines are started and stopped for each test. But you can start the machines ahead of time and run the tests multiple times instead:
69
+
70
+ ```sh
71
+ node qemu.js start # Start the machines
72
+ node qemu.js # Test (without shutting down)
73
+ node qemu.js # Test again
74
+ node qemu.js stop # Stop everything
75
+ ```
76
+
77
+ You can also restrict the test to a subset of machines:
78
+
79
+ ```sh
80
+ # Full test cycle
81
+ node qemu.js test debian_x64 debian_i386
82
+
83
+ # Separate start, test, shutdown
84
+ node qemu.js start debian_x64 debian_i386
85
+ node qemu.js test debian_x64 debian_i386
86
+ node qemu.js stop
87
+ ```
88
+
89
+ Finally, you can join a running machine with SSH with the following shortcut, if you need to do some debugging or any other manual procedure:
90
+
91
+ ```sh
92
+ node qemu.js ssh debian_i386
93
+ ```
94
+
95
+ Each machine is configured to run a VNC server available locally, which you can use to access the display, using KRDC or any other compatible viewer. Use the `info` command to get the VNC port.
96
+
97
+ ```sh
98
+ node qemu.js info debian_x64
99
+ ```
100
+
101
+ ## Todo list
102
+
103
+ After the release of version 1.3.0, the current priorities for the next major release are:
104
+
105
+ - Automate Windows/AArch64 (qemu) and macOS/AArch64 (how?) tests and builds
106
+ - Create a real-world example, using several libraries (Raylib, SQLite, libsodium) to illustrate how to work with various C API styles
107
+
108
+ The following features are also planned eventually, not necessarily in that order:
109
+
110
+ - Optimize passing of structs and arrays, with separate HFA-specific helper functions
111
+ - Add simple struct type parser
112
+ - Add more ways to manually encode and decode various types to and from byte arrays
113
+ - Add support for unions
114
+ - Provide better ways to automatically deal with caller/heap-allocated memory (strings, etc.)
115
+ - Port Koffi to PowerPC (POWER9+) ABI