Sign in to follow this  

Tips for ensuring quality in complex code

This topic is 2113 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've gotten to a point in Tangent where debugging is a pain. Worse than a pain. Debugging parser errors is a pain. Debugging 'something in the code generation is not correct' is... it's hellish. I can't even run the debugger on the code at this point since the debugger takes orders of magnitude more time than the optimised build (7m42s vs ~1s for the current issue).

I've gone through and done many of the best practices I am aware of where possible.
- There are decent error messages where errors occur.
- I've made the code pessimistic towards errors (even if we might continue through an error, just die).
- I've automated unit tests.
- I've focused on having something that works, and then incrementally adding functionality, verifying regression during each step.
- I've kept things relatively isolated so that changes are similarly isolated.
- I've got debugging symbols in the code generation so that I can debug through that as needed.

...and a number of others that I can't think of since I take them for granted...

I understand that the nature of the problem will cause the work to be difficult, but I suspect that I'll need to learn/develop new techniques since most of the ones I have for different sorts of programs are unusable. Advice?

I'm the only one working on the project, and it's in C# with MSVS if that matters.

Share this post


Link to post
Share on other sites
Debug being a factor of ~500 times slower seems to be your main problem there. Have you tried profiling it to find out why it's so slow?

Here's a few ideas for improving debug performance:

- Memory allocations are a whole lot slower if you start the program with the debugger attached, because that makes Windows enable the debug heap. Try starting it normally and attaching afterwards.
- Turn off the "basic runtime checks" in the project settings. They kill the performance of small functions for little benefit. Edit: I think this only applies to C++ and not C#.
- Turn optimizations on / off with more granularity than the whole solution. Do it per file or function if need be.

Share this post


Link to post
Share on other sites
[quote name='Adam_42' timestamp='1330017536' post='4915906']
Have you tried profiling it to find out why it's so slow?
[/quote]

Eh, no. The 'don't profile debug builds' guideline prevented me from thinking through that. The majority of the runtime is likely in a big nasty recursive generator that does a number of small allocations. I'll look into the other options, though stepping through the thing isn't exactly the nicest thing in the world either.

[quote name='SiCrane' timestamp='1330019133' post='4915914']
One thing I didn't see on your list was using static analysis tools.
[/quote]

Indeed. What sort of things have you used/do you recommend? I'm not using anything at the moment. We use FxCop here at work and it does a good job at enforcing consistency, but maybe not so much at providing product quality as opposed to nice source code. I'm not sure that would fall into this category.

Share this post


Link to post
Share on other sites
Well, there are static code analysis tools for C# that go beyond just style consistency. I know ReSharper can be used to detect common performance problems like unused variables, redundant casts and that sort of thing. NDepend can also be used to track things like cyclomatic complexity of methods and dependency cycles. Neither are free, however. There's also Gendarme, which is free, and contains static code checks for correctness like self assignment or integer divisions cast to floating point types.

Share this post


Link to post
Share on other sites
Make your code less complex.


I'm not just trying to be a smartass here, either; I'm serious. One of the killer traits of most painful code bases is that they tend to be very complicated beasts. If you can reduce that complexity in any way, debugging and optimizing both become much easier.

For instance, if you have a hand-written parser, try replacing it with a table-driven one based on a known-good generation tool. Write code in terms of generic operations instead of inheritance and virtual dispatch. When in doubt, change implementation techniques or even languages if you think you can reduce the amount of code that is involved.

The Epoch Release 12 candidate code is smaller, faster, and much easier to understand than R11 ever was. It's a huge pain to recompile the parser because it's a complicated piece of code, and templated code generation is very slow and memory-intensive at that level - so it remains one of the few areas I don't touch any more often than absolutely necessary.

Code generation, though, has become almost trivial, since it's basically just a traversal of the semantically-decorated IR tree and a lot of simple data transforms. Even though I'm working in C++ and don't have real language features like pattern matching/decomposition, it's still pretty compact and clean code. Semantic analysis itself is a lot simpler, since I'm now working in terms of a genuine AST instead of a mongrel demon-spawn conglomeration of weirdness.


