为什么我的D代码性能不如预期?

huangapple go评论82阅读模式
英文:

Why my D code is not performant as expected?

问题

我正在为自己的乐趣进行基准测试!我用多种编程语言编写了一部分代码,并使用ab进行基准测试,以查看哪种语言更快,以及速度差距有多大。我知道这种方法可能不太有效,不能作为使用某种语言的明确依据,但是出于我自己的信息需求,我正在这样做。我还想了解的另一个因素是在每种语言中编写相同示例的难易程度。我已经用Python/Python(asyncio)、Haskell、Go、Kotlin和D编写了代码。我预期D的性能比Go要快(或者至少速度相当)。但不幸的是,我的D代码比Go慢得多。下面是两段代码,请帮助我找出代码为什么没有达到预期的速度。或者,我的期望完全是错误的吗?

Python代码:

import cbor;
import std.array : appender;
import std.format;
import std.json;
import vibe.vibe;

struct Location
{
    float latitude;
    float longitude;
    float altitude;
    float bearing;
}
RedisClient redis;

void main()
{
    auto settings = new HTTPServerSettings;
    redis = connectRedis("localhost", 6379);

    settings.port = 8080;
    settings.bindAddresses = ["::1", "127.0.0.1"];
    listenHTTP(settings, &hello);

    logInfo("Please open http://127.0.0.1:8080/ in your browser.");
    runApplication();
}

void hello(HTTPServerRequest req, HTTPServerResponse res)
{
    if (req.path == "/locations") {
        immutable auto data = req.json;
        immutable auto loc = deserializeJson!Location(data);
        auto buffer = appender!(ubyte[])();
        encodeCborAggregate!(Flag!"WithFieldName".yes)(buffer, loc);
        auto db = redis.getDatabase(0);

        db.set("Vehicle", cast(string) buffer.data);
        res.writeBody("Ok"); 
    }
}

Go代码:

package main

import (
    "github.com/kataras/iris"
    "github.com/kataras/iris/context"
)

import "github.com/go-redis/redis"

import (
    "bytes"
    "github.com/2tvenom/cbor"
)

type Location struct {
    Latitude  float32 `json:"latitude"`
    Longitude float32 `json:"longitude"`
    Altitude  float32 `json:"altitude"`
    Bearing   float32 `json:"bearing"`
}

func main() {
    app := iris.New()
    client := redis.NewClient(&redis.Options{Addr: "localhost:6379"})

    app.Post("/locations", func(ctx context.Context) {
        var loc Location
        ctx.ReadJSON(&loc)
        var buffTest bytes.Buffer
        encoder := cbor.NewEncoder(&buffTest)
        encoder.Marshal(loc)
        client.Set("vehicle", buffTest.Bytes(), 0)
        client.Close()
        ctx.Writef("ok")
    })
    app.Run(iris.Addr(":8080"), iris.WithCharset("UTF-8"))
}

使用ab进行测试,Go的结果约为4200个请求/秒,而D的结果约为2800个请求/秒!

英文:

I am doing a benchmark test for my own fun! I have written a part of code in many programming languages and benchmark it using ab to see which is faster and how much. I know the method may not be so valid and can not be used as an evident to use some, but for my own information I am doing so. The other factor I want to know is how easy/difficult is writing the same sample in each language. I wrote the code in Python/Python(asyncio),Haskell,Go, Kotlin and D. I expcted the D port to be faster than Go (or at least equal in speed). But unfortunately my D code is much slower than Go. Here I put oth codes and please help me why the code is not fast as expected. Or am I wrong absolutely in my expectations?

import cbor;
import std.array : appender;
import std.format;
import std.json;
import vibe.vibe;


struct Location
{
    float latitude;
    float longitude;
    float altitude;
    float bearing;
}
RedisClient redis;


void main()
{
    auto settings = new HTTPServerSettings;
    redis = connectRedis("localhost", 6379);

    settings.port = 8080;
    settings.bindAddresses = ["::1", "127.0.0.1"];
    listenHTTP(settings, &hello);

    logInfo("Please open http://127.0.0.1:8080/ in your browser.");
   runApplication();
}

