doukong5394 2016-09-11 14:41
浏览 130
已采纳

Golang代码的运行速度比PHP中的相同代码慢

New to Golang, Yesterday I started to play with Golang and wrote some code which was actually written in PHP, I just wanted to see difference in performance. I am doing the exact same thing in PHP response is exact same in http request but the Golang is performing really slow even after compiling it. I am trying to understand what things that I am using in Golang I shouldn't be using and how can I imporve performance in this piece of Code. I know Iterating over map is slow but PHP using hash maps for implementing multidimentional arrays, well. I can gurantee the sql queries I used were exact same copy pasted from PHP, machines are same, and loop numbers are same in both codes.

package main

import (
    "database/sql"
    "encoding/json"
    "fmt"
    _ "github.com/go-sql-driver/mysql"
    "net/http"
    "reflect"
    "strings"
)

func main() {
    db, err := sql.Open("mysql", "***:****@tcp(****:3306)/****")
    fmt.Println(reflect.TypeOf(db))
    checkErr(err)
    fmt.Println("Handle Request setup... OK")
    http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {

        jsonData, err := getListings(db)
        checkErr(err)

        w.Write([]byte(jsonData))

    })
    fmt.Println("Starting Server....")
    fmt.Println("Listening on port 8081")
    http.ListenAndServe(":8081", nil)

}

func getListings(db *sql.DB) ([]byte, error) {
    var userId string = "142"

    normalListings := sqlToArray(db, `******`)

    manualListings := sqlToArray(db, "******")

    var groupIds []string
    for key := range manualListings {

        groupId := "142," + manualListings[key]["group_id"]
        if !stringInSlice(groupId, groupIds) {
            groupIds = append(groupIds, groupId)
        }
    }

    var groupIdsString string
    groupIdsString = strings.Join(groupIds, ", ")

    manualGroups := sqlToArray(db, "*****")

    for key := range manualListings {

        for key2 := range manualGroups {
            groupId := "142," + manualListings[key]["group_id"]

            if groupId == manualGroups[key]["ticket_id"] {
                entry := make(map[string]string)
                entry["ticket_id"] = manualListings[key]["listing_id"]
                entry["date_created"] = manualGroups[key2]["date_created"]
                normalListings = append(normalListings, entry)

            }
        }
    }

    return json.Marshal(normalListings)

}

func stringInSlice(a string, list []string) bool {
    for _, b := range list {
        if b == a {
            return true
        }
    }
    return false
}

func sqlToArray(db *sql.DB, sqlString string) []map[string]string {

    rows, err := db.Query(sqlString)
    checkErr(err)
    columns, err := rows.Columns()
    count := len(columns)
    values := make([]interface{}, count)
    valuePtrs := make([]interface{}, count)
    tableData := make([]map[string]string, 0)

    for rows.Next() {

        for i := 0; i < count; i++ {
            valuePtrs[i] = &values[i]
        }
        rows.Scan(valuePtrs...)
        entry := make(map[string]string)
        for i, col := range columns {

            val := values[i]
            b, ok := val.([]byte)
            if ok {
                entry[col] = string(b)
            } else {
                entry[col] = string(b)
            }

        }
        tableData = append(tableData, entry)

    }

    return tableData

}

func checkErr(err error) {
    if err != nil {
        panic(err)
    }
}

Edits: Changed the code to use statically typed structs instead of using maps and Identified the problematic piece of code

New code:

package main

import (
    "database/sql"
    "encoding/json"
    "fmt"
    _ "github.com/go-sql-driver/mysql"
    "net/http"
    "strings"
)

type listingsType struct {
    TicketId    string
    DateCreated string
}

func main() {
    db, err := sql.Open("mysql", "******")

    checkErr(err)
    fmt.Println("Handle Request setup... OK")
    http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {

        jsonData, err := getListings(db)
        checkErr(err)

        w.Write([]byte(jsonData))

    })
    fmt.Println("Starting Server....")
    fmt.Println("Listening on port 8081")
    http.ListenAndServe(":8081", nil)

}

