Http Get from C# to APL

APL-related discussions - a stream of APL consciousness.
Not sure where to start a discussion ? Here's the place to be
Forum rules
This forum is for discussing APL-related issues. If you think that the subject is off-topic, then the Chat forum is probably a better place for your thoughts !

Http Get from C# to APL

Postby Tomas Gustafsson on Mon Jan 05, 2015 10:26 pm

Time for me too to learn this. I could use some help... Anyone interested in translating this? The public's etc confuse me.. Thx!

http://msdn.microsoft.com/en-us/library/86wf6409%28v=vs.110%29.aspx
Tomas Gustafsson
 
Posts: 101
Joined: Mon Sep 19, 2011 6:43 pm

Re: Http Get from C# to APL

Postby Morten|Dyalog on Tue Jan 06, 2015 7:40 am

Hi Tomas, is there any reason why you don't just use Samples.HTTPGet from the CONGA workspace? What are you trying to achieve?
User avatar
Morten|Dyalog
 
Posts: 453
Joined: Tue Sep 09, 2008 3:52 pm

Re: Http Get from C# to APL

Postby paulmansour on Tue Jan 06, 2015 1:41 pm

I notice the link leads a page titled "Making Asynchronous Requests."

Is the Asynch vs synch an issue?
paulmansour
 
Posts: 420
Joined: Fri Oct 03, 2008 4:14 pm

Re: Http Get from C# to APL

Postby Tomas Gustafsson on Tue Jan 06, 2015 3:16 pm

Morten|Dyalog wrote:Hi Tomas, is there any reason why you don't just use Samples.HTTPGet from the CONGA workspace? What are you trying to achieve?

paulmansour wrote:I notice the link leads a page titled "Making Asynchronous Requests."
Is the Asynch vs synch an issue?

Yes indeed is it an "sync/async/APL thread 0/Conga 1+ thread" issue, in addition to very much being a learning thing fr myself. I haven't used the OO features for anything real yet, and this particular example deals with thansporting an object between it's initial creation and an async'ed callback. I couldn't get it to function, see my own novice approach below.

I know Conga might be faster. In addition to the (slight) disadvantage of involving the DRC namespace from Conga, plus the conga25.dll, i notied that even if the Conga documentation says conga25.dll involves other/multiple CPU cores, a rather big part of the Samples.HTTPGet logic still seems to happen in APL thread 0. There is a fair deal of preparation code first, and as the read streams come in a, a fair deal of housekeeping and decoding. In fact, to most part it seems that only the "DRC.Wait cmd 5000" potentially invokes multiple cores?

Naturally, that IS the most relevant part, the actual transmission. I am likely at least somewhat wrong in my thinking here, and i'd be happy to see any discussion about the matter of threading behavior.

The task in my case is ONLY to read various XML strings, repeatedly, by schedule/que etc.

The .net 4.5 example was intended for benchmarking against Conga, and now we must notice, that i execute these under a condition where the CPU (thread 0) is constantly in a loop - there aren't many extra cycles available; depends a bit on the speed of the GPU (where a slow GPU causes more free time for a fast CPU). It's turn-based, the CPU calcs and batches for the GPU, then the GPU paints, letting the CPU start again, etc. Nevertheless, i must execute the transmission in this particular environment, making it different from just measuring consumed time by different alternatives in an idling environment. The eventual impact on the user experience only comes by realworld testing.

