dongzhidian3538 2012-09-18 18:33
浏览 88
已采纳

使用Goroutine实际上需要更长的时间才能执行

I'm sure that I'm doing something wrong, I have a Go program that parses in 3D models in OBJ format and outputs a json object. When I run it without adding in goroutines I get the following output:

$ go run objParser.go ak47.obj extincteur_obj.obj 
--Creating ak47.json3d from ak47.obj
--Exported 85772 faces with 89088 verticies
--Creating extincteur_obj.json3d from extincteur_obj.obj
--Exported 150316 faces with 151425 verticies
Parsed 2 files in 8.4963s

Then I added in the goroutines and I get this output:

$ go run objParser.go ak47.obj extincteur_obj.obj 
--Creating ak47.json3d from ak47.obj
--Creating extincteur_obj.json3d from extincteur_obj.obj
--Exported 85772 faces with 89088 verticies
--Exported 150316 faces with 151425 verticies
Parsed 2 files in 10.23137s

The order of how it's printed is what I expected given the interlacing of the parsing but I have no idea why it actually takes longer! The code is pretty long, I snipped what I could but it's still pretty long, sorry about that!

package main

func parseFile(name string, finished chan int) {
    var Verts []*Vertex
    var Texs []*TexCoord
    var Faces []*Face

    var objFile, mtlFile, jsonFile *os.File
    var parseMaterial bool

    // Set up files and i/o
    inName := name
    outName := strings.Replace(inName, ".obj", ".json3d", -1)
    parseMaterial = false

    fmt.Printf("--"+FgGreen+"Creating"+Reset+" %s from %s
", outName, inName)

    var err error
    var part []byte
    var prefix bool

    if objFile, err = os.Open(inName); err != nil {
        fmt.Println(FgRed+"!!Failed to open input file!!"+Reset)
        return
    }

    if jsonFile, err = os.Create(outName); err != nil {
        fmt.Println(FgRed+"!!Failed to create output file!!"+Reset)
        return
    }

    reader := bufio.NewReader(objFile)
    writer := bufio.NewWriter(jsonFile)
    buffer := bytes.NewBuffer(make([]byte, 1024))

    // Read the file in and parse out what we need
    for {
        if part, prefix, err = reader.ReadLine(); err != nil {
            break
        }

        buffer.Write(part)
        if !prefix {
            line := buffer.String()
            if(strings.Contains(line, "v ")) {
                Verts = append(Verts, parseVertex(line))
            } else if(strings.Contains(line, "vt ")) {
                Texs = append(Texs, parseTexCoord(line))
            } else if(strings.Contains(line, "f ")) {
                Faces = append(Faces, parseFace(line, Verts, Texs))
            } else if(strings.Contains(line, "mtllib ")) {
                mtlName := strings.Split(line, " ")[1]
                if mtlFile, err = os.Open(mtlName); err != nil {
                    fmt.Printf("--"+FgRed+"Failed to find material file: %s
"+Reset, mtlName)
                    parseMaterial = false
                } else {
                    parseMaterial = true
                }
            }
            buffer.Reset()
        }
    }

    if err == io.EOF {
        err = nil
    }

    objFile.Close()

    // Write out the data
    writer.WriteString("{\"obj\":[
");

    // Write out the verts
    writer.WriteString("{\"vrt\":[
");
    for i, vert := range Verts {
        writer.WriteString(vert.String())
        if i < len(Verts) - 1 { writer.WriteString(",") }
        writer.WriteString("
")
    }

    // Write out the faces
    writer.WriteString("],\"fac\":[
")
    for i, face := range Faces {
        writer.WriteString(face.String(true))
        if i < len(Faces) - 1 { writer.WriteString(",") }
        writer.WriteString("
")
    }

    // Write out the normals
    writer.WriteString("],\"nrm\":[")
    for i, face := range Faces {


        writer.WriteString("[")
        for j, vert := range face.verts {
            length := math.Sqrt((vert.X * vert.X) + (vert.Y * vert.Y) + (vert.Z * vert.Z))
            x := vert.X / length
            y := vert.Y / length
            z := vert.Z / length
            normal := fmt.Sprintf("[%f,%f,%f]", x, y, z)
            writer.WriteString(normal)
            if(j < len(face.verts)-1) { writer.WriteString(",") }
        }
        writer.WriteString("]")




        //writer.WriteString("[0, 1, 0]")
        if i < len(Faces) - 1 { writer.WriteString(",") }
        writer.WriteString("
")
    }

    // Write out the tex coords
    writer.WriteString("],\"tex\":[")
    for i, face := range Faces {
        writer.WriteString("[")
        writer.WriteString(face.tex[0].String())
        writer.WriteString(",")
        writer.WriteString(face.tex[1].String())
        writer.WriteString(",")
        writer.WriteString(face.tex[2].String())
        writer.WriteString("]")
        if i < len(Faces) - 1 { writer.WriteString(",") }
        writer.WriteString("
")
    }

    // Close obj block
    writer.WriteString("]}]");

    if parseMaterial {
        writer.WriteString(",mat:[{");
        reader := bufio.NewReader(mtlFile)

        // Read the file in and parse out what we need
        for {
            if part, prefix, err = reader.ReadLine(); err != nil {
                break
            }

            buffer.Write(part)
            if !prefix {
                line := buffer.String()
                if(strings.Contains(line, "map_Kd ")) {
                    parts := strings.Split(line, " ")
                    entry := fmt.Sprintf("\"t\":\"%s\",", parts[1])
                    writer.WriteString(entry)

                    width, height := 256, 256
                    var imageFile *os.File
                    if imageFile, err = os.Open(parts[1]); err != nil {
                        fmt.Printf("--"+FgRed+"Failed to find %s, defaulting to 256x256"+Reset+"
", parts[1])
                        return
                    } else {
                        var config image.Config
                        imageReader := bufio.NewReader(imageFile)
                        config, err = jpeg.DecodeConfig(imageReader)
                        width, height = config.Width, config.Height
                        fmt.Printf("--"+FgGreen+"Verifing"+Reset+" that %s is %dpx x %dpx
", parts[1], width, height)
                    }

                    size := fmt.Sprintf("\"w\":%d,\"h\":%d,", width, height)
                    writer.WriteString(size)

                } else if(strings.Contains(line, "Kd ")) {
                    parts := strings.Split(line, " ")
                    entry := fmt.Sprintf("\"r\":%s, \"g\":%s, \"b\":%s,", parts[1], parts[2], parts[3])
                    writer.WriteString(entry)
                }
                buffer.Reset()
            }
        }

        if err == io.EOF {
            err = nil
        }

        writer.WriteString("\"res\":100,\"uv\":true}]");
    }

    // Close json
    writer.WriteString("}");
    writer.Flush()
    jsonFile.Close()

    fmt.Printf("--"+FgGreen+"Exported"+Reset+" %d faces with %d verticies
", len(Faces), len(Verts))

    finished <- -1
}

func main(){
    // Verify we were called correctly
    if len(os.Args) < 2 {
        fmt.Println("Usage: go run objParser.go <OBJ File>");
        return
    }

    files := len(os.Args)
    finished := make(chan int)

    now := time.Now()

    for i := 1; i < files; i++ {
        go parseFile(os.Args[i], finished)
    }

    for i := 1; i < files; i++ {
        <- finished
    }

    fmt.Printf("Parsed %d files in %s
", files-1, time.Since(now))
}
  • 写回答

1条回答 默认 最新

  • duanbishai5271 2012-09-18 18:47
    关注

    You should set GOMAXPROCS environment variable for go to the maximum number of usable processors. Or use function GOMAXPROCS at executing time.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 用hfss做微带贴片阵列天线的时候分析设置有问题
  • ¥50 我撰写的python爬虫爬不了 要爬的网址有反爬机制
  • ¥15 Centos / PETSc / PETGEM
  • ¥15 centos7.9 IPv6端口telnet和端口监控问题
  • ¥120 计算机网络的新校区组网设计
  • ¥20 完全没有学习过GAN,看了CSDN的一篇文章,里面有代码但是完全不知道如何操作
  • ¥15 使用ue5插件narrative时如何切换关卡也保存叙事任务记录
  • ¥20 海浪数据 南海地区海况数据,波浪数据
  • ¥20 软件测试决策法疑问求解答
  • ¥15 win11 23H2删除推荐的项目,支持注册表等