I guess what I'm getting at is, if at all possible, find ways to rearchitect your code so that it is simpler. This almost always means it will get more powerful and faster at the same time, assuming you're generalizing correctly.

Share this post


Link to post
Share on other sites
Agree with ApochPiQ 100%. Sacrifice everything, including all the code you have, if you think you can implement the same features with less code given the benefit of experience and hindsight.

If you're at the point of asking how to simplify, picture how you'd start from scratch.

Share this post


Link to post
Share on other sites
[quote name='return0' timestamp='1330042107' post='4916029']
If you're at the point of asking how to simplify, picture how you'd start from scratch.
[/quote]

No it's great advice, my 'don't rewrite, refactor' guideline prevented me from thinking much about that; especially for something I've already mostly re-written a half dozen times. I need to stop that behavior, but there is some opportunity to be had. Better to take a few steps back then a few longer steps forward than sitting here with an idle project like I've had I suppose.

Good advice all around; keep it coming.

Share this post


Link to post
Share on other sites
[quote name='Telastyn' timestamp='1330013452' post='4915889']
I've gotten to a point in Tangent where debugging is a pain. Worse than a pain. Debugging parser errors is a pain. Debugging 'something in the code generation is not correct' is... it's hellish. I can't even run the debugger on the code at this point since the debugger takes orders of magnitude more time than the optimised build (7m42s vs ~1s for the current issue).
[/quote]

Have you considered writing your own debugger for tangent?

Share this post


Link to post
Share on other sites
If it is possible, can you pregenerate this data you need? Perhaps a way to provide a file that knows how many allocations to make, and simply reading in the data? Even if you don't plan to use it in the release, I find that from time to time, it is of great use to remove from the equation parts of the application that are not being tested. For instance, if I were to be generating an image and then displaying it and it fails to display, I would pregenerate the image using safe methods, and load the image just before displaying in the debugger. The time saved in not having to regenerate the image would enable much faster debugging, and remove one more cause for the bug.

Share this post


Link to post
Share on other sites
If you are certain of the stability of certain routines, #pragma optimize and #pragma runtime_checks will do wonders for speeding up functions that become extremely slow in debug mode.

[EDIT]
I read the topic at work where I could not reply and then replied many hours later at home. I forgot it was C#, and my reply may not be relevant.
[/EDIT]

L. Spiro

Share this post


Link to post
Share on other sites
[quote name='RobTheBloke' timestamp='1330538277' post='4917858']
[quote name='Telastyn' timestamp='1330013452' post='4915889']
I've gotten to a point in Tangent where debugging is a pain. Worse than a pain. Debugging parser errors is a pain. Debugging 'something in the code generation is not correct' is... it's hellish. I can't even run the debugger on the code at this point since the debugger takes orders of magnitude more time than the optimised build (7m42s vs ~1s for the current issue).
[/quote]

Have you considered writing your own debugger for tangent?
[/quote]

I've not. Since it compiles down into CIL, visual studio actually does a good job of debugging compiled Tangent code with minimal effort on my part.

The issue in the original post is debugging through the C# the compiler is written in. (not sure if that was clear)

Share this post


Link to post
Share on other sites
[quote name='SiCrane' timestamp='1330019133' post='4915914']
One thing I didn't see on your list was using static analysis tools.
[/quote]
Out of interest, do you have any recommendations for the cheapskate? :)

Share this post


Link to post
Share on other sites
Well I already mentioned Gendarme, which is free. It's not perfect, but it at least warns you about some basic things you might otherwise forget. FxCop and StyleCop are free, but really only good for making sure your code is consistent with existing conventions. Useful for me because .NET naming conventions are still something I haven't gotten instinctively down yet. YMMV.

Share this post


Link to post
Share on other sites

This topic is 2113 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this