Debugging memory leaks in Ruby
samsaffron.com
samsaffron.com
Edit: alright, I got downvoted for speaking a fact. Don't get me wrong, OP's article is great, but not everyone has control over the underlying code, nor has enough time to tinker into runtime nuances.
To confess I have maintained >100K LoC Python/Ruby projects, yet the respawn way is the most effective and easiest mitigation method available and I think it's likely to continue to be in a very long time.
"Sadly, most Ruby devs out there simply employ monit , inspeqtor or unicorn worker killers. This allows you to move along and do more important work, tidily sweeping the problem snugly under the carpet."
The author describes a mindset to solve the underlying problem. Endemic to any language.
Rasmus Lerdorf
More endemic in some languages than others.
http://en.wikiquote.org/wiki/Rasmus_Lerdorf
I mean, I'd be first person to tell you that I am a scripter at heart, but I would never, ever say "I don't care about this [computer science] crap at all." I feel like my job is to defer to the many programmers that are smarter than I am. Including the parser and compiler and linker etc
PHP execution model satisfies 2 crowds : hosting service providers that can provide cheap hosting to the second group of people, hobbyists that just want to install wordpress or write a "dynamic" page.
The later will never care about OOP,TDD,FP,Agile, and stuff like that. In PHP you begin with writing HTML then you put the PHP code. not the other way around,no matter how hard "advanced users" try to deny that fact, PHP scripts begin with a TAG,it is,first and foremost, a templating language that generates HTML files.
The sad thing is that it could have been done a better way. But serious language designers were too pedantic and arrogant to write simple solutions. Rasmus lazyness paid off ...
And untold tens of thousands of companies using PHP to drive their corporate internet presence.
I kinda agree with that sentiment. There's a lot of unnecessary stuff going on in CS. We had extreme OOP and I fear extreme FP will spread into the mainstream. The mission of programming language designers should be to help programmers do their jobs better, not design something elegant/interesting/powerful/expressive/[buzzword]. Those things are all good, but only in the service of programs with fewer bugs and shorter time-to-market.
That may be true for programming language designers, but I'm afraid you misunderstand what CS is all about. Hint: it's not about time-to-market. The job of CS is to explore the theory -- precisely how to do something in interesting/elegant/expressive ways. Its job is to explore the theoretical and practical underpinnings of computing; to provide proofs; to explore the abstract and formal systems behind software. CS is not necessarily directly applicable to enterprise software (though of course CS research does have practical applications; and of course there is overlap between theoretical and practical computing).
A lot of cognitive dissonance comes from people who look at CS thinking it's what they need in order to write software.
PL is not a buzzword-oriented culture. No (serious?) language designer creates a language with the intent of making it harder for programmers to do their jobs. (Brainfuck and other Turing traps excluded.) That said, being "helpful" can be interpreted in many different ways. And of course, every PL designer does interpret it differently!
OOP took off because it was a revolutionary way of structuring your code so it could be easily used, reused, and maintained. The point was to help teams be more efficient!
Functional Programming is so worthwhile first off due to immutable types. This allows highly parallelizable code. You don't have to worry about race conditions because your objects are read-only! The emphasis on types also allows better ability to prove correctness of a program before run-time. Finally, all FP languages (that I can think of) are highly expressive. This means that you can write the same program in (OCaml, Haskell, CL, Clojure) in a shorter amount of time than you could in Java/C#/Obj-C.
If you still think there is "a lot of unnecessary stuff going on in CS", I'd really like to hear what you think is necessary and we'll go from there. I already discussed your "fewer bugs and shorter time-to-market" points.
/rant
I'm not sure where you're going with that. I have stared at enough medium- to large-sized codebases to realize that an excellent way to "fewer bugs" is to protect programmers against themselves and restrict their proven ability to shoot themselves in the foot (especially in the absence of code review and/or competent technical leads). Shorter time-to-market is actually a different property. PHP or Rails got popular because they make it easy to crank out a web application in a relatively small amount of code. However, this often doesn't translate into "fewer bugs" when the codebase gets big.
I don't know what "extreme FP" mean, but there is a night and day difference working with referential transparency and immutable data structures in terms of cognitive load and ability to change parts of the system with confidence (for the record, I'm also mystified about "extreme OOP").
PHP is (admittedly slowly) moving in a positive direction because of community effort, Rasmus' opinion shouldn't terrify anyone since he's just one vote of many.
It took a decade for these web programming communities to introduce and/or build on ideas from 1958. Long before the web.
PHP is better, however Rasmus' philosophy (while ok at the time) permeates PHP's design and it hurts. It hurts a lot.
Perl was far more widespread early on (96-99) than PHP was, but it was quite painful to deal with compared to PHP. PHP made web stuff dead simple, and that's why it 'won'. CF and VBS never really stood a chance because of the extra costs involved. iHTML, HTML/OS and others were all vying for a foot in the door at this stage, but all were second-run players charging money for something that 99% of hosts were never going to pay for, and therefore devs wouldn't get exposed to those tools.
"For all the folks getting excited about my quotes. Here is another - Yes, I am a terrible coder, but I am probably still better than you :)"
Good he threw a 'probably' in there and his attitude towards memory leaks is one that is quite common in people with a 'scripting' background.
If you come from telecommunications or device drivers then you're not going to get away with that.
For anyone who's job description involves writing software and owning it's performance and reliability, process supervisors are a crutch. A crutch to be used only until the memory leak is found and a patch submitted to the relevant project.
A former colleague used to refer to the concept of software entropy. Like physical entropy, it tends to increase. It's both natural and inevitable. But as engineers we sometimes, for brief windows of time, have the ability to impose order on chaos. To locally decrease entropy.
I've seen the end result of relying on process supervisors to work around frequent crashes and memory leaks. The result is that you end up with ruby processes with multigigabyte heaps, resulting in a stack that can only run a few dozen requests/s even on the beefiest of hardware.
To be clear, I'm not saying don't ever use process supervisors. It's just that if they are saving your bacon multiple times a day something's wrong.
I'm also not claiming that inefficient software will cause your company to fail. It's perfectly possible that your buffaloak architecture will keep running until your company dies of natural causes, but I believe that we should have enough professional pride to fight entropy, even if we're the only ones who know what we did.
I don't know how to get the same kind of information on Ruby, Python or node.js but I'm pretty sure it might involve some gdb and debug symbols. No idea.
This really is just pedantry though, because the net effect is "the memory usage chart keeps going up and to the right" in both cases. "Memory leak" is a fine enough term for what's happening in this case.
The Full Article is talking about handing over data with references to live objects to some library that doesn't let go of those references, it seems. That is a space leak and can and will happen anywhere in any language regardless of whether you're using a perfect GC or not.
So the difference is this:
Ruby has a memory leak -> not my fault, I'll just stop using the offending method that leaks memory, thanks article!
Someone caused ruby to space leak -> duh, it's your fault, no need to write an article about it, you should be letting your references be GC'ed if you don't need them anymore, learn that memory is a scarce resource, etc.
Totally different problems. I was very confused reading the comments here because people are afraid of being called a pedant. Folks, our trade comes with a jargon. If you don't learn it you won't know what you don't know.
Saying simply "unneeded memory is not being reclaimed" is not constructive. Why is it not being reclaimed? Because the reason matters to programmers, we invented different names for those occurrences.
Yes it is. It's a description of a problem your monitoring tool has reported that needs investigation.
> Why is it not being reclaimed?
That's the first step of the investigation of the memory leak.
It's OK if you don't understand the difference yet - you'll get it eventually - but there is a big difference.
Oh I understand the difference. But losing track of memory and accidentally keeping memory in play are both called memory leaks. I would still call it a memory leak if it's due to cyclic references or stale entries in a hash table or other container.
Ah. I thought I was going crazy. Memory leaks in a managed language (i.e. one with a GC) are solely the fault of the GC implementer and cannot be fixed by the language user.
What is being talked about here is space leak.