小编Jak*_*kob的帖子

进入系统调用与C系统调用

Go和C都直接涉及系统调用(技术上,C将调用存根).

从技术上讲,write既是系统调用又是C函数(至少在许多系统上).但是,C函数只是一个调用系统调用的存根.Go不会调用此存根,它会直接调用系统调用,这意味着此处不涉及C.

从C write调用和Go syscall.Write之间的差异

我的基准测试显示,纯C系统调用比最新版本(go1.11)中的纯Go系统调用快15.82%.

我错过了什么?可能是什么原因以及如何优化它们?

基准:

走:

package main_test

import (
    "syscall"
    "testing"
)

func writeAll(fd int, buf []byte) error {
    for len(buf) > 0 {
        n, err := syscall.Write(fd, buf)
        if n < 0 {
            return err
        }
        buf = buf[n:]
    }
    return nil
}

func BenchmarkReadWriteGoCalls(b *testing.B) {
    fds, _ := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
    message := "hello, world!"
    buffer := make([]byte, 13)
    for i := 0; i < b.N; i++ {
        writeAll(fds[0], []byte(message))
        syscall.Read(fds[1], buffer) …
Run Code Online (Sandbox Code Playgroud)

c system-calls go

11
推荐指数
1
解决办法
1328
查看次数

如何编写可观察的指令重排示例?

举个例子:

#include <thread>
#include <iostream>

int main() {
    int a = 0;
    volatile int flag = 0;

    std::thread t1([&]() {
        while (flag != 1);

        int b = a;
        std::cout << "b = " << b << std::endl;
    });

    std::thread t2([&]() {
        a = 5;
        flag = 1;
    });

    t1.join();
    t2.join();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

从概念上flag = 1;可以理解,可以在此之前重新排序和执行a = 5;,因此b的结果可以是5或0。

但是,实际上,我无法在计算机上产生输出为0的结果。我们如何保证行为或指令可重复地重排?具体如何更改代码示例?

c++ memory-barriers

8
推荐指数
1
解决办法
108
查看次数

如何用 std::variant 正确替换 boost::variant?

使用boost:variant:

#include <tuple>
#include <iostream>
#include <boost/variant.hpp>

template <size_t n, typename... T>
boost::variant<T...> _tuple_index(size_t i, const std::tuple<T...>& tpl) {
    if (i == n)
        return std::get<n>(tpl);
    else if (n == sizeof...(T) - 1)
        throw std::out_of_range("Out of Index");
    else
        return _tuple_index<(n < sizeof...(T)-1 ? n+1 : 0)>(i, tpl);
}
template <typename... T>
boost::variant<T...> tuple_index(size_t i, const std::tuple<T...>& tpl) {
    return _tuple_index<0>(i, tpl);
}

template <typename T>
auto tuple_len(T &tpl) {
    return std::tuple_size<T>::value;
}

int main()
{
    std::tuple<std::string, double, double, int> …
Run Code Online (Sandbox Code Playgroud)

c++ boost

6
推荐指数
1
解决办法
480
查看次数

为什么右值参考传递为左值参考?

pass()引用参数并将其传递给reference,但是实际上调用了一个rvalue参数reference(int&)而不是reference(int &&),这里是我的代码片段:

#include <iostream>
#include <utility>
void reference(int& v) {
    std::cout << "lvalue" << std::endl;
}
void reference(int&& v) {
    std::cout << "rvalue" << std::endl;
}
template <typename T>
void pass(T&& v) {
    reference(v);
}
int main() {
    std::cout << "rvalue pass:";
    pass(1);

    std::cout << "lvalue pass:";
    int p = 1;
    pass(p);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出是:

rvalue pass:lvalue
lvalue pass:lvalue
Run Code Online (Sandbox Code Playgroud)

因为p根据参考折叠规则很容易理解,但为什么模板函数传递v给reference()lvalue?

c++

5
推荐指数
2
解决办法
737
查看次数

当goroutine争用超过3400时,为什么sync.Mutex会大大降低性能?

我正在比较关于sync.Mutex和Go频道的性能。这是我的基准:

// go playground: https://play.golang.org/p/f_u9jHBq_Jc
const (
    start = 300  // actual = start  * goprocs
    end   = 600 // actual = end    * goprocs
    step  = 10
)

var goprocs = runtime.GOMAXPROCS(0) // 8

// https://perf.golang.org/search?q=upload:20190819.3
func BenchmarkChanWrite(b *testing.B) {
    var v int64
    ch := make(chan int, 1)
    ch <- 1
    for i := start; i < end; i += step {
        b.Run(fmt.Sprintf("goroutines-%d", i*goprocs), func(b *testing.B) {
            b.SetParallelism(i)
            b.RunParallel(func(pb *testing.PB) {
                for pb.Next() {
                    <-ch
                    v += 1
                    ch …
Run Code Online (Sandbox Code Playgroud)

performance go

5
推荐指数
2
解决办法
282
查看次数

如何在docker centos7中安装gcc7

我正在尝试构建一个基于 docker 镜像centos7

FROM centos:centos7

RUN yum -y update
RUN yum -y install gcc
RUN gcc --version
Run Code Online (Sandbox Code Playgroud)

安装的gcc是4.8:

步

 4/4 : RUN gcc --version
 ---> Running in 70b9aa4a1f67
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Run Code Online (Sandbox Code Playgroud)

如何安装 gcc7?我尝试了 devtools-7,它不起作用:

FROM centos:centos7

RUN yum -y update
RUN yum …
Run Code Online (Sandbox Code Playgroud)

gcc docker centos7

2
推荐指数
1
解决办法
9341
查看次数

C write call和Go syscall.Write之间的区别

syscall write返回-1并且set errno是一个简单的例子.我对errnoif C write调用返回零或正数的状态感兴趣.对于任何情况,如果不为零,则syscall.WriteGo中的包装器将返回,其中还包括调用返回为正的情况.errerrnowrite

https://github.com/golang/go/blob/3cb64ea39e0d71fe2af554cbf4e99d14bc08d41b/src/syscall/zsyscall_linux_386.go#L1007

然而,的C man页面write调用大致介绍了errno 可能也被设置但是不确定,如果我们写零长度的缓冲区没有解释任何细节.

因此,以下案例似乎不清楚:

  1. errnoif write调用为文件,非阻塞套接字或阻塞套接字返回0 的状态是什么?
  2. 何时以及如何write调用返回0并且errno不是0?
  3. errnoif writecall返回正数的状态是什么?它会消极吗?
  4. 是否有其他系统调用可能会遇到相同的情况?

我认为上面的描述指出了C write调用和Go 之间的区别syscall.Write,这对于开发人员来说还不清楚,以下是我的想法:

根据手册页,在C write调用文件和非阻塞套接字中明确定义了返回零,但是不清楚是否存在阻塞套接字的非错误条件,这将导致write()不阻塞,返回0,并且(据推测)如果重试可能会在以后成功.

确实Go直接包装系统调用write.但是,以下代码片段似乎不安全,因为written等于零是可能触发的情况,err但我们不想破坏循环:

func writeAll(fd int, buffer []byte) bool {
    length := len(buffer)
    for length > 0 {
        written, err := syscall.Write(fd, buffer)
        if …
Run Code Online (Sandbox Code Playgroud)

c system-calls go

1
推荐指数
1
解决办法
270
查看次数

矩阵乘法与goroutine降低性能

我正在通过Go中的goroutines优化矩阵乘法.

我的基准测试显示,每行或每个元素引入并发性会大大降低性能:

goos: darwin
goarch: amd64
BenchmarkMatrixDotNaive/A.MultNaive-8                            2000000               869 ns/op               0 B/op          0 allocs/op
BenchmarkMatrixDotNaive/A.ParalMultNaivePerRow-8                  100000             14467 ns/op              80 B/op          9 allocs/op
BenchmarkMatrixDotNaive/A.ParalMultNaivePerElem-8                  20000             77299 ns/op             528 B/op         65 allocs/op
Run Code Online (Sandbox Code Playgroud)

我知道缓存局部性的一些基本的先验知识,每个元素并发性能会降低性能.但是,为什么即使在天真的版本中,每行仍然会降低性能?

事实上,我还写了一个块/平铺优化,它的vanilla版本(没有goroutine并发)甚至比天真版本更糟糕(这里不存在,让我们首先关注天真).

我在这做错了什么?为什么?如何在这里优化?

乘法:

package naive

import (
    "errors"
    "sync"
)

// Errors
var (
    ErrNumElements = errors.New("Error number of elements")
    ErrMatrixSize  = errors.New("Error size of matrix")
)

// Matrix is a 2d array
type Matrix struct {
    N    int
    data [][]float64
}

// New a size by size matrix …
Run Code Online (Sandbox Code Playgroud)

concurrency go matrix-multiplication goroutine

1
推荐指数
1
解决办法
204
查看次数

在 macOS 上使用 GDB 调试 Go 程序

一个简单的 Go 程序,比如main.go:

package main

func main() {
    println("hello, world!")
}
Run Code Online (Sandbox Code Playgroud)

然后用

go build -gcflags "-N -l" -o main main.go
Run Code Online (Sandbox Code Playgroud)

使用 GDB:

$ gdb main
GNU gdb (GDB) 8.2
(...)
Reading symbols from main...(no debugging symbols found)...done.
Loading Go Runtime support.
(gdb) source /usr/local/Cellar/go/1.11/libexec/src/runtime/runtime-gdb.py
Loading Go Runtime support.
(gdb) info files
Symbols from "/Users/changkun/Desktop/demo/main".
Local exec file:
        `/Users/changkun/Desktop/demo/main', file type mach-o-x86-64.
        Entry point: 0x1049e20
        0x0000000001001000 - 0x000000000104dfcf is .text
        0x000000000104dfe0 - 0x0000000001077344 is __TEXT.__rodata
        (...)
(gdb) b *0x1049e20 …
Run Code Online (Sandbox Code Playgroud)

gdb go

1
推荐指数
1
解决办法
1869
查看次数