void hello(HTTPServerRequest req, HTTPServerResponse res)
{

if (req.path == "/locations") {

    immutable auto data = req.json;
    immutable auto loc = deserializeJson!Location(data);
    auto buffer = appender!(ubyte[])();
    encodeCborAggregate!(Flag!"WithFieldName".yes)(buffer, loc);
    auto db = redis.getDatabase(0);

    db.set("Vehicle", cast(string) buffer.data);
    res.writeBody("Ok"); 
    }
}

And here is the Go

package main

import (
    "github.com/kataras/iris"
    "github.com/kataras/iris/context"
)

import "github.com/go-redis/redis"

import (
    "bytes"
    "github.com/2tvenom/cbor"
)

type Location struct {
    Latitude  float32 `json:"latitude"`
    Longitude float32 `json:"longitude"`
    Altitude  float32 `json:"altitude"`
    Bearing   float32 `json:"bearing"`
}

func main() {
    app := iris.New()
    client := redis.NewClient(&redis.Options{Addr: "localhost:6379"})

    app.Post("/locations", func(ctx context.Context) {
	    var loc Location
	    ctx.ReadJSON(&loc)
	    var buffTest bytes.Buffer
	    encoder := cbor.NewEncoder(&buffTest)
	    encoder.Marshal(loc)
	    client.Set("vehicle", buffTest.Bytes(), 0)
	    client.Close()
	    ctx.Writef("ok")
    })
    app.Run(iris.Addr(":8080"), iris.WithCharset("UTF-8"))
}

Using ab, Go results in about 4200 req/sec, while D about 2800 req/sec!

答案1

得分: 5

你不仅仅在对比Go和D语言,还在对比你选择的非标准Go和D库,比如cborvibeiris等。而且你还在对比你特定的实现性能可能相差1000倍

由于有这么多变量,原始的基准测试数据对于比较两种语言的性能来说意义不大。其中任何一个第三方库都有可能导致性能问题。实际上,你只是在比较这两个特定的程序。这是在跨语言比较除了简单程序之外的任何东西时的核心问题:变量太多了。

你可以通过性能分析来减少其中一些变量的影响;在Go中,可以使用go tool pprof进行性能分析。这将告诉你哪些函数和代码行被调用了多少次并消耗了多少资源。通过这样,你可以找到性能瓶颈,即代码中消耗大量资源的地方,并将优化工作集中在那里。

当你为每个版本进行分析和优化时,你将更接近比较真实的、经过优化的实现。或者你将更好地了解每种语言和库在哪些方面效率高,哪些方面效率低。

比较语言的问题很大程度上受特定问题和特定程序员的影响。X程序员总是认为X是最好的语言,不是因为X是最好的语言,而是因为X程序员在使用X语言编写代码时表现最佳,并且可能选择了他们熟悉的问题。正因为如此,有许多项目致力于众包每种语言的最佳实现。

我立刻想到的一个项目是The Computer Language Benchmarks Game。他们有Go,但没有D。也许你可以添加进去。

英文:

You're not just benchmarking Go vs D. You're also benchmarking your particular choice of non-standard Go and D libraries against each other: cbor, vibe, iris, etc. And you're benchmarking your particular implementation which can easily vary by 1000x in performance.

With this many variables, the raw benchmark numbers are pretty meaningless for comparing the performance of two languages. It's possible any one of those 3rd party libraries are causing a performance problem. Really you're comparing just those two particular programs. This is the core problem of trying to compare anything but trivial programs across languages: there's too many variables.


You can reduce the impact of some of these variables with performance profiling; in Go this would be go tool pprof. This will tell you what functions and lines are being called how many times and taking how much resources. With that you can find bottlenecks, places in the code which are consuming a lot of resources, and focus optimization efforts there.

As you do profile and optimization rounds for each version, you'll get closer to comparing real, optimized implementations. Or you'll have a better understanding of what each language and library does efficiently, and what they don't.


The problem of comparing languages is heavily influenced by the particular problem and the particular programmer. X programmers invariably find X to be the best language not because X is the best language, but because X programmers are their best when writing in X and probably chose a problem they're comfortable with. Because of this, there are a number of projects to crowd source the best implementation for each language.

The one which immediately comes to mind is The Computer Language Benchmarks Game. They do Go, but not D. Maybe you can add it?

huangapple
  • 本文由 发表于 2017年6月18日 04:05:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/44608929.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定