The options i have are (and my estimates of what happens):
    1. TCPSocket in thread 0
    - Not recommended by Dyalog.
    2. TCPSocket&
    - Same, not recommended.
    3. Conga.HttpGet
    - Copy DRC namespace, invoke new conga25.dll - shared between thread 0 and core(s) ?. Blockfreezes my loop when the housekeeping in thread 0 happens.
    4. Conga.HttpGet&
    - In practice probably as above, but won't blockfreeze my loop, slows it down for a while though. Probably the fastest/smoothest solution.
    5. .net 4 sync WebRequest.Create url/GetResponse/StreamReader/ReadToEnd
    - In thread 0, freezeblocking.
    6. .net 4 sync WebRequest.Create & [rest as 5]
    - Very much the same, still in APL's core only, won't freezeblock but slows down for a while.
    7. .net 4 async, where the OS executes on core n and delivers data segments to my APL callback fn in thread n on APL's core.
    - Probably a bit slower than alt. 4. Notice here, that APL automatically executes the callback in an own thread n. This is the original example, that i couldn't get to function

Of the above, 3, 4 and 7 use multiple cores.

Opinions? :-)

Code: Select all
:Class RequestState

:Access Public

    url←'http://www.stormwind.fi'

    :Field Public BufferSize←1024
    :Field Public RequestData←#.StringBuilder
    :Field Public BufferRead←#.ByRef
    :Field Public Request←#.WebRequest
    :Field Public ResponseStream←#.Stream
    :Field Public StreamDecode←#.Encoding.UTF8.GetDecoder ⍝ Create Decoder for appropriate enconding type.
     

    ∇ make0
      :Access Public
      :Implements Constructor
     
      BufferRead←#.ByRef.New⊂BufferSize⍴' '
      RequestData←#.StringBuilder.New #.String.Empty
      Request←⎕NULL
      ResponseStream←⎕NULL
    ∇

:EndClass


Code: Select all
:Class ClientGetAsync

:Access Public

⍝    :field public allDone←#.ManualResetEvent

    BUFFER_SIZE←1024

    ∇ Main;ar;httpSite;r;rs;wreq
      :Implements Constructor
      :Access Public
      httpSite←#.Uri.New'http://www.stormwind.fi'
      wreq←#.WebRequest.Create httpSite
      rs←⎕NEW #._Http.RequestState
      rs.Request←wreq
⍝     #.DISP,¨rs.(a,[1.1]⍎¨a←⎕NL ¯2)
      ar←#.AsyncCallback.New ⎕OR'RespCallback'
      r←wreq.BeginGetResponse ar rs
    ∇


    ∇ RespCallback arg;req;resp;rc;rs;ResponseStream
      :Access Public
      'resp'
      rs←arg.AsyncState
      req←rs.Request
      resp←req.EndGetResponse arg
      ResponseStream←resp.GetResponseStream
      rs.ResponseStream←ResponseStream
      rc←#.AsyncCallback.New ⎕OR'#._Http.ReadCallback'
      ResponseStream.BeginRead rs.BufferRead 0 BUFFER_SIZE rc rs
    ∇


    ∇ ReadCallback arg;ar;charBuffer;len;read;responseStream;rs;str
      :Access Public
      'read'
      rs←arg.AsyncState
      responseStream←rs.ResponseStream
      :If 0<read←responseStream.EndRead arg      ⍝ Integer, length of data
          charBuffer←#.ByRef.New⊂BUFFER_SIZE⍴' ' ⍝ charBuffer←⎕NEW Char[1024]
          len←rs.StreamDecode.GetChars rs.BufferRead 0 read charBuffer 0
          str←#.String.New charBuffer 0 len
          rs.RequestData.Append #.Encoding.ASCII.GetString rs.BufferRead 0 read
          a←responseStream.BeginRead rs.BufferRead 0 BUFFER_SIZE rc rs
      :Else
          :If rs.RequestData.Length>0
              rs.RequestData.Length'bytes'
              rs.RequestData.ToString
          :End
          responseStream.Close
      :End
    ∇

:EndClass


The above doesn't function, the RespCallback never gets called upon (the missing ManualResetEvent handling may be why... or simply because i cannot have callback functions in the :Class). If i do it in traditional APL code, it does get called, but arg.AsyncState causes a VALUE error (arg lacks the AsyncState).
Tomas Gustafsson
 
Posts: 101
Joined: Mon Sep 19, 2011 6:43 pm

