我正在研究应用程序中的性能热点,它将50%的时间花在memmove(3)上.应用程序将数百万个4字节整数插入到已排序的数组中,并使用memmove将数据"向右"移位,以便为插入的值腾出空间.
我的期望是复制内存非常快,我很惊讶在memmove上花了这么多时间.但后来我认为memmove很慢,因为它正在移动重叠区域,这必须在紧密的循环中实现,而不是复制大页面的内存.我写了一个小的微基准测试,以确定memcpy和memmove之间是否存在性能差异,期望memcpy能够取胜.
我在两台机器(核心i5,核心i7)上运行我的基准测试,看到memmove实际上比memcpy更快,在旧核心i7上甚至快了两倍!现在我正在寻找解释.
这是我的基准.它用memcpy复制100 mb,然后用memmove移动大约100 mb; 来源和目的地重叠.尝试了源和目的地的各种"距离".每次测试运行10次,打印平均时间.
https://gist.github.com/cruppstahl/78a57cdf937bca3d062c
以下是Core i5的结果(Linux 3.5.0-54-generic#81~precision1-Ubuntu SMP x86_64 GNU/Linux,gcc是4.6.3(Ubuntu/Linaro 4.6.3-1ubuntu5).括号中的数字是源和目的地之间的距离(间隙大小):
memcpy 0.0140074
memmove (002) 0.0106168
memmove (004) 0.01065
memmove (008) 0.0107917
memmove (016) 0.0107319
memmove (032) 0.0106724
memmove (064) 0.0106821
memmove (128) 0.0110633
Run Code Online (Sandbox Code Playgroud)
Memmove实现为SSE优化的汇编代码,从后到前复制.它使用硬件预取将数据加载到缓存中,并将128个字节复制到XMM寄存器,然后将它们存储在目标中.
(memcpy-ssse3-back.S,第1650行)
L(gobble_ll_loop):
prefetchnta -0x1c0(%rsi)
prefetchnta -0x280(%rsi)
prefetchnta -0x1c0(%rdi)
prefetchnta -0x280(%rdi)
sub $0x80, %rdx
movdqu -0x10(%rsi), %xmm1
movdqu -0x20(%rsi), %xmm2
movdqu -0x30(%rsi), %xmm3
movdqu -0x40(%rsi), %xmm4
movdqu -0x50(%rsi), %xmm5
movdqu -0x60(%rsi), %xmm6
movdqu -0x70(%rsi), %xmm7
movdqu -0x80(%rsi), %xmm8
movdqa %xmm1, …Run Code Online (Sandbox Code Playgroud) 我正在尝试将一个键值数据库集成到Spark并提出一些问题.我是Spark初学者,已经阅读了很多并运行了一些样本,但没有太复杂.
场景:
我正在使用一个小型hdfs集群将传入的消息存储在数据库中.群集有5个节点,数据分为5个分区.每个分区都存储在单独的数据库文件中.因此,每个节点都可以处理自己的数据分区.
问题:
数据库软件的接口基于JNI,数据库本身以C实现.由于技术原因,数据库软件一次只能维护一个活动连接.只能有一个JVM进程连接到数据库.
由于此限制,读取和写入数据库必须经过相同的JVM过程.
(背景信息:数据库嵌入到进程中.它是基于文件的,一次只能打开一个进程.我可以让它在一个单独的进程中运行,但由于IPC开销,这会慢一点.我的应用程序将执行许多全表扫描.其他写入将被批处理并且不是时间关键的.)
解决方案:
我在脑海中有一些想法如何解决这个问题,但我不知道它们是否适用于Spark.
也许有可能神奇地将Spark配置为每个节点只有一个我专有的InputFormat实例.
如果我的InputFormat第一次使用,它会启动一个单独的线程来创建数据库连接.然后,该线程将继续作为守护进程,并且只要JVM存在,它就会存在.这仅在每个节点只有一个JVM时才有效.如果Spark在同一节点上启动多个JVM,那么每个JVM都会启动自己的数据库线程,这不起作用.
将我的数据库连接移动到每个节点的单独JVM进程,然后我的InputFormat使用IPC连接到此进程.正如我所说,我想避免这种情况.
或者也许你有另一个更好的主意?
我最喜欢的解决方案是#1,紧接着是#2.
感谢您的任何评论和回答!
我使用boost :: python来包装一个C++类.这个类不允许复制构造函数,但python模块总是想创建一个.
C++类看起来像这样(简化)
class Foo {
public:
Foo(const char *name); // constructor
private:
ByteArray m_bytearray;
};
Run Code Online (Sandbox Code Playgroud)
ByteArray类继承自boost :: noncopyable,因此Foo没有复制构造函数.
这是Python模块存根:
BOOST_PYTHON_MODULE(Foo)
{
class_<Foo>("Foo", init<const char *>())
;
}
Run Code Online (Sandbox Code Playgroud)
在编译boost :: python模块时,我得到的错误是无法创建Foo的复制构造函数,因为ByteArray继承自boost :: noncopyable.
如何在我的python模块中禁用复制构造函数?
谢谢Christoph
我想用Rust,Hyper和websocket-rs编写一个Web服务器.Web服务器必须能够在同一端口上处理http请求和websocket请求.我使用官方样本(async-server.rs:https://github.com/cyderize/rust-websocket/blob/master/examples/async-server.rs)并尝试修改它.我的想法是改变错误处理.如果客户端的请求是一个简单的http请求,那么不会返回错误,而是产生一个处理请求的未来.
基于另一个SO问题(如何在使用rust-websocket时处理错误,以便只有那个连接失败而不是整个程序?)我改变了样本中的错误处理.
这是旧代码:
.map_err(|InvalidConnection {error, ..}| {
println!("Error:{:?}",error);
return error;
})
Run Code Online (Sandbox Code Playgroud)
这是我的新代码:
.map(Some).or_else(|_| -> Result<_, ()> {
// SPAWN THE FUTURE
Ok(None)
})
Run Code Online (Sandbox Code Playgroud)
这是我被困的地方.示例代码调用一个函数spawn_future,该函数需要一个upgrade.reject()在我的代码中不可用的parameter(),因为我无法访问upgrade结构.我尝试了一些其他的东西(即调用handle.spawn_fn),但编译器从不喜欢我做的事情.(我可以粘贴一些编译器错误,但我认为它们不会提高我帖子的质量.)
这是我的问题:编写可以在同一端口上处理http请求和websocket请求的异步服务器的推荐方法是什么?如果我的方法是正确的:你能帮我填一下SPAWN THE FUTURE吗?
附加上下文(如果你还没有注意到):我是一个完整的Rust初学者.
我在使用Perl脚本时遇到了麻烦.我尝试在哈希中存储哈希.脚本很简单:
use Data::Dumper;
my %h1=();
$h1{name}="parent";
my %h2=();
$h2{name}="child";
$h1{nested}=%h2; # store hash h2 in hash h1
print "h2:\n";
print Dumper(%h2); # works
print "h1{nested}:\n";
print Dumper($h1{nested}); # fails
Run Code Online (Sandbox Code Playgroud)
结果:
h2:
$VAR1 = 'name';
$VAR2 = 'child';
h1{nested}:
$VAR1 = '1/8';
Run Code Online (Sandbox Code Playgroud)
为什么$ h1 {nested}没有作为哈希转储,而是作为某种奇怪的标量(1/8)?
PS:即使这个问题听起来微不足道 - 我搜索了SO,但没有发现它之前被问过.PPS:我的Perl是为x86_64-linux-gnu-thread-multi构建的v5.10.1(*)(有53个已注册的补丁,有关详细信息,请参阅perl -V)
我正在尝试使用SSE指令通过uint64数组实现线性搜索。我为uint16和uint32工作,但我得到uint64代码的编译器错误(linux,gcc-请参见最后的规格)。
我正在尝试比较2x2 64位数字,然后以某种方式将结果转换为数组的索引。这可以与uint32一起很好地工作(学分请访问 http://schani.wordpress.com/2010/04/30/linear-vs-binary-search/):
#include <xmmintrin.h>
#include <smmintrin.h>
typedef ham_u64_t vec2uint64 __attribute__ ((vector_size (16)));
typedef ham_u32_t vec4uint32 __attribute__ ((vector_size (16)));
typedef float vec4float __attribute__ ((vector_size (16)));
typedef ham_u16_t vec8uint16 __attribute__ ((vector_size (16)));
typedef ham_u8_t vec16uint8 __attribute__ ((vector_size (16)));
// ...
vec4uint32 v1 = _mm_loadu_si128((const __m128i *)&data[start + i + 0]);
vec4uint32 v2 = _mm_loadu_si128((const __m128i *)&data[start + i + 4]);
vec4uint32 v3 = _mm_loadu_si128((const __m128i *)&data[start + i + 8]);
vec4uint32 v4 = _mm_loadu_si128((const __m128i *)&data[start + i + …Run Code Online (Sandbox Code Playgroud)