func getListings(db *sql.DB) ([]byte, error) {
    var userId string = "142"

    normalListings := sqlToArray(db, `*****`)

    manualListings := sqlToArray(db, "*****")

    var groupIds []string

    for _, elem := range manualListings {
        groupId := "142," + elem.DateCreated
        if !stringInSlice(groupId, groupIds) {
            groupIds = append(groupIds, groupId)
        }

    }

    var groupIdsString string
    groupIdsString = strings.Join(groupIds, ", ")
    fmt.Println(groupIdsString)
    manualGroups := sqlToArray(db, "******")

    for _, manualList := range manualListings {

        for _, manualGroup := range manualGroups {
            groupId := "142," + manualList.DateCreated

            if groupId == manualGroup.TicketId {
                var entry listingsType
                entry.TicketId = manualList.TicketId
                entry.DateCreated = manualGroup.DateCreated
                normalListings = append(normalListings, entry)

            }
        }
    }

    return json.Marshal(normalListings)

}

func stringInSlice(a string, list []string) bool {
    for _, b := range list {
        if b == a {
            return true
        }
    }
    return false
}

func sqlToArray(db *sql.DB, sqlString string) []listingsType {

    rows, err := db.Query(sqlString)
    checkErr(err)

    tableData := []listingsType{}

    for rows.Next() {

        var entry listingsType
        rows.Scan(&entry.TicketId, &entry.DateCreated)

        tableData = append(tableData, entry)

    }

    return tableData

}

func checkErr(err error) {
    if err != nil {
        panic(err)
    }
}

Problematic piece of code As soon as I comment the following block of code the my code performs just fine. Any idea what is wrong with this loop ?

for _, manualList := range manualListings {

        for _, manualGroup := range manualGroups {
            groupId := "142," + manualList.DateCreated

            if groupId == manualGroup.TicketId {
                var entry listingsType
                entry.TicketId = manualList.TicketId
                entry.DateCreated = manualGroup.DateCreated
                normalListings = append(normalListings, entry)

            }
        }
    }

Profiling Result

enter image description here

  • 写回答

2条回答 默认 最新

  • doutangdan3588 2016-09-16 22:04
    关注

    Ok So got it fixed by the way. I brought the request time from 5k+ MS to 500 MS, now finally my PHP code is slower which is 900 MS

    I got rid of the inner loop to search by implementing a separate function to get SQL data in a different data structure in key value of maps instead of searching whole arrays I created the value as key which I was looking for in array, This way I got rid of the second loop which was making trouble by linear search on strings.

    manualGroups := sqlToArraySpecial(db, "****")
    
        for _, manualList := range manualListings {
            //index := stringInSliceArray(manualList.DateCreated, manualGroups)
            groupId := "142," + manualList.DateCreated
            var entry listingsType
            entry.TicketId = manualList.TicketId
            entry.DateCreated = manualGroups[groupId]
            normalListings = append(normalListings, entry)
    
        }
    

    and here is my new SQL function

    func sqlToArraySpecial(db *sql.DB, sqlString string) map[string]string {
    
        rows, err := db.Query(sqlString)
        checkErr(err)
    
        tableData := make(map[string]string)
    
        for rows.Next() {
    
            var date_created string
            var ticket_id string
    
            rows.Scan(&ticket_id, &date_created)
            //fmt.Println(ticket_id)
            tableData[ticket_id] = date_created
    
        }
    
        return tableData
    
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥50 求解vmware的网络模式问题
  • ¥24 EFS加密后,在同一台电脑解密出错,证书界面找不到对应指纹的证书,未备份证书,求在原电脑解密的方法,可行即采纳
  • ¥15 springboot 3.0 实现Security 6.x版本集成
  • ¥15 PHP-8.1 镜像无法用dockerfile里的CMD命令启动 只能进入容器启动,如何解决?(操作系统-ubuntu)
  • ¥30 请帮我解决一下下面六个代码
  • ¥15 关于资源监视工具的e-care有知道的嘛
  • ¥35 MIMO天线稀疏阵列排布问题
  • ¥60 用visual studio编写程序,利用间接平差求解水准网
  • ¥15 Llama如何调用shell或者Python
  • ¥20 谁能帮我挨个解读这个php语言编的代码什么意思?