Erlang/OTP Forums

Author Message

<  Erlang  ~  Strange behavior of gen_server logging messages

odi
Posted: Fri Feb 18, 2011 12:19 pm Reply with quote
Joined: 19 Feb 2009 Posts: 9
I have a sample application where a lot of processes send synchronous messages to gen_server which logs it using file module. With 2000 processes, each sending 100 messages of 50 bytes it takes about 15 seconds.
[A]
Client1 ---\
Client2 ---- Server1 --- IO
Client3 ---/

However I noticed something what seemed strange at first - if each message was sent through additional gen_server with call/2 function then logging took only 5 seconds.
[B]
Client1 ---\
Client2 ---- Server1 --- Server2 --- IO
Client3 ---/

My idea was that in [A] messages from clients were accumulating in the Server1 process queue and when message was to be logged by IO then io_reply would go to the end of the queue. I corrected receive statement used in io:execute_request/2 according to OTP-8623 (see my_file:execute_request/2). With this enhancement processing of all messages with 1 gen_server took only 7.5 seconds instead of 15.

Attached files - my_server.erl, my_client.erl, my_file.erl
Usage:
my_server:start_link(dir_proc).
my_server:start_link(redir_proc).
% starts 2000 processes each logging 100 messages of 50 bytes
my_client:start(2000,100,50,{direct, dir_proc, my_file}). % solution A with corrected IO
my_client:start(2000,100,50,{redirect, redir_proc, dir_proc, file}). % solution B with standard IO

I used Erlang R14B.
My question is why the solution with 2 gen_servers (5s) is still faster than the solution with only 1 gen_server (7.5s)?
View user's profile Send private message
odi
Posted: Mon Feb 21, 2011 1:10 pm Reply with quote
Joined: 19 Feb 2009 Posts: 9
After running this program with eprof it turned out that erlang:demonitor/1 is a most expensive function.
In my_file:execute_request/2 function
Code:
receive
   {io_reply, Mref, Reply} ->
       erlang:demonitor(Mref),
       receive
           {'DOWN', Mref, _, _, _} -> true
       after 0 -> true
       end,
       Reply;

it appears that the receive statement after receiving io_reply and demonitoring a process reference is inefficient. According to http://www.erlang.org/doc/man/erlang.html#demonitor-2 it was changed to
Code:
erlang:demonitor(Mref, [flush])

Now my version of a program with only 1 gen_server takes only 3.5 seconds.
View user's profile Send private message
rvirding
Posted: Tue Feb 22, 2011 9:19 am Reply with quote
User Joined: 30 Aug 2006 Posts: 452 Location: Stockholm, Sweden
One reason why the solution with 2 gen_servers is faster could be because of the number of messages in the message queue of the process doing the io request. In the 1 gen_server version there will be 2000 requests in message queue, one from each client as even if the processing is synchronous each client will have sent off a request. In the 2 gen_server version there will only be one request in the queue. As the message queue is scanned for 'DOWN' and 'EXIT' messages for each io request this will take longer time when the input queue is longer. This scanning will also take place in your second improved version even if it is done implicitly by erlang:demonitor/2.

This is a case where knowing how the message queue is processed can help you.

As you know you are writing to a file you might try opening the file in 'raw' mode and using file:write/2 instead. This should be faster but is less versatile.

_________________
Robert Virding, Erlang Solutions Ltd.
View user's profile Send private message Visit poster's website MSN Messenger
odi
Posted: Thu Feb 24, 2011 2:38 pm Reply with quote
Joined: 19 Feb 2009 Posts: 9
Thanks for your reply Robert,
You're right when you say that in the solution [B] there'll be only 1 request in 2nd gen_server's queue but there'll be almost 2000 requests in a 1st gen_server's queue and it has to scan for 'DOWN' and 'EXIT' messages too. Main problem in solution [A] was an inefficient io_reply receive statement.
I also checked the 'raw' mode as you suggested - it is faster in a 2 gen_server version yet still noticably slower in a 1 gen_server solution. I looked at a code of prim_file which is used underneath and it probably has the same problem; inefficient receive statement used to get response from a file driver.
View user's profile Send private message
rvirding
Posted: Fri Feb 25, 2011 4:18 pm Reply with quote
User Joined: 30 Aug 2006 Posts: 452 Location: Stockholm, Sweden
odi wrote:
You're right when you say that in the solution there'll be only 1 request in 2nd gen_server's queue but there'll be almost 2000 requests in a 1st gen_server's queue and it has to scan for 'DOWN' and 'EXIT' messages too. Main problem in solution [A] was an inefficient io_reply receive statement.


