On Sat, May 30, 2020, 6:08 PM Tom Larsen <larsenthom...@gmail.com> wrote:

> I've managed to batch the incoming data, so I thought I would provide an
> update:
>
> Batching 10 records at a time reduced runtime to just under 40 seconds
> (beating Python!), so the slowdown I am seeing is overhead.  In my case the
> overhead equates to about 5 microseconds per call from C to Go.
>

Thanks for the update.

It's interesting that needm and extram are so high.  Are these calls from
threads started by C to Go, as opposed to calls from Go to C to Go?  In the
current implementation that is the worst case.

Ian




On Wednesday, May 27, 2020 at 1:08:17 PM UTC-4, Tom Larsen wrote:
>>
>> I am attempting to build a Golang SDK for the Alteryx analytic
>> application.  Alteryx provides a C API for interacting with the engine, so
>> I thought I would use cgo to build a bridge between Alteryx and Go.
>>
>> The basic flow-of-control looks something like this:
>>
>>    1. The engine pushes a record of data (a C pointer to a blob of
>>    bytes) to my SDK by calling a cgo function (iiPushRecord). So, C is 
>> calling
>>    Go here. My cgo function looks like this:
>>
>>    //export iiPushRecord
>>    func iiPushRecord(handle unsafe.Pointer, record unsafe.Pointer) C.long {
>>        incomingInterface := pointer.Restore(handle).(IncomingInterface)
>>        if incomingInterface.PushRecord(record) {
>>            return C.long(1)
>>        }
>>        return C.long(0)
>>    }
>>
>>    2. My SDK calls a method on an interface that does something with the
>>    data.  For my basic example, I'm just copying the data to some outgoing
>>    buffers (theoretically, a best case scenario).
>>    3. The interface object pushes the data back to the engine by calling
>>    my SDK's PushRecord function, which in turn calls a similar C function on
>>    the engine.  The PushRecord function in my SDK looks like this:
>>
>>    func PushRecord(connection *ConnectionInterfaceStruct, record 
>> unsafe.Pointer) error {
>>        result := C.callPushRecord(connection.connection, record)
>>        if result == C.long(0) {
>>            return fmt.Errorf(`error calling pII_PushRecord`)
>>        }
>>        return nil
>>    }
>>
>>
>>    and the callPushRecord function in C looks like this:
>>
>>    long callPushRecord(struct IncomingConnectionInterface * connection, void 
>> * record) {
>>        return connection->pII_PushRecord(connection->handle, record);
>>    }
>>
>>
>> When I execute my base code 10 million times (simulating 10 million
>> records) in a unit test, it will execute in 20-30 seconds.  This test does
>> not include the cgo calls.  However, when I package the tool and execute it
>> in Alteryx with 10 million records, it takes about 1 minute 20 seconds to
>> execute.  I benchmarked against an equivalent tool I built using Alteryx's
>> own Python SDK, which takes 1 minute.  My goal is to be faster than Python.
>>
>> I ran a CPU profile while Alteryx was running.  Of the 1.38 minute
>> runtime, the profile samples covered 42.95 seconds.  The profile starts out
>> like this:
>>
>> crosscall2 (0%) -> _cgoexp_89e40a732b6d_iiPushRecord (0%) -> runtime
>> cgoballback (0%) -> runtime cgocallback_gofunc (0.14%)
>>
>> At this point, the profile branches into 3:
>>
>>    1. runtime cgocallback, which eventually calls all of my SDK code.
>>    This branch accounts for 17.06 seconds in total
>>    2. runtime needm, which accounts for 8.21 seconds in total
>>    3. runtime dropm, which accounts for 17.43 seconds in total
>>
>> If you want a graphical display of the profile, it's here:
>> https://i.stack.imgur.com/CphbG.png
>>
>> It looks like the C to Go overhead is responsible for ~60% of the total
>> execution time?  Is this the correct way to interpret the profile?  If so,
>> is it because of something I did wrong, or is this overhead inherent to the
>> runtime?  There isn't noticeable overhead when my Go code calls C, so the
>> upfront overhead from C to Go really surprised me.  Is there anything I can
>> do here?
>>
>> I am running Go 1.14.3 on windows/amd64.  It's actually a Windows 10 VM
>> on my Macbook, if that makes any difference.
>>
>> All of the code is on GitHub: https://github.com/tlarsen7572/goalteryx
>>
>> Note: I asked this on SO a few days ago, but got no answers, so I thought
>> I would try here.  I hope that's ok.
>>
> --
> 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+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/golang-nuts/67cf04eb-ea28-4ac9-b341-ee8d33af992a%40googlegroups.com
> <https://groups.google.com/d/msgid/golang-nuts/67cf04eb-ea28-4ac9-b341-ee8d33af992a%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>

-- 
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+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAOyqgcW5qKQphXusb3LcjSGaPuSRuQB3aCEGYfWd7vgLSZ0REw%40mail.gmail.com.

Reply via email to