Morning Folks, As most of you know there were a few people who had the following three bugs: * CLOSE_WAIT: Lots of sockets in CLOSE_WAIT state. * 99% CPU: Mongrel''s getting "stuck" pegged at 99% CPU. * LEAK: Memory leak. I''ve successfully fixed these bugs or attributed them to one main cause: pstore. First, the memory leak was because of a bug in how the GC in Ruby was collecting threads after they used a Mutex. Don''t ask me why, but switching to Sync fixed it. Problem is, this also causes the leak on Win32. Still working on that problem. Now for the recommendations: 1) DON''T USE PSTORE AS A SESSION STORE! All of the people who had Mongrel processes going crazy, blocking, locking, or just generally doing bad things had a pstore as their session storage option. What happens is the pstore isn''t that great when multiple processes access it, and if one Mongrel has problems pulling an object from the pstore then it''ll explode. Use the file store when you develop, and use the database or memcached store in production. You should also be looking for other ways processes are sharing resources when they lock up or do weird things. Try running with just one process, and if you don''t have any problems then it''s a resource locking problem (most likely). 2) DON''T STORE COMPLEX OBJECTS IN THE SESSION! This especially goes for you Java people who think the session store is a temporary database. The session really only works for simple types like integers, strings, etc. You *must* follow the mantra of "Share Nothing" and either store everything in the database or use form fields and GET parameters to make it stateless. As I''ve said repeatedly, "If rails-core don''t do it, you don''t do it." Rails-core does not do this. You don''t do it. 3) USE THE USR1 LOGGING! Every person who had a problem with Mongrel processes getting stuck could have used the new USR1 logging to quickly find out what Rails action was blocking the process. Once I got a good USR1 log it was trivial to see a message stating that 981 threads were waiting for one Rails action. Once I pointed this out, they went back and figured out what the problem was. Use "killall -USR1 mongrel_rails" to turn this on temporarily, and Mongrel will log the numbers of threads waiting for each request and which are remaining to be processed by Mongrel. It''s very handy. Hitting the mongrels with USR1 again turns it off. It''s also pretty fast so you could leave it on all the time and not see a big performance hit. 4) YOUR RAILS CODE SUCKS! I hate to say it folks, and I''ll gladly help people when they''ve got a problem, but please check your Rails code first, and assume it''s broken. Lots and lots and lots and lots of sites are running high traffic Mongrel installs without any problems. If you have a problem, then you''ve got something different. I know, you''re absolutely perfect and there''s nothing you''re doing strange, but really look. In all the cases mentioned above they were also doing something weird. Things to look for: * Using extensions to libraries you didn''t write. If you have a library that you bought and then wrapped with Ruby''s extensions, then chances are it''s *not* designed for multi-threaded Ruby action. Move this library to a sequentially run DRb process shared by all your Mongrel processes. * Trying to resolve hosts against broken DNS. Many people have slow rails actions because they''re doing tons of DNS resolving of hosts. Make sure your internal DNS is fast, reliable and consider using dnsmasq running locally to cache the results. Main problem is Ruby''s resolving blocks the process. * Use pstore as the session store, so probably using pstore for nearly anything is bad. * Using your own custom network protocols. If you just wrote it then it''s broken. #1, #2, and #3 rule of programming. It''s not Mongrel. * Using the mysql.rb instead of installing the actual mysql compiled gem. The mysql.rb is just for development, and it sucks horribly. Thanks for your time folks, and keep coming with those bugs. -- Zed A. Shaw http://www.zedshaw.com/ http://mongrel.rubyforge.org/ http://www.lingr.com/room/3yXhqKbfPy8 -- Come get help.
On 9/3/06, Zed Shaw <zedshaw at zedshaw.com> wrote:> First, the memory leak was because of a bug in how the GC in Ruby was > collecting threads after they used a Mutex. Don''t ask me why, but > switching to Sync fixed it. Problem is, this also causes the leak on > Win32. Still working on that problem.I still doubt that Mutex itself is the problem here. Sync uses the same algorithm for exclusive locking, and I can run _millions_ of threads through IOWA, which operates similarly to Mutex with regard to how it spawns threads, without any memory leaks, and Mutex gets used with every one of those requests/threads.> All of the people who had Mongrel processes going crazy, blocking, > locking, or just generally doing bad things had a pstore as their > session storage option. What happens is the pstore isn''t that great > when multiple processes access it, and if one Mongrel has problems > pulling an object from the pstore then it''ll explode. Use the file > store when you develop, and use the database or memcached store in > production.I have had similar misery with PStore. I''ve been meaning to get it done for a month, but I have a process/threadsafe to-disk persistence library that I will bundle and release separately from IOWA. It provides relatively fast persistence and could be used to store sessions like people use PStore. I''ll try to finally get that done today if anyone wants to try it out as a PStore replacement for storing sessions to disk. Kirk Haines
On 9/3/06, Kirk Haines <wyhaines at gmail.com> wrote:> I still doubt that Mutex itself is the problem here. Sync uses the > same algorithm for exclusive locking, and I can run _millions_ of > threads through IOWA, which operates similarly to Mutex with regard towhich runs similarly to Mongrel.... Sorry for the confusion. Kirk Haines
On Sun, 2006-09-03 at 10:42 -0600, Kirk Haines wrote:> On 9/3/06, Zed Shaw <zedshaw at zedshaw.com> wrote: > > > First, the memory leak was because of a bug in how the GC in Ruby was > > collecting threads after they used a Mutex. Don''t ask me why, but > > switching to Sync fixed it. Problem is, this also causes the leak on > > Win32. Still working on that problem. > > I still doubt that Mutex itself is the problem here. Sync uses the > same algorithm for exclusive locking, and I can run _millions_ of > threads through IOWA, which operates similarly to Mutex with regard to > how it spawns threads, without any memory leaks, and Mutex gets used > with every one of those requests/threads.Theorize all you want, but all I know is, use Mutex, process gets killed, use Sync, process stays up. Can''t argue with the evidence. -- Zed A. Shaw http://www.zedshaw.com/ http://mongrel.rubyforge.org/ http://www.lingr.com/room/3yXhqKbfPy8 -- Come get help.
On 9/3/06, Zed Shaw <zedshaw at zedshaw.com> wrote:> Theorize all you want, but all I know is, use Mutex, process gets > killed, use Sync, process stays up. Can''t argue with the evidence.Sure I can. Your conclusion about Mutex is like the conclusion once drawn about the sun. It comes up in the east and goes down in the west, so the evidence clearly shows that the sun rotates around the earth, right? There is nothing wrong with Mutex. It''s an incredibly simple piece of code and can quite clearly be demonstrated not to leak. I''m not arguing with the fact that for some users simply swapping Sync in place of Mutex appears to clear a problem. I''m just arguing with your conclusion that this is because Mutex is broken or because Ruby is leaking memory when it is used. Kirk Haines
On Sun, 2006-09-03 at 11:48 -0600, Kirk Haines wrote:> On 9/3/06, Zed Shaw <zedshaw at zedshaw.com> wrote: > > > Theorize all you want, but all I know is, use Mutex, process gets > > killed, use Sync, process stays up. Can''t argue with the evidence. > > Sure I can. Your conclusion about Mutex is like the conclusion once > drawn about the sun. It comes up in the east and goes down in the > west, so the evidence clearly shows that the sun rotates around the > earth, right? > > There is nothing wrong with Mutex. It''s an incredibly simple piece of > code and can quite clearly be demonstrated not to leak. > > I''m not arguing with the fact that for some users simply swapping Sync > in place of Mutex appears to clear a problem. I''m just arguing with > your conclusion that this is because Mutex is broken or because Ruby > is leaking memory when it is used.I like you Kirk, so don''t take it personally, it''s just an incredibly sore spot with me since I''ve been complaining about this for ages and everyone keeps telling me I''m crazy despite what I demonstrate. But, explain this: http://pastie.caboo.se/10194 vs. http://pastie.caboo.se/10317 First one leaks, second one doesn''t (with graphs even). What''s worse is the inverse is true on win32. These scripts have no Mongrel code, no Rails code, they''re just short Ruby scripts. Now, it''s not about users, it''s about the two bug reductions that simulate how Mongrel uses processes demonstrating a leak in both 1.8.5 and 1.8.4. And it''s insulting that you compare my careful examination of the problem and numerous people''s countless investigation into this as nothing more than tribal Sun worship. If anything the Ruby morons (not you) running around ignoring Ruby''s problems are the religious fanatics who need to get a grip and fix this crap before guys like me get fed up and run happily to a platform that doesn''t suck. It also has nothing to do with the Sun, Ptolemaic Astronomy, Polynesian navigation by dead reckoning, or other stuff you read about in that one speech/essay by Feynman about Cargo Cults. I have evidence, many other people reported the same results in different systems, and I have demonstration scripts. The only evidence other people have produced is to write a different script that doesn''t leak, which doesn''t fix the script that does leak. Instead, the "garbage collection apologists" insist that it''s not Mutex, yet the change log for 1.8.5 says there were bugs in the GC code for Threads. I''m betting that it''s not fixed, and that people like you who keep arguing it''s not a bug are doing nothing but making it so nobody has to admit three things: 1) Threads suck ass in Ruby. 2) The GC sucks even worse. 3) Combining two forms of suckage makes for ultra suckage. But hey, I''ve been over this a billion times with tons of people, and all I get in response is that I''m totally wrong because someone else can write a different script that doesn''t leak. Yet, this different script doesn''t fix the script that does leak given above. It''s a never ending truly Ptolemaic cycle of Ruby on Ruby when the real problem is deep in the morass of C code that makes up the wonderful split between Thread GC and "everything else GC". So, sorry Kirk, I''m not full of crap or making this up or anything else you''re implying. I have demonstration code, I and others run the code and it happens, I have graphs, statistics, measurements, and demonstrated fixes. Oh no, it''s not Ruby, it''s me. Meanwhile, I don''t even have time to go investigate the problem because I''m trying to get this stuff out so people can do their jobs. I''ll leave it to the apologists to argue that everything''s just quite alright and start looking for my next platform. I hear Lua likes to fix their virtual machine. Maybe I''ll start there. Again, sorry for ranting at you directly, but it really doesn''t sit right with me to have my careful measurements compared with ancient psuedo-science. -- Zed A. Shaw http://www.zedshaw.com/ http://mongrel.rubyforge.org/ http://www.lingr.com/room/3yXhqKbfPy8 -- Come get help.
Zed wrote:> * Using the mysql.rb instead of installing the actual mysql compiled > gem. The mysql.rb is just for development, and it sucks horribly.Please forgive the stupid question, but how does one tell whether one is using the mysql compiled gem or not? I''ve installed it, apparently successfully, but I''d feel happier if I could be certain that Rails was using it... Thanks! -- paul.butcher->msgCount++ Snetterton, Castle Combe, Cadwell Park... Who says I have a one track mind? MSN: paul at paulbutcher.com AIM: paulrabutcher Skype: paulrabutcher LinkedIn: https://www.linkedin.com/in/paulbutcher
On 9/3/06, Paul Butcher <paul at paulbutcher.com> wrote:> Please forgive the stupid question, but how does one tell whether one is > using the mysql compiled gem or not? I''ve installed it, apparently > successfully, but I''d feel happier if I could be certain that Rails was > using it...General procedure without really knowing too much about the drivers ;-) : either - try running coverage, to see which of them gets executed (probably too slow, too much work) - look at both versions to spot some differences in e.g. private method names and check it in your code. - try induce some exception in the mysql code and check the stack trace. - examine caller() inside a block called from some mysql stuff - the easiest one: look for some VERSION constant or similar thing.
Try:> irbirb> require ''mysql'' If it works, you''ve got the compiled version, if it throws an exception, you don''t. That''s how Rails itself checks for it. -- Josh H. On 9/4/06, Jan Svitok <jan.svitok at gmail.com> wrote:> > On 9/3/06, Paul Butcher <paul at paulbutcher.com> wrote: > > Please forgive the stupid question, but how does one tell whether one is > > using the mysql compiled gem or not? I''ve installed it, apparently > > successfully, but I''d feel happier if I could be certain that Rails was > > using it... > > General procedure without really knowing too much about the drivers ;-) : > either > - try running coverage, to see which of them gets executed (probably > too slow, too much work) > - look at both versions to spot some differences in e.g. private > method names and check it in your code. > - try induce some exception in the mysql code and check the stack trace. > - examine caller() inside a block called from some mysql stuff > - the easiest one: look for some VERSION constant or similar thing. > _______________________________________________ > Mongrel-users mailing list > Mongrel-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/mongrel-users >-------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/mongrel-users/attachments/20060904/bfb7dbdf/attachment.html
I am wondering the same thing. So what exactly are using to do in order to check? On 9/3/06, Joshua Harvey <joshmh at gmail.com> wrote:> > Try: > > > irb > irb> require ''mysql'' > > If it works, you''ve got the compiled version, if it throws an exception, > you don''t. That''s how Rails itself checks for it. > > -- Josh H. > > > > On 9/4/06, Jan Svitok <jan.svitok at gmail.com> wrote: > > > > On 9/3/06, Paul Butcher <paul at paulbutcher.com> wrote: > > > Please forgive the stupid question, but how does one tell whether one > > is > > > using the mysql compiled gem or not? I''ve installed it, apparently > > > successfully, but I''d feel happier if I could be certain that Rails > > was > > > using it... > > > > General procedure without really knowing too much about the drivers ;-) > > : either > > - try running coverage, to see which of them gets executed (probably > > too slow, too much work) > > - look at both versions to spot some differences in e.g. private > > method names and check it in your code. > > - try induce some exception in the mysql code and check the stack trace. > > - examine caller() inside a block called from some mysql stuff > > - the easiest one: look for some VERSION constant or similar thing. > > _______________________________________________ > > Mongrel-users mailing list > > Mongrel-users at rubyforge.org > > http://rubyforge.org/mailman/listinfo/mongrel-users > > > > > _______________________________________________ > Mongrel-users mailing list > Mongrel-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/mongrel-users > >-- Jared Brown jaredbrown at gmail.com (765) 409-0875 7001 Central Ave Indianapolis, IN 46220 -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/mongrel-users/attachments/20060903/5db94255/attachment.html
On 9/3/06, Zed Shaw <zedshaw at zedshaw.com> wrote:> But, explain this: > > http://pastie.caboo.se/10194 > > > vs. > > http://pastie.caboo.se/10317 > > First one leaks, second one doesn''t (with graphs even). What''s worse is > the inverse is true on win32. These scripts have no Mongrel code, no > Rails code, they''re just short Ruby scripts. > > Now, it''s not about users, it''s about the two bug reductions that > simulate how Mongrel uses processes demonstrating a leak in both 1.8.5 > and 1.8.4. And it''s insulting that you compare my careful examination > of the problem and numerous people''s countless investigation into this > as nothing more than tribal Sun worship. If anything the Ruby morons > (not you) running around ignoring Ruby''s problems are the religious > fanatics who need to get a grip and fix this crap before guys like me > get fed up and run happily to a platform that doesn''t suck.No. People who thought that the sun revolved around the earth made a perfectly logical assumption, given the evidence that they observed. They were just missing some information that would have led them to a more accurate conclusion. When I read your original post about Mutex and Sync, and looked at the graphs, my first thought was, "Ugh. Maybe that''s where my memory leak comes from!" I slept on it and when I woke in the morning, I dug into your test scripts, the code for Mutex and Sync, and the GC subsystem. I hacked the GC to give me detailed information about allocations, sweeps, free hash spots, etc... I modified your scripts to give me detailed object counts. I ran numerous variations of your tests. I couldn''t find a leak. In fact, your test script itself (with Mutex) ate memory until it reached a stable point, then dropped a bit, then climbed back up to that stable point. I could make it behave worse by making the thread do something that actually creates a lot of garbage objects for the GC to deal with, but it still did not seem to be a leak. It did exhibit some curious behavior that I am not satisfied that I understand, though. When in a work loop that actually creates a lot of garbage objects, many, many more of them are accumulated when running under Mutex than when running under Sync. They seem to accumulate in greater numbers than they are cleared by the GC. However, doing nothing more than slowing the Mutex operation down to around the same speed as a Sync fixed that problem. Sync uses more up front resources, and is slower than Mutex. Both are implemented in pure ruby, and if Mutex leaks, there is no hope, because it is simpler than almost anything anybody writes in Ruby. Have you tried monitoring objectspace counts in a Mongrel process that appears to be leaking? Have you tried running it under valgrind? Have you tried putting diagnostic hooks into a specially compiled Ruby so that you can see when GC is called and when space is added to the heap while running a leaking Mongrel? I don''t have any doubt at all that something funny is happening, but I have yet to see anything, including your test scripts and graphs, that actually indict Mutex. BTW, in my own case, I did end up finding a memory leak in Ruby. It was a stupid error in Hash causing some memory to never be freed. I would not be all surprised if there are other similar errors hiding in Ruby. Kirk Haines
On Sep 3, 2006, at 7:10 PM, Kirk Haines wrote:> I don''t have any doubt at all that something funny is happening, but I > have yet to see anything, including your test scripts and graphs, that > actually indict Mutex.I posted something on the ruby talk list that directly pointed at Mutex. Yes, Mutex sooner-or-later stabilises, but that really can be later rather than sooner. Try this, run your test but this time remove all references to the Mutex before garbage collecting. Watch what (doesn''t) happen. Sync doesn''t have this problem. Cheers, Bob ---- Bob Hutchison -- blogs at <http://www.recursive.ca/ hutch/> Recursive Design Inc. -- <http://www.recursive.ca/> Raconteur -- <http://www.raconteur.info/> xampl for Ruby -- <http://rubyforge.org/projects/xampl/>
On Sun, Sep 03, 2006 at 09:18:06AM -0700, Zed Shaw wrote:> 2) DON''T STORE COMPLEX OBJECTS IN THE SESSION! > > This especially goes for you Java people who think the session store is > a temporary database. The session really only works for simple types > like integers, strings, etc. You *must* follow the mantra of "Share > Nothing" and either store everything in the database or use form fields > and GET parameters to make it stateless. As I''ve said repeatedly, "If > rails-core don''t do it, you don''t do it." Rails-core does not do this. > You don''t do it.This piece of advice I find a little troubling. Often you have to store a lot of data temporarily in your application, f.ex. with multipage form submissions. Having to store only simple types will make this much more complicated compared to simply storing a single object in the session which is repeatedly updated until stored in the database. Is the data in the session not simply marshalled and then read back on the next request? If so, what is the difference between simple and complex types, they should marshal and unmarshal equally well, yes? Am I missing something here? -- Thanks, - Jacob Atzen
On Sep 4, 2006, at 11:02 AM, Jacob Atzen wrote:> On Sun, Sep 03, 2006 at 09:18:06AM -0700, Zed Shaw wrote: >> 2) DON''T STORE COMPLEX OBJECTS IN THE SESSION! >> >> This especially goes for you Java people who think the session >> store is >> a temporary database. The session really only works for simple types >> like integers, strings, etc. You *must* follow the mantra of "Share >> Nothing" and either store everything in the database or use form >> fields >> and GET parameters to make it stateless. As I''ve said repeatedly, >> "If >> rails-core don''t do it, you don''t do it." Rails-core does not do >> this. >> You don''t do it. > > This piece of advice I find a little troubling. Often you have to > store > a lot of data temporarily in your application, f.ex. with multipage > form > submissions. Having to store only simple types will make this much > more > complicated compared to simply storing a single object in the session > which is repeatedly updated until stored in the database. > > Is the data in the session not simply marshalled and then read back on > the next request? If so, what is the difference between simple and > complex types, they should marshal and unmarshal equally well, yes?This is true of all webapp servers I''ve ever used that serialises/ restores sessions. The source of trouble I''ve encountered is where there is some sort of object identity that the application is assuming. This can be very subtle. "Share nothing" is one solution, the other is to rely on some mechanism (say the DB, or in my case, xampl) to manage this for you. (If you are thinking of storing what amounts to structured data, then you are probably okay, except that this inevitably evolves into something else and you''ll end up trying to debug a nasty situation and you''ll be looking at the change that did it and that''ll be nowhere near where the problem actually is.) I''m sure there are other problems, and they''ll be subtle too. Cheers, Bob> > Am I missing something here? > > -- > Thanks, > - Jacob Atzen > _______________________________________________ > Mongrel-users mailing list > Mongrel-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/mongrel-users---- Bob Hutchison -- blogs at <http://www.recursive.ca/ hutch/> Recursive Design Inc. -- <http://www.recursive.ca/> Raconteur -- <http://www.raconteur.info/> xampl for Ruby -- <http://rubyforge.org/projects/xampl/>
On Sep 4, 2006, at 11:02 AM, Jacob Atzen wrote:> On Sun, Sep 03, 2006 at 09:18:06AM -0700, Zed Shaw wrote: >> 2) DON''T STORE COMPLEX OBJECTS IN THE SESSION! >> >> This especially goes for you Java people who think the session >> store is >> a temporary database. The session really only works for simple types >> like integers, strings, etc. You *must* follow the mantra of "Share >> Nothing" and either store everything in the database or use form >> fields >> and GET parameters to make it stateless. As I''ve said repeatedly, >> "If >> rails-core don''t do it, you don''t do it." Rails-core does not do >> this. >> You don''t do it. > > This piece of advice I find a little troubling. Often you have to > store > a lot of data temporarily in your application, f.ex. with multipage > form > submissions. Having to store only simple types will make this much > more > complicated compared to simply storing a single object in the session > which is repeatedly updated until stored in the database. > > Is the data in the session not simply marshalled and then read back on > the next request? If so, what is the difference between simple and > complex types, they should marshal and unmarshal equally well, yes?This is true of all webapp servers I''ve ever used that serialises/ restores sessions. The source of trouble I''ve encountered is where there is some sort of object identity that the application is assuming. This can be very subtle. "Share nothing" is one solution, the other is to rely on some mechanism (say the DB, or in my case, xampl) to manage this for you. (If you are thinking of storing what amounts to structured data, then you are probably okay, except that this inevitably evolves into something else and you''ll end up trying to debug a nasty situation and you''ll be looking at the change that did it and that''ll be nowhere near where the problem actually is.) I''m sure there are other problems, and they''ll be subtle too. Cheers, Bob> > Am I missing something here? > > -- > Thanks, > - Jacob Atzen > _______________________________________________ > Mongrel-users mailing list > Mongrel-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/mongrel-users---- Bob Hutchison -- blogs at <http://www.recursive.ca/ hutch/> Recursive Design Inc. -- <http://www.recursive.ca/> Raconteur -- <http://www.raconteur.info/> xampl for Ruby -- <http://rubyforge.org/projects/xampl/>
On Mon, 2006-09-04 at 17:02 +0200, Jacob Atzen wrote:> On Sun, Sep 03, 2006 at 09:18:06AM -0700, Zed Shaw wrote: > > 2) DON''T STORE COMPLEX OBJECTS IN THE SESSION! > > > > This especially goes for you Java people who think the session store is > > a temporary database. The session really only works for simple types > > like integers, strings, etc. You *must* follow the mantra of "Share > > Nothing" and either store everything in the database or use form fields > > and GET parameters to make it stateless. As I''ve said repeatedly, "If > > rails-core don''t do it, you don''t do it." Rails-core does not do this. > > You don''t do it. > > This piece of advice I find a little troubling. Often you have to store > a lot of data temporarily in your application, f.ex. with multipage form > submissions. Having to store only simple types will make this much more > complicated compared to simply storing a single object in the session > which is repeatedly updated until stored in the database. > > Is the data in the session not simply marshalled and then read back on > the next request? If so, what is the difference between simple and > complex types, they should marshal and unmarshal equally well, yes? > > Am I missing something here? >I generally do these things to work with large objects that are built in stages: 1) Include a "state" variable that determines what stage of its preparation it is currently at. This gets saved and updated as you operate making it possible to restore it to where it needs to continue. Very handy in situations where people need to save their job and come back. 2) Store only the object id in the user''s session, or better yet associate the user with the object(s) being built and call that association their "queue". This lets them create and manage jobs as needed. 3) Make the larger object composed of smaller object representing the parts that make up your forms/stages. This lets you put the validations in the smaller objects and save them as the user goes, but then use a large complete object later. 4) If you have to use one giganto object then find a way to either not do validations or do them in a delayed fashion (this is a royal pain). 5) Finally, use Ajax in key places to make building and modifying the smaller objects more seamless. Staged forms are kind of an addiction in business process redesign, and many times when you''re forced to break the process down into smaller data objects you begin to see a pattern that lets you redesign the process to be simpler. Many times what you think are discrete stages are actually very similar. But, if you''ve *got* to use a staged form process then really use the state field to implement a state machine. This gives you more error correction capabilities and makes it easier to translate people''s in process work when the state machine changes. You just run a migration that moves everyone to the new required state, or zaps their in process work (if that''s possible). Another thing you''ll find is that this is faster than session storage because AR (and many ORM) store only the deltas. Since smaller data chunks are getting saved between form views it tends to go quicker than saving the whole massive blob to the session after marshaling. Hope that helps. -- Zed A. Shaw http://www.zedshaw.com/ http://mongrel.rubyforge.org/ http://www.lingr.com/room/3yXhqKbfPy8 -- Come get help.
Zed Shaw <zedshaw at zedshaw.com> writes:> On Sun, 2006-09-03 at 11:48 -0600, Kirk Haines wrote: >> On 9/3/06, Zed Shaw <zedshaw at zedshaw.com> wrote: >> >> > Theorize all you want, but all I know is, use Mutex, process gets >> > killed, use Sync, process stays up. Can''t argue with the evidence. >> >> Sure I can. Your conclusion about Mutex is like the conclusion once >> drawn about the sun. It comes up in the east and goes down in the >> west, so the evidence clearly shows that the sun rotates around the >> earth, right? >> >> There is nothing wrong with Mutex. It''s an incredibly simple piece of >> code and can quite clearly be demonstrated not to leak. >> >> I''m not arguing with the fact that for some users simply swapping Sync >> in place of Mutex appears to clear a problem. I''m just arguing with >> your conclusion that this is because Mutex is broken or because Ruby >> is leaking memory when it is used. > > I like you Kirk, so don''t take it personally, it''s just an incredibly > sore spot with me since I''ve been complaining about this for ages and > everyone keeps telling me I''m crazy despite what I demonstrate. > > But, explain this: > > http://pastie.caboo.se/10194 > > > vs. > > http://pastie.caboo.se/10317 > > First one leaks, second one doesn''t (with graphs even). What''s worse is > the inverse is true on win32. These scripts have no Mongrel code, no > Rails code, they''re just short Ruby scripts.I''m really not trying to be dense here, but why are you reading a horizontal line as a leak? Especially a horizontal line that is not very far above the average (''estimated'' by squinting and guessing) of the second graph.... Steve
Uh oh! I''m sort of guilty of both #1 and #2! I''m not having any performance problems, but... I''ve been using the file store for sessions -- how much faster is using the database or memcached? I always thought files were quicker than the db (especially since each session gets its own file). I''ve been sticking the member object in a session when they login, and only updating it if they change their info. I was using the same assumption that files were quicker than the db. Joe --- 1) DON''T USE PSTORE AS A SESSION STORE! All of the people who had Mongrel processes going crazy, blocking, locking, or just generally doing bad things had a pstore as their session storage option. What happens is the pstore isn''t that great when multiple processes access it, and if one Mongrel has problems pulling an object from the pstore then it''ll explode. Use the file store when you develop, and use the database or memcached store in production. You should also be looking for other ways processes are sharing resources when they lock up or do weird things. Try running with just one process, and if you don''t have any problems then it''s a resource locking problem (most likely). 2) DON''T STORE COMPLEX OBJECTS IN THE SESSION! This especially goes for you Java people who think the session store is a temporary database. The session really only works for simple types like integers, strings, etc. You *must* follow the mantra of "Share Nothing" and either store everything in the database or use form fields and GET parameters to make it stateless. As I''ve said repeatedly, "If rails-core don''t do it, you don''t do it." Rails-core does not do this. __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com
On Sat, 2006-09-09 at 10:58 -0700, Joe Ruby wrote:> Uh oh! I''m sort of guilty of both #1 and #2! I''m not > having any performance problems, but... > > I''ve been using the file store for sessions -- how > much faster is using the database or memcached? I > always thought files were quicker than the db > (especially since each session gets its own file). > > I''ve been sticking the member object in a session when > they login, and only updating it if they change their > info. I was using the same assumption that files were > quicker than the db.Well, two points here. First, if you''re going to store this member object in the database using session, why just skip the middle man and store it in the database directly? Session is slower than database for any sort of complex objects because it has to marshal/unmarshal while the AR system can use delta storage and other tricks (and even memcache caching). Second, have you tested this hypothesis? Write a simple benchmarking rails action that stores/retrieves a bunch of random member objects from the database and then from your chosen session store. I found that storing small stuff like strings, numbers, etc. is faster, but that any complex types are nasty slow. So, test it first, use the database or memcache if session storage is faster (for stability), and use the database by default in general. -- Zed A. Shaw http://www.zedshaw.com/ http://mongrel.rubyforge.org/ http://www.lingr.com/room/3yXhqKbfPy8 -- Come get help.