Re: Http Get from C# to APL

Postby paulmansour on Tue Jan 06, 2015 4:49 pm

Tomas,

I was unaware that Conga used multiple cores.

I also did not think that using a new thread implied using additional cores, which I think you are saying. Is that true?

Paul
paulmansour
 
Posts: 420
Joined: Fri Oct 03, 2008 4:14 pm

Re: Http Get from C# to APL

Postby Tomas Gustafsson on Tue Jan 06, 2015 9:17 pm

Hm.. At least the Conga documentation says:

Outside the APL session, Conga (which is written in C) uses multiple operating system threads to handle TCP communications. It will handle communications independently of what the interpreter is doing, and return each result to the APL thread which is waiting, as appropriate.


I distinguish between three threading options:

1. "thread 0" - APL's thread on APL's CPU core.
2. "thread n" - APL's other thread but still on APL's CPU core only.
3. "core n" - a process initiated by APL, either by Conga or a .net call.

The cases 3,4 and 7 do this (if i got it right) to various extent. What i do not know is how various extent - would be nice to see a comment on that. The Conga's Samples.HttpGet is synchronously written code, in that it has no &'s. But it invokes a dll call, that apparently jumps to and performs in another core, so it blocks HttpGet at that calling point (locally, in APL execution) BUT doesn't necessarily place burden on the core that APL's thread 0 sits in, while doing that blocking (which is good). Yet, since Samples.HttpGet is loopy-loopy here, the multi-core transmissions part results are then assembled back into a single result in thread 0, which i guess is not so good (why not in the dll?). Is this how it works? Same goes for the .net option, where i may get multiple callbacks to thread 0 (with the difference, that .net rolls around an object holding a decoder/something, so i don't really know all of what happens where :-)).

In any case, i take it i should be always calling Samples.HttpGet&, not Samples.HttpGet?
Tomas Gustafsson
 
Posts: 101
Joined: Mon Sep 19, 2011 6:43 pm

Re: Http Get from C# to APL

Postby paulmansour on Wed Jan 07, 2015 3:10 am

Interesting stuff, hopefully Bjorn can weigh in on the way Conga uses cores.

I'm not really sure if conga is using multiple cores itself to gather TCP/IP messages, but regardless of that Samples.HttpGet has to be "loopy-loopy" (though more on this below)due to the HTTP protocol itself. I too wondered about this myself awhile back - why not just do it in the dll?- but an HTTP app has to be able to inspect the message bit by bit as it arrives. For example, you might want to reject a message with a 1 GB payload before you receive the whole thing, so you want to be able to inspect the headers as soon as they arrive, send a response, and close the connection.

You will want to thread HttpGet simply if you don't want to wait for the response. But I think you will need a cover function to thread, so you can get the response and do something with it, rather than threading HttpGet directly.

Regarding loopy-loopy and the thread issue, I just posted "Rumba" in another thread which is an implementation of HTTP/1.1 over Conga. I am sure you do not want even more code than Conga and HttpGet, but you might want to take a look. I take a slightly different approach to sending and receiving http messages from the client. First, and this is just a matter of taste really, there are no loops, all replaced with tail calls in dfns. Second, the receiving mechanism is threaded internally, because I need to be able to send more than one message on a connection before getting the responses.

All that said, I don't think it would do anything for you that Conga.HttpGet under another thread would.
paulmansour
 
Posts: 420
Joined: Fri Oct 03, 2008 4:14 pm

Re: Http Get from C# to APL

Postby Tomas Gustafsson on Wed Jan 07, 2015 3:36 am

A bit wiser re. the .net code.

(Some parts left out) I have a class:
      :Class RequestState
and create an instance if it:
      rs←⎕NEW #._Http.RequestState
Then i have a callback function:
      ∇ RespCallback4 arg;req;resp;rc;rs;ResponseStream
res←arg.AsyncState etc...
and create an object of it:
      ar←#.AsyncCallback.New ⎕OR'#._Http.ReadCallback4'
So far so good. Then i pass ar and rs to a .net function:
      r←wreq.BeginGetResponse ar rs
that is supposed to call the ar callback function, once it has connected to the web. And it does, BUT as i try on the first line to get the rs object (the APL OO object, that was earlier created) from arg using:
      res←arg.AsyncState
i get a VALUE ERROR (but arg is there, and other arg elements work:
      1:VALUE ERROR
RespCallback4[1] res←arg.AsyncState

arg
System.Net.ContextAwareResult
arg.⎕nl ¯2
AsyncState AsyncWaitHandle CompletedSynchronously IsCompleted
arg.⎕nl ¯3
Equals GetHashCode GetType ReferenceEquals ToString

#.DISP ,¨arg.(AsyncWaitHandle CompletedSynchronously IsCompleted)
┌───────────────────────────────────┬─┬─┐
│ System.Threading.ManualResetEvent │0│1│
└───────────────────────────────────┴─┴─┘
My conclusion is that rs is not at all a .net object, but something solely managed inside APL only? Since IF i set rs to a real .net object, arg.AsyncState holds that object (although it is an object of wrong type, of course).

Q: How do i create the APL OO object rs so that it is a ".net object", recognized and kept by .net? You can see the Class code in an earlier post.

Look at the difference:
      z←⎕NEW _Http.RequestState
z
#.[RequestState]

      z←⎕NEW #.HttpWebResponse
z
System.Net.HttpWebResponse

Brackets / no brackets ??? .net seems to accept rs, but then loses it on the way??

I saw somewhere about "exporting to memory" (in order to be able to create an APL defined OO object), but that was for Dyalog version 11. Appears unnecessary, since i CAN do ⎕NEW _Http.RequestState in 14?
Tomas Gustafsson
 
Posts: 101
Joined: Mon Sep 19, 2011 6:43 pm

Re: Http Get from C# to APL

Postby Morten|Dyalog on Wed Jan 07, 2015 10:14 am

paulmansour wrote:I'm not really sure if conga is using multiple cores itself to gather TCP/IP messages, but regardless of that Samples.HttpGet has to be "loopy-loopy" (though more on this below)due to the HTTP protocol itself. I too wondered about this myself awhile back - why not just do it in the dll?


Conga is handling all TCP communications using threads which run in parallel with the APL interpreter, which is what I think Tomas is looking for (he needs 100% of one thread to run his main loop). We have considered adding a mechanism to Conga to declare that it should wait for a complete HTTP response before reporting anything back to APL: I think this would give Tomas everything that he needs. If you know you are waiting for a medium-sized payload, you probably don't need to sniff at it as the bits come in.
User avatar
Morten|Dyalog
 
Posts: 453
Joined: Tue Sep 09, 2008 3:52 pm

Re: Http Get from C# to APL

Postby JohnD|Dyalog on Wed Jan 07, 2015 12:05 pm

Hi Tomas,

You are correct rs is not "a .net object", it is just a namespace in the workspace. The interpreter does not create a .Net object that encapsulates this namespace (although I have been considering something like this - our databinding does something similar).

In order for rs to be available in AsyncState you will need to do an "Export to Memory" - this should create a .net wrapper for that class. Alternatively you could pass some other reference to rs to BeginGetResponse, a unique name, or an index into an array for example.

On a related note, AsyncState generates a VALUE ERROR because the interpreter raises this error when a .Net method or property doesn't return a result (i.e. returns null). We are considering having the interpreter return ⎕NULL in this case, as this would be more symmetrical, and resolve some other inconsistencies in behaviour. We are interested in any and all feedback on this change.

Best Regards,
John Daintree.
User avatar
JohnD|Dyalog
 
Posts: 74
Joined: Wed Oct 01, 2008 9:35 am

Next

Return to APL Chat

Who is online

Users browsing this forum: No registered users and 1 guest