Become a fan of Slashdot on Facebook

 



Forgot your password?
typodupeerror
×
Programming IT Technology

Fast Native Eclipse with GTK+ Looks 300

Mark Wielaard writes "The gcj team created a natively compiled build of the Eclipse IDE. The resulting binary starts up faster then with any traditional JVM since there is no virtual machine to initialize or slow byte code interpreter or just in time compiler involved. This means that gcj got a lot better since the last Slashdot story in December about gcj and Eclipse. Red Hat provides RPMs for easy installation. Footnotes has screenshots by Havoc Pennington of the Eclipse IDE with GTK+ widgets."
This discussion has been archived. No new comments can be posted.

Fast Native Eclipse with GTK+ Looks

Comments Filter:
  • by iamacat ( 583406 ) on Sunday August 03, 2003 @12:12PM (#6600220)
    From what I heard so far, gcj has problems with garbage collection and doesn't generate very good code. Did I miss any dramatic improvements recently? Also, how complete is the class library?
    • GCJ uses the same backend as GCC (C/C++). Its code should therefore be as good or as bad as for that one.

      The class library is certainly complete enough to write nice, crisp, fast and beautiful native GUIs with SWT.

      The true question is: What can you do with GCJ?

      The answer is: everything you can't do with the JDK, because the JDK starts up too slowly, because Swing suffers from obesity, and because both memory and disk footprints of the JRE are a disaster.
      • by Call Me Black Cloud ( 616282 ) on Sunday August 03, 2003 @12:41PM (#6600347)
        From your comments it's apparent you're not a Java programmer then, because you merely repeat old complaints that are no longer valid. Ok, sure, the JRE takes up a bit of space but compared to the size of hard drives today the amount is trivial. Having the JRE on disk is like installing the MS or Borland libraries (or Linux counterparts) that some applications use - once it's there other applications don't have to include the code as part of the executable.

        Swing suffers from obesity - what does that mean?

        I've been developing Java applications for years (including a stint as project lead on a weather satellite imagery analysis program) and I know firsthand how much Java has improved. Spend some time writing applications in Java, using Swing (I use Netbeans for my IDE)...you'll see how sporty applications can be. Also check out Sun's Java Games [java.net] community for some links to games that really exhibit excellent performance.
        • There are lots of things you can't do with Java. Little CLI apps like 'ls', 'cd', etc, would be painful to use if they were written in Java, because of the startup costs of the VM. It takes GCC 0.004 seconds (ie: within measurement error) to startup and give me the usage message. It takes javac 0.330 seconds to do the same.
          • There are lots of things you can't do with Java. Little CLI apps like 'ls', 'cd', etc, would be painful to use if they were written in Java, because of the startup costs of the VM. It takes GCC 0.004 seconds (ie: within measurement error) to startup and give me the usage message. It takes javac 0.330 seconds to do the same.

            two responses to that.

            1. People have no problem with little perl scripts run from the command line, but perl has exactly the same startup overheads as Java.
            2. Running commands under bash is running them in, effectively, a C language environment. The basic C language shared libraries are already loaded. If you had a Java shell already running in its own JVM it could invoke instances of Java classes at the same order of cost as a conventional shell starting an ELF executable.

            I write 95% of my work in Java. It's just as performant as anything else doing the same job. Most of my stuff (web applications) typically service small requests - very much like ls, albeit in a different environment. But the trick is, you don't start a new JVM for each invocation; you have a JVM running all the time and service the requests you receive within it. In this sense, the webapp is analogous ot a shell.

            I'm not saying Java doesn't have problems - it does have a significant problem which is Sun's attitude to 'intellectual property' and their continued restrictive licensing. But speed and efficiency are no longer problems Java has.

        • Uh, the parent post was specifically askinb about the performance and library and code generation quality of GCJ , not Java in general, so untie your panties there.
      • Ok, but this doesn't quite answer my question. Eclipse is a good example of application that itself takes up a lot of memory and disk space. The question is how well does it run under GCJ once it gets started? To be honest, JRE is not great for desktop applications, but I certainly wouldn't want GC UI lag to get any worse.
    • It runs very nicely! The native-compiled eclipse is noticably more snappy and responsive than it is on the JRE 1.4.2 on my (XP 1800) machine. It also seems quite stable - I stress-tested it for about half an hour last night and couldn't produce any bugs or crashes.
    • Eclipse contains a java compiler which you can also compile as a standalone app with with gcj (see http://sources.redhat.com/rhug). The gcj-compiled compiler is almost three times faster than the latest IBM JRE run version.
  • by millenium ( 689108 ) on Sunday August 03, 2003 @12:14PM (#6600229)
    GCJ aka "native Java" now really seems to be ready for its day under the spotlights.

    • Last I looked, aside from avoiding the JVM startup time, gcj produced code that ran more slowly than in the IBM JDK (*non-native code*).

      Five years from now, when gcj has sped up and can take advantage of the Java 1.5 typed container classes and disable bounds checking, Java may actually become usable, if still slower than C/C++ programs.
      • I could show you plenty of examples of benchmarks that run significantly faster with GCJ than on the IBM JDK. Its true that there are still some occasions where GCJ will run slower - due to bottlenecks in the runtime or missed optimizations in the compiler. But if you have a simple application that runs significantly slower with GCJ, please write to java@gcc.gnu.org and tell us about it. We can't fix performance problems we don't know about.
  • load times (Score:3, Interesting)

    by khuber ( 5664 ) on Sunday August 03, 2003 @12:17PM (#6600245)
    I still don't understand why load times are such a big deal. Do people sit there and start and exit applications continuously?

    I leave stuff like mozilla, eclipse, and xemacs running for weeks on end.

    • by aled ( 228417 )
      Yes! I love so much all those modal splash windows, in fact I'm recompiling all my apps to exit inmediately after showing them...
    • Re:load times (Score:3, Informative)

      by iabervon ( 1971 )
      It's not such a big deal for Eclipse, but it matter a whole lot for command-line programs like jar and javadoc, where the amount of time spend running the program is less than the amount of time spend starting the program; this makes correspondingly more of a difference to programs using the traditional UNIX philosophy.

      Of course, java tends toward handling this differently, where java programs invoke each other inside the same runtime, but it makes mixing java and non-java tools annoying.
    • by mccrew ( 62494 ) on Sunday August 03, 2003 @03:05PM (#6601048)
      Do people sit there and start and exit applications continuously?

      For those who start up their IDE in the morning and close it down in the evening (or at the end of the week, whatever), then long startup times are just a minor cost of doing business.

      For someone like me, however, who is ambivalent about this IDE or that IDE, and whose fingers are too hard-wired for one particular editor [vim.org] to use the brain-damaged editors foisted by most IDEs, startup time IS a big issue. When you are going in and out of tools all day long, it becomes a major annoyance to have to wait for the darned thing to start up.

      • When you are going in and out of tools all day long, it becomes a major annoyance to have to wait for the darned thing to start up.

        Yup, And there's also stuff like daemons started from inetd, tools launched from cron jobs and shell scripts and data manipulation programs - the general UNIX philosophy favors launching these kinds of things as short-lived processes.

        I know java advocates who would probably recommend that all the other code that interfaces with these things just be written in java and run as
      • by ChannelX ( 89676 ) on Sunday August 03, 2003 @11:12PM (#6603324) Homepage
        I still dont get why you need to restart Eclipse to go into another editor. Run them both at the same time. IIRC the Eclipse editor will detect the new file changes.
  • by SilentMajority ( 674573 ) on Sunday August 03, 2003 @12:19PM (#6600252) Homepage
    I found this info at http://gcc.gnu.org/java/

    "A team of hackers from Red Hat has released RPMS for a version of Eclipse, a free software IDE written in Java, that has been compiled with a modified gcj. You can find more information here. We'll be integrating the required gcj patches into cvs in the near future."

    ps

    Slashdot preview is buggy today...can't do HTML format preview and links one or more spaces get embedded in URLs (like the one below).

    ---
    My most underrated Slashdot post is http://slashdot.org/comments.pl?sid=68610&cid=6276 748

    What is yours?

  • Another FOSS IDE. (Score:4, Interesting)

    by Black Parrot ( 19622 ) on Sunday August 03, 2003 @12:22PM (#6600272)


    There is another FOSS IDE called gps [act-europe.fr]. They call the unsupported version the "academic edition", but you can download the source, and a peak at a few files shows that it's GPL'd. (Their economic model is to give it away for free and sell support for those who need it.)

    It's a cross-platform IDE, with binaries available for Linux, Solaris, and various versions of Windows, and in principle you should be able to build it on any *n*x system where you can get GTK2 to run.

    The bad news is that language support is still limited. It has full support for Ada and partial support for C and C++, which are lower priorities for the authors. It comes with instructions for setting up support for your language, but that looks like a non-trivial task.

    I've just started playing with it so I can't give a good review, but so far it has been very helpful. The features listed at their Web site are:

    • Language-sensitive editor
    • Automatic generation of body files
    • Source code reformatting
    • Intelligent source code navigation
    • Context-sensitive search and replace
    • Application builder
    • Automatic code fixing
    • Version control (CVS, ClearCase, etc.)
    • Visual file comparison
    • Graphical source-level debugger
    • Project and program entities explorer
    • Project wizard
    • Types and program entities graphs
    • Call graphs
    • File dependency graphs
    • Project dependency graphs
    You can use the built-in editor or make it pop up your favorite editor. If you use the gnuclient Emacs interface you get the same kind of language-sensitive pop-up menus you get with the built-in editor.

    Screenshots are available at the link above.

    • by 0x0d0a ( 568518 ) on Sunday August 03, 2003 @03:01PM (#6601032) Journal
      It is extremely important that *all* developers read the parent post. This IDE may have the most groundshaking features *ever*!

      Let's take a look:

      Automatic generation of body files

      Hot *damn*! It writes my code for me!

      Source code reformatting

      Then it reformats it to fit whatever standard I need!

      Automatic code fixing

      Then it *debugs* the code!

      Application builder

      Finally, it *builds* the program I'm working on!

      All this, from a piece of software that the ignorant layman might consider no more than a wrapper for an editor and a compiler.

      Truly, a groundbreaking achievement. :-)
  • Plugins? (Score:4, Interesting)

    by connsmythe96 ( 576445 ) <slashdot@adamkemp . c om> on Sunday August 03, 2003 @12:36PM (#6600331) Homepage
    The eclipse IDE is supposed to be extremely pluggable. How does natively compiling it affect that? Do you have to compile the plugins with the IDE? Or can you still just drop the .class files somewhere?
    • Re:Plugins? (Score:4, Informative)

      by Anonymous Coward on Sunday August 03, 2003 @01:06PM (#6600481)
      I believe run-time loading works. GCJ also includes a bytecode interpreter, so it will use that (it'll be slower than a normal JVM, but if you know you'll be loading it, you can compile the plugin natively, I think).

      That was the case last time I looked at GCJ about a year ago. I ended up being unable to use it because of lack of windowing toolkit support. Anyone know the status on all that?
      • Re:Plugins? (Score:5, Interesting)

        by Per Bothner ( 19354 ) <per@bothner.com> on Sunday August 03, 2003 @03:36PM (#6601214) Homepage
        That was the case last time I looked at GCJ about a year ago. I ended up being unable to use it because of lack of windowing toolkit support. Anyone know the status on all that?

        Eclipse uses its own SWT toolkit, which works well under GCJ. SWT is a combination of native code and Java, and is said to both be fast and integrate well with other window systems, as it uses native widgets when available.

        The implementation of AWT (including applets) is coming along very quickly, but it isn't complete yet.

  • by jfengel ( 409917 ) on Sunday August 03, 2003 @12:40PM (#6600342) Homepage Journal
    The intriguing idea behind JIT compilers is that the result can be optimized for your exact configuration (AMD vs Intel, particular kinds of RAM, etc.) It can even (conceptually) optimize the same program differently at different times depending on usage. At, of course, a startup penalty and runtime compilation overhead.

    I don't know how much of this potential is actually realized in JITs (it's insanely hard to do) and how much of a difference it makes in the end. How substantial would the difference between a specialized AMD vs Intel optimziation be, for example (which would presumably depend on the task)?

    I suppose the best possible world would be to have the optimization run exactly once, the first time you install a program. (Yeah, you could conceptually move the same installation to a different CPU, or add more RAM, or some such, but let's not make an already messy issue even messier.)

    I doubt such things are easy to benchmark, and the best test may well be something like this (gcj'd Eclipse), where the end result to the user is "which one feels faster?" and "which one actually runs faster?"
    • My understanding (I may be wrong) is that the way that Microsoft's "managed code" works is that the installer creates a native compile of your application on your computer right when it installs.

      I don't know how well it works but I can see the potential.

      • My understanding (I may be wrong) is that the way that Microsoft's "managed code" works is that the installer creates a native compile of your application on your computer right when it installs.

        I think .NET is just in time compiled, similar to Java.

        If what you said is true, we wouldn't be able to copy an executeable from one computer to another. It would have to be installed.

    • by Anonymous Coward
      > The intriguing idea behind JIT compilers is that the result
      > can be optimized for your exact configuration (AMD vs
      > Intel, particular kinds of RAM, etc.) It can even
      > (conceptually) optimize the same program differently at
      > different times depending on usage. At, of course, a
      > startup penalty and runtime compilation overhead.

      True, the optimization for hardware platforms are less significant than the overall optimizations.

      > I don't know how much of this potential is actually
      > rea
    • by Anonymous Coward
      The intriguing idea behind JIT compilers is that the result can be optimized for your exact configuration (AMD vs Intel, particular kinds of RAM, etc.) It can even (conceptually) optimize the same program differently at different times depending on usage. At, of course, a startup penalty and runtime compilation overhead.

      That's not nearly as interesting as using runtime feedback to further optimize code. Static optimizing compilers need to make guesses about things, like how often loops are expected to r

    • GCJ, as far as I know, is not a JIT compiler, but a AOT compiler (Ahead of Time) - basically a normal compiler. So there is no greater opporunity to optimise per platform at runtime here. JITs are found tightly integrated in JVM implementations, such as Sun's HotSpot VM.

      That's what makes GCJ so interesting: it's a Java compiler that, unlike most other Java compilers, compiles directly to native code without the VM in between. Thus, you potentially lose some of the advantages that the VM can provide you
    • by Anonymous Coward
      The intriguing idea behind JIT compilers is that the result can be optimized for your exact configuration (AMD vs Intel, particular kinds of RAM, etc.) It can even (conceptually) optimize the same program differently at different times depending on usage. At, of course, a startup penalty and runtime compilation overhead.

      Oh, but there are a few fallacies associated with that.

      The first and bigggest one, a pet peeve of mine, is that people claim that they can reoptimize the application repeatedly on the fly
    • On modern processors, the performance of a program is affected greatly by the success of the branch-prediction system, which gets hints from the compiler. This means that a compiler that knows what the flow control of the program is actually like is going to generate substantially better code. Traditional compilers have some information about flow control (e.g., most loops are run a lot of times; some are run either not at all or lots of times; few are run exactly once), but JIT compilers have the benefit t
      • You can get most of the benifets of that from profile-guided optimizations. It would be unusual to see something whose flow patterns were too irregular to benifet from PGO, but were regular enough to allow the JIT to make good optimizations.
        • On modern processors, the performance of a program is affected greatly by the success of the branch-prediction system, which gets hints from the compiler.

        There's an interesting claim I have seen made: Apparently the late binding feature of object-oriented languages -- virtual methods in C++, any non-static method in Java -- works against branch prediction, effectively resetting the prediction state whenever such a call is made, because the target jump address must be resolved -- read from a memory location -- only at the time of the jump. If this claim is accurate, this means typical OO code is inherently slower to execute than non-OO code on modern processors. Of course, the problem will equally apply to any language that supports function pointers, and in particular to C programs "emulating" OO with structs and function-pointer tables.

    • IBM's AS/400 JVM does exactly this. Java byte code is compiled the first time it is run and optimized for the exact processor and OS version. The binary is managed transparently by the JVM and updated when the bytecode changes. On AS400, this is all integrated with the filesystem (i.e., you can't screw it up by touching with a funny date).

      You get all the advantages of Native compilation, and system specific JIT compilation combined - at the expense of more complexity and lots more disk space.

      As other

    • by lokedhs ( 672255 ) on Sunday August 03, 2003 @03:28PM (#6601168)
      In general, GCJ compiled code is slower than the smae code running in the JVM. The only speed advantage comes from the startup times.

      Often the JVM will out-perform GCJ with a factor of 3. Check out the numbers on this page [shudo.net].

      I fail to see why people want to run a GCJ compiled evrsion of a development tool and run at at one third of the speed of the JVM, just in order to save a few seconds of startup time.

      • I checked out the numbers, but GCJ seems to be just barely edged out by Hotspot in most cases. Considering that GCJ is free and allows you to distribute native binaries, that's pretty good.

        They don't have figures for memory usage, installation profile, etc., and I bet in those areas GCJ beats Hotspot for end-users. And you can't beat an install with no library dependencies.

  • Good for QNX (Score:3, Informative)

    by Animats ( 122034 ) on Sunday August 03, 2003 @12:51PM (#6600398) Homepage
    This will be useful for QNX, for which Java support is weak.
  • by 1nv4d3r ( 642775 ) on Sunday August 03, 2003 @12:53PM (#6600411)
    Thanks to the expected slashdotting, this is just one more eclipse I can't look directly at.
  • Eclipse takes an aspect-oriented approach to UI design. If your not in the "Debug View" then you wont be able to find the things you need to debug.

    Once of the advantages of this aspect-oriented approach is that menu items and UI elements change as your view changes. You keep the same oouter wrapper at all times, but your available choices very. I found it very confusing in the beginning, but once you get used to it it makes life a lot easier and keeps things cleaner.
  • Why JVM? (Score:3, Interesting)

    by be-fan ( 61476 ) on Sunday August 03, 2003 @03:01PM (#6601029)
    I never really understood the whole point of the JVM. Why load this big program at every application launch? JIT still has more overhead than AOT compilation, in the real world, and most importantly, the huge memory footprint of the VM wreaks havoc on your caches.

    What's the purpose of the JVM?

    Dynamicity? No. Java is a aggressively static language. Meanwhile, highly dynamic languages like Lisp, Dylan, and Scheme (among others) can be efficiently compiled to native code.

    Speed? While in theory a JIT can be faster, its not the case in practice. In the "Great Computer Language Shootout" (which isn't bad, as far as these things go) Java has an average CPU rank of 14, behind other static languages like C, C++, Ocaml, and SML, and behind dynamic languages like Scheme and CL as well! In reality, Java can only get within 90% of the speed of C for inner-loop numeric-type stuff (which lends itself to JIT optimization).

    Flexibility? Java is highly inflexible. Its almost as as inflexible as C. It requires you to manually specify pretty much everything. You even have to do manual boxing/unboxing! Java is so highly structured, it should be compilable to native code that hits 90% the speed of C, without a very smart optimizer at all.

    Safety? Given Java's lack of pointer types, it shouldn't need a JVM monitoring it to be safe. Again, there are lots of safe languages (Haskell, Clean, and the aforementioned dynamic languages) that don't require a runtime monitor.

    Actually, I don't see much of a point in Java at all. Its got statically typed, but can't use that advantage to be as fast as C++. It runs in a VM, but can't use that advantage to be as dynamic as Python. Its syntax isn't any easier to use than something like Dylan (kinda like Lisp with a Pascal syntax) or Python. It doesn't have the development environment advantages of Smalltalk. Heck, its not even a very good compromise language ---- Dylan is as easy, often faster, and more powerful, Python is much easier (and thanks to Psyco) often as fast, C++ is much more powerful, as well as much faster, etc.
    • Hey hey,

      - Dynamicity? No.

      I don't think 'Dynamicity' is a word. But hey, enlighten me?

      - Flexibility? Java is highly inflexible. Its almost as as inflexible as C.

      Nup, not even. See 'instanceof' - which, although considered hackish among OOP elites, gives volumes compared to using void pointers in C. Then there's the whole polymorphism thing, but hey - C is procedural.

      - Safety? Given Java's lack of pointer types, it shouldn't need a JVM monitoring it to be safe.

      Someone correct me if I'm wrong, but AFAIK
      • I don't think 'Dynamicity' is a word. But hey, enlighten me?
        >>>>>>>>
        It's not a word. But I'm referring to how dynamic the language is. In Java, dynamic method invocation is very limited --- just basic single argument polymorphism. Other languages have much greater dynamic capabilities: For example, in Dylan (chosen because its syntax is easier for most people to follow), I can do the following:

        let vec = make(, size: 100); // ...fill vector...
        for(i from 0 below 100)
        do-foo(vec[i]
      • Re:Why JVM? (Score:3, Informative)

        by be-fan ( 61476 )
        I hate you slashdot. Now, let's try this with the code samples in place?

        I don't think 'Dynamicity' is a word. But hey, enlighten me?
        >>>>>>>>
        It's not a word. But I'm referring to how dynamic the language is. In Java, dynamic method invocation is very limited --- just basic single argument polymorphism. Other languages have much greater dynamic capabilities: For example, in Dylan (chosen because its syntax is easier for most people to follow), I can do the following:

        let vec = make(
    • Re:Why JVM? (Score:5, Informative)

      by the eric conspiracy ( 20178 ) on Sunday August 03, 2003 @04:22PM (#6601395)
      Dynamicity? No. Java is a aggressively static language.

      Static types perhaps, but very dynamic when it comes to linking. Java has a lot of support for things like dynamic class loaders that lead to a very nice plug-in architecture, and extreme flexibility when it comes to deployment of code updates to a running application. Not to mention fun with diddling bytecodes on the fly.

    • Re:Why JVM? (Score:3, Interesting)

      by Bodrius ( 191265 )
      If you're looking for the strengths of Java, I think you should ask what was Java created for in the first place?

      If I understand the myth/history correctly, it was made to run arbitrary code from an arbitrary source in an arbitrary environment, in a safe manner.

      Sun needed something to load up additional code within a program which the original programmer didn't know anything about, get it from somewhere in the network at runtime, then run it in anything from a toaster to a cable-box to a PC to a cell-phon
      • If you're looking for the strengths of Java, I think you should ask what was Java created for in the first place?
        >>>>>>
        Not looking for the strengths, but why it requires a VM.

        Flexibility? Once more, it's not about the type-system. It's about loading arbitrary code into your application server without shutting it down, or worrying too much that the code will crash your system.
        >>>>>
        But why does it require a VM? C/C++ can do the dynamic code loading via dlopen() and kin, and L
        • If the code is source portable (something achieved by many languages) what's the big deal about one compile per platform?

          The big deal is that unless you have the source, you're restricted to those platforms that the maker happens to support. Which is usually a depressingly small number, and if you're not running Windows XYZ, can be a pretty frustrating experience.

          Permissions is usually the domain of the OS kernel, not the language runtime. How is putting the thing in a VM any more secure than putting t

  • Did any of you get a chance to try it out and compare how much memory it uses? One of the annoyances about Java when compared to C is the total memory usage. So when apps like Eclipse written in Java can be compiled and if the memory usage is lower as a result, then that would make Java more attractive. I'm guessing that even a "hello world" will suck up a lot of memory for a Java console app compiled using GCJ because of required runtime library. Just a guess. Yes, memory is cheap but some of us are s
    • by thimo ( 36102 ) on Sunday August 03, 2003 @04:21PM (#6601389) Homepage
      A quick test (using an Eclipse 2.1.1 from eclipse.org):

      Eclipse 2.1.1 with JVM
      - Second start: 13 seconds
      - Memory Eclipse: 80 MB
      - Memory JVM: 65 MB

      Eclipse 2.0.1 without JVM
      - Second start: 9 seconds
      - Memory: 96 MB

      The download page seems to indicate you're downloading an Eclipse 2.1.0 version, but the about dialog says 2.0.1. Which one is it?

      Cheers,

      Thimo (back to coding in Eclipse 2.1.1 :)
  • Get your torrent here [homelinux.org]
  • by Kynde ( 324134 ) <kynde@[ ].fi ['iki' in gap]> on Monday August 04, 2003 @04:55AM (#6604305)

    Just so you all know. A good jit/hotspot compiler can make things quite a bit faster than any static build compiler. This is because at runtime certain optimizations are possible that simply cannot be done at build. These optimizations are typically very aggressive, to that extent that later on in execution it may turn out so that those snippets have to be thrown away and recompiled. And thus they usually target only the hotspots, i.e. portions of code that are being executed inside tight loops, which is usually where compile time savings occur anyway. The speed of the rest of the code is pretty much governed by the programmer anyway along with his choice of algorithms and data structures.

    A good example of such snippets would be the inlining of a virtual method, turning a virtual method recursion into a loop along with some unrolling, inlining function pointer call (which is basically the same as virtual method call).

    Mind you, ofcourse a hotspot compiler could also be implemented to a C/C++ runtime environments, but I haven't heard of anyone actually taking that path.

    (for the record, I'm a C programmer and rarerly write much with java)

Work is the crab grass in the lawn of life. -- Schulz

Working...