--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
type Model struct {Header [80]byteCount uint32}
type Triangle struct {Vertex1 [3]float32Vertex2 [3]float32Vertex3 [3]float32Attribute uint16}
I think for optimal read performance you'll need to use package unsafe and avoid encoding/binary. After you have read in the header (which you can do with encoding/binary because it's not a lot), you can allocate a byte slice the size of triangle data that will follow. Just read this with one call to os File.Read(), which should be fast. Once you have your byte slice, you can use package unsafe to convert the slice to a []Triangle without copying anything. It's like C where you cast a void * to the expected data type.
I haven't done the above with .stl files yet, but with other types of files that have large chunks of similar data, and it turns out to be much faster than using encoding/binary. Ideally encoding/binary would be optimized to use a similar technique (when the file byte order matches the machine byte order), so one could simply use encoding/binary and read the []Triangle in a single call as well and it would fly like the code above.
@Elliott what is the biggest size you have seen on a STL for a 3D Printer? with unsafe method, bufio might not be needed after all...
The biggest we're playing with is around 9.5MB, tho we're just looking at things from thingiverse at the moment.
Have a look for a large desk tidy or even the Yoda is a decent stress test.
Is this a personal project? Feel free to ping me outside of this channel. Would be interested to follow the progress.
@Elliott what is the biggest size you have seen on a STL for a 3D Printer? with unsafe method, bufio might not be needed after all...I've been printing files up the 350MB, larger than that, the printer software balks... I suppose you'll find gigabyte .stl files in the wild.
--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/eqtmH2WGSKE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
Only the first one read is fine, I suppose it has something to do with the sizes, but I'm unsure as I have never used unsafe before. Any help is welcome.
func ParseSTL(filename string) *Model {// Reading entire STL file into memory
data, err := ioutil.ReadFile(filename)if err != nil {panic(err)}m := new(Model)
// Parsing Header first 80 bytes.err = binary.Read(bytes.NewBuffer(data[0:80]), binary.LittleEndian, &m.Header)
if err != nil {panic(err)}
// Parsing triangle count uint32 at byte 80err = binary.Read(bytes.NewBuffer(data[80:84]), binary.LittleEndian, &m.Length)
if err != nil {panic(err)}
// Allocating enough memory for all the triangles in the slicem.Triangles = make([]Triangle, m.Length)// Parsing the Triangle slice on byte 84 onwards, 50 bytes per triangleerr = binary.Read(bytes.NewBuffer(data[84:]), binary.LittleEndian, &m.Triangles)
if err != nil {panic(err)}
return m}
Wrt the alignment problem, you might be able to make a special io.Reader which emits bytes for the padding as you read from an underlying io.Reader. Not sure if it will be faster though.
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
That will give the wrong result if run on a big-endian machine, no?
Or if the Go compiler starts to use different alignment rules.
Please let's not go this way
On Thu, Oct 3, 2013 at 6:30 PM, Jesse van den Kieboom
<jess...@gmail.com> wrote:
> The standard library does the same thing where performance matters.
I'm not aware of any single place where any stdlib code is not
endianess agnostic. Can you please point out such place? I'll fill a
bug in that case.
PS: Really good reading is
http://commandcenter.blogspot.de/2012/04/byte-order-fallacy.html
-j
Hey Kyle, I'm trying to go through all this changes, but I'm not used to the Reader Interface. Should I create a bytes.NewReader to feed into the io.Reader with a set size? One other thing, you mention the copy operation is useless and that I should read directly to the Triangle slice... thing is, how do I use a slice of my slice as a param in the binary.Read function. I already tried that, and only the first Triangle was copied correctly when I sent the pointer to the first element of the subslice.
If you have an example of code with a bytes.Reader to send into my io.ReaderSize with a set sized buffer, that would be awesome! (and I can get rid of buf, and the bytes.Buffer I'm used to) Then I can just figure out the best way to copy the data to the Triangle slice with binary.Read or else. Thing is, I'm concerned how parsing a file requires at least twice the memory even while buffering the read... I suppose that should not happen and I hope you changes help me fix that.
On Wednesday, October 2, 2013 9:27:11 PM UTC-5, Kyle Lemons wrote:a few things. Sorry I'm so late to the game. If I'm suggesting a repeat, let me know.Just start out by reading from the file directly. You don't know your buffer size yet, so hold off on the bufio.use io.ReadFullbytes.NewReaderhowever, you should be able to read these straight out of the file, you shouldn't need to read it in and then make a bytes.Readerif you don't make a bufio.Reader above, you don't need to seek, and can just make the ReaderSize here.You've got some crazy double-buffering going on here. Get rid of "buf" and just read straight out of the bufio.Reader. When it empties, it will fill itself up, and then you can binary.Read straight out of it.I would be very surprised if this is helping you. Read straight into the triangle you're currently decoding. If your profile shows that you're spending a lot of time in reflect, unroll that binary.Read into a ReadFull and then the right sequence of calls to binary.LittleEndian.*
--
On Thu, Oct 3, 2013 at 5:15 PM, Guillermo Estrada <phro...@gmail.com> wrote:
Hey Kyle, I'm trying to go through all this changes, but I'm not used to the Reader Interface. Should I create a bytes.NewReader to feed into the io.Reader with a set size? One other thing, you mention the copy operation is useless and that I should read directly to the Triangle slice... thing is, how do I use a slice of my slice as a param in the binary.Read function. I already tried that, and only the first Triangle was copied correctly when I sent the pointer to the first element of the subslice.To feed into which io.Reader? The one for binary.Read? I didn't look at the code again, but I think it should look like this:f, err := os.Open(filename)if err != nil { ... }defer f.Close()var header Headerif err := binary.Read(f, binary.LittleEndian, &header); err != nil { ... }
triangles := make([]Triangle, header.Triangles)
r := bufio.NewReaderSize(f, BufferTriangles*binary.Size(Triangle{}))for i := range triangles {if err := binary.Read(f, binary.LittleEndian, &triangles[i]); err != nil { ... }
On Fri, Oct 4, 2013 at 11:52 AM, Jesse van den Kieboom
<jess...@gmail.com> wrote:
> Just to put some measurements on my claims, I compared both reading unsafe
> and reading using standard reflect. The two functions I used are on
> http://play.golang.org/p/HlAFRnxQ-K
>
> STL unsafe:
> 49.527777ms (49.69955ms) 25.05 MB 10 Allocs
>
> STL reflect:
> 974.764166ms (974.900398ms) 99.02 MB 3371574 Allocs
Comparing the performance against a solution using reflect makes no
sense
as you can write code running correctly regardless of endianess
without using whatsoever from the reflect package, which is okay per
se, but inevitably principally slow in many, if not most cases
.
-j