No! Well yes, there will be almost 2000 requests on in the 1st server's queue BUT this doesn't matter in case. It is the io_reply which does the check for 'DOWN' and 'EXIT' and so it is ONLY in the server which writes to the file where the input queue length matters. The other requests don't result in that type of check, they just take the next request, do it and send back a reply, so the input queue length is unimportant.

So in case [A] it is the server which is writing to the file and does the checks on the input queue. In case [\B] while the 1st server does have a long input queue it does not check it and only sends one message at a time to the 2nd server (gen:call/2 is synchronous) so the input queue of the 2nd server will be short and the io_reply will have very short queue in which to scan for 'DOWN' and 'EXIT' (one message).

So in the second case you will have a long input queue where the length doesn't matter and a short one where it does matter. That is why it is faster.

This way of scanning the input queue is necessary for io_reply to ensure that the process which handles the actual io-requests is alive and to check if it dies before it returns a reply. Otherwise the calling process could hang.

_________________
Robert Virding, Erlang Solutions Ltd.
View user's profile Send private message Visit poster's website MSN Messenger
odi
Posted: Fri Mar 04, 2011 7:42 am Reply with quote
Joined: 19 Feb 2009 Posts: 9
Maybe I'm misunderstanding something but in gen_server's call there is also a check for 'DOWN' and 'EXIT' messages after reply is received (it's done through erlang:demonitor/2 - see gen_server:do_call/4).
According to you:
rvirding wrote:
As the message queue is scanned for 'DOWN' and 'EXIT' messages for each io request this will take longer time when the input queue is longer. This scanning will also take place in your second improved version even if it is done implicitly by erlang:demonitor/2.

In both cases if there's a long input queue in a gen_server process the queue length does matter however it was corrected with OTP-8623 enhancement.
View user's profile Send private message
dongdongwu
Posted: Thu Sep 20, 2012 6:08 am Reply with quote
User Joined: 19 Sep 2012 Posts: 236
His good friend Diane said: "Christian Louboutin Men Shoes was a magician, he make shoes is immediately put his female people with legs and advantage. He understands women wanted to do and can make them into beautiful Cinderella." Madonna often in its concert wearing Christian louboutin high heels , and some famous superstar like Angelina jolie, mariah Carey, beyonce Knowles, the famous Japanese singer YaYouMei Hamasaki helps Christian Louboutin Men Shoes set up its powerful position. The youngest customers will count Tom cruise's daughter sully cruz. Louboutin made for only a pair of handmade Christian Louboutin high heel Shoes! Want to be more fashion? Put on Christian Louboutin Outlet !
Candy colors of the chalaza high-heeled shoes with lolita type allure, set full finely gem blue "neon shoes" is to need to use "sexy" to describe. Each pair are worth careful appreciation of lithe and graceful fairy ludaoli, what kind of most let you move?Christian Louboutin Men Shoes that one brush red is always cannot resist the temptation, Christian Louboutin men outlet continue to use the days of high 8cm above slender heel proclaim the sexy and luxuriant. The bowknot on black pointed high-heeled shoes with sharp rivet concomitant, wild python met enchanting color printing grain, It is that pairs of high-heeled shoes lets Carrie more feminine flavour. Like Christian Louboutin for men her word.
View user's profile Send private message

Display posts from previous:  

All times are GMT
Page 1 of 1
This forum is locked: you cannot post, reply to, or edit topics.

Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum