- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试通过将现有的 unicode 排序规则库(用 Erlang 编写)重写为 NIF 实现来优化它。主要原因是排序规则是 CPU 密集型操作。
实现链接:https://github.com/abhi-bit/merger
通过基于纯 Erlang 的优先级队列对 1M 行进行 Unicode 排序:
erlc *.erl; ERL_LIBS="..:$ERL_LIBS" erl -noshell -s perf_couch_skew main 1000000 -s init stop
Queue size: 1000000
12321.649 ms
通过基于 NIF 的二项式堆对 1M 行进行 Unicode 排序规则:
erlc *.erl; ERL_LIBS="..:$ERL_LIBS" erl -noshell -s perf_merger main 1000000 -s init stop
Queue size: 1000000
15871.965 ms
这很不寻常,我预计它可能会快 10 倍。
我打开了eprof
/fprof
,但是对于NIF模块来说它们并没有多大用处,下面是eprof
所说的关于突出功能
FUNCTION CALLS % TIME [uS / CALLS]
-------- ----- --- ---- [----------]
merger:new/0 1 0.00 0 [ 0.00]
merger:new/2 1 0.00 0 [ 0.00]
merger:size/1 100002 0.31 19928 [ 0.20]
merger:in/3 100000 3.29 210620 [ 2.11]
erlang:put/2 2000000 6.63 424292 [ 0.21]
merger:out/1 100000 14.35 918834 [ 9.19]
我确信,NIF 实现可以更快,因为我有一个基于使用动态数组的二进制堆的 unicode 排序规则的纯 C 实现,而且速度要快得多。
$ make
gcc -I/usr/local/Cellar/icu4c/55.1/include -L/usr/local/Cellar/icu4c/55.1/lib min_heap.c collate_json.c kway_merge.c kway_merge_test.c -o output -licui18n -licuuc -licudata
./output
Merging 1 arrays each of size 1000000
mergeKArrays took 84.626ms
我在这里提出的具体问题:
perf top
来查看函数调用,顶部的函数调用(显示了一些十六进制地址)来自“beam.smp”。最佳答案
调用 NIF 的开销很小。当 Erlang 运行时加载一个加载 NIF 的模块时,它会使用模拟器指令修补该模块的 Beam 代码以调用 NIF。在调用实现 NIF 的 C 函数之前,指令本身仅执行少量设置。这不是导致性能问题的区域。
分析 NIF 与分析任何其他 C/C++ 代码非常相似。从您的 Makefile 来看,您似乎正在 OS X 上开发此代码。在该平台上,假设您安装了 XCode,则可以使用 Instruments application使用 CPU Samples 工具来查看您的代码在哪里花费了大部分时间。在 Linux 上,您可以使用 callgrind tool of valgrind与 Erlang emulator built with valgrind support 一起衡量您的代码。
例如,如果您在代码中使用这些工具,您会发现 perf_merger:main/1
大部分时间都花在 merger_nif_heap_get
上,这反过来,在 CollateJSON
中花费了大量时间。该函数似乎调用了 convertUTF8toUChar
和 createStringFromJSON
相当多。您的 NIF 似乎还执行了大量内存分配。这些是您应该重点关注的领域,以加快您的代码速度。
关于c - unicode 排序规则 NIF 运行速度比纯 Erlang 实现慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34557134/
在实现 NIF 时,Dialyzer 给了我 Function crc16/1 has no local return 可能是因为我做退出在 .erl 模块中(如官方文档推荐): -module(my
我正在编写一些 Erlang 代码,它基本上从 TCP 连接接受一些二进制数据,然后使用 C nif 解密数据并返回解密的数据。 问题是我似乎无法弄清楚如何修改传入的二进制文件。 这是我正在使用的功能
我会想,如果我所做的只是 1) 加载一个 NIF 库,2) 执行我的 new/0 方法,3) 通过 F() 释放一切,然后 4) erlang:garbage:collect()我会回到内存的起点。事
我正在尝试为简单的线性代数实现 NIF。这是我的矩阵内部结构: typedef struct la_matrix { uint rows, columns; double **data; }
我创建了一个 DLL“Addition.dll”,我在其中实现了 hello 函数这些是我用于创建库的文件: main.cpp : #include "main.h" //Hello function
我正在试验 NIF,但我对 Erlang 使用的数字类型感到困惑,因为我对自己的精确度感到有些奇怪。 这是一个例子: erlang:band(18446744073709551614, 5) == 4
我对 Erlang NIF 中的线程有一个小问题。您可以在这里查看我的代码:http://pastebin.com/HMCj24Jp .问题是,当我启动线程时,它需要一些参数并启动 generate_
我有一个通过串行端口实现特殊协议(protocol)的 C++ 代码。代码是多线程的,内部轮询串口并做自己的循环处理。我想从 erlang 调用这个驱动程序并接收来自这个驱动程序的事件。我担心的是这个
我有点困惑,当我创建一个脏 NIF(例如,通过在其 ErlNifFunc 条目中为脏 NIF 设置适当的标志值)时,这会创建一个在脏线程上运行的脏调度程序。 我知道我只能有 N 个 cpu-bond
如果我自己编写 escript,我可以使用 nif,但是当我使用 rebar escriptize 时,找不到 nif 函数。我认为这是因为 *.so 对象没有像 Beam 文件那样被打包。这是一个简
NIF 实现可以使用常规 C/C++ 线程锁定原语还是必须使用 NIF API(enif_mutex_lock(..)、enif_mutex_create(..)、 等) 最佳答案 来自 nif do
我发现Elixir程序可以通过NIFs (native implemented functions)或OS-level ports运行C代码。阅读了这些链接和类似链接后,我不清楚何时使用一种或另一种方
我打算使用 NIF 为我计划在 Erlang 中编写代码的应用程序操作二进制文件。下面给出了 NIF 的 cpp 文件和 erl 文件的要点链接。 [Erl 要点链接] https://gist.gi
是否可以从 NIF 调用 Erlang 函数(回调函数)? 我阅读了文档(http://www.erlang.org/doc/man/erl_nif.html),但没有找到如何做到这一点。 最佳答案
我观察到 C NIF 在被许多 Erlang 进程同时调用时的阻塞行为。可以做成非阻塞的吗?这里有我无法理解的互斥锁吗? 附言在特定的 PID 调用它的情况下,可以通过使其 sleep 一百个微秒来测
在编写 Erlang C NIF 时,如何将用 C 创建的指针(比如说数组)返回到 Erlang,以便稍后在另一个 NIF 调用中由同一 Erlang 进程使用? #define LENGTH =
我尝试使用 cygwin gcc 在 Windows 上编译一个 erlang nif 插件。它编译正常,但链接器出现一些错误: 对 `_enif_get_int' 的 undefined refer
我在尝试将我的共享库(erlang nif)链接到另一个使用 dlopen 加载其他共享库(插件)的共享库(libpurple)时遇到问题。 问题是 mylib.so 链接到 libpurple.so
当 Erlang VM beam 运行一些用 C 编写的代码时,其他用 Erlang 编写的进程没有被调度。例如: static ERL_NIF_TERM nifsleep(ErlNi
我正在使用 NIF 进行 C-Erlang 集成,但在初始化 Binary 时遇到了一些问题并添加 char*指向它的数据。 我是这样做的: ErlNifBinary *output_binary;
我是一名优秀的程序员,十分优秀!