TheSwamp

Code Red => .NET => Topic started by: mcarson on January 14, 2009, 04:02:33 PM

Title: Refactoring
Post by: mcarson on January 14, 2009, 04:02:33 PM
Not been coding for long, but already I have been asking a few questions:

My assembly autoloaded into AutoCAD 2008 presently is about 700KB in size. There is quite a lot going on in
the assembly and I would like some opinions on:
Given the points above, should I refactor into separate assemblies or is it acceptable to create one HUGE dll
that loads with AutoCAD.

Any opinions would be appreiciated.

Title: Re: Refactoring
Post by: sinc on January 14, 2009, 04:13:45 PM
These questions are application-specific, and depend highly upon the code you have written.  There is no "one answer fits all" to those questions.
Title: Re: Refactoring
Post by: sinc on January 14, 2009, 04:14:56 PM
...by which, I mean that a 30MB assembly might cause no noticeable impact to Autocad performance, but a 0.05MB assembly could drop it to a crawl, depending on what the code does.
Title: Re: Refactoring
Post by: mcarson on January 14, 2009, 04:43:17 PM
...by which, I mean that a 30MB assembly might cause no noticeable impact to Autocad performance, but a 0.05MB assembly could drop it to a crawl, depending on what the code does.

Thanks, I understand that this is not entirely specific.

Say I have a Layer Control program that helps AutoCAD users insert new layers, and follow company CAD standards. This program has some good code for the GUI that is just good plain old .NET. The AutoCAD specific functions include CreateLayer, AddPlotStyleToLayer, AddPlotStyle to layout etc.
Should this assembly be split into two assemblies, one that contains AutoCAD specific code (public modules etc) with another assembly referencing this.
Title: Re: Refactoring
Post by: sinc on January 14, 2009, 06:20:32 PM
If you are only worried about performance in Autocad, then I think you are overthinking this.

The primary reason for creating separate assemblies is to help your development.  If you have a bunch of core functionality that is used by multiple applications, then you can put that common functionality into an Assembly, and then link to that Assembly from both of your applications.  This keeps you from needing to maintain the same code in multiple places.

Splitting code into multiple demand-loaded assemblies makes sense for certain situations.  But once a DLL is loaded into Autocad, it stays there until Autocad is shut down.  So if all your code must be loaded in order for it to run, then you don't really gain anything by splitting it into multiple demand-loaded modules.  It would only make sense if one of your assemblies contains code that is rarely run, and does not need to be loaded most of the time, and you don't want to allocate those resources unless they are needed.  If you are talking about a total of 1MB of code, then chances are you will not gain anything.  After all, mouse drivers these days are far larger than that.
Title: Re: Refactoring
Post by: JohnF on January 14, 2009, 11:16:58 PM
Well put sinc
Title: Re: Refactoring
Post by: TonyT on January 15, 2009, 12:18:03 AM
Hmmmm.... you say you've not been coding long, yet you've got an
assembly that's 700KB in size.

What, might I ask, do you have in the assembly?

Not been coding for long, but already I have been asking a few questions:

My assembly autoloaded into AutoCAD 2008 presently is about 700KB in size. There is quite a lot going on in
the assembly and I would like some opinions on:
  • Does the size of the assembly really matter to AutoCAD? Should the assembly hit 2MB, would this create
    some sort of performance issue on already slow (user opinion) computers?
  • For maintenance and upgrading it is generally recommended to refactor code not only in separate
    classes/modules, but also in separate assemblies. With AutoCAD, these can be set to load on demand.
Given the points above, should I refactor into separate assemblies or is it acceptable to create one HUGE dll
that loads with AutoCAD.

Any opinions would be appreiciated.


Title: Re: Refactoring
Post by: TonyT on January 15, 2009, 12:28:11 AM
If you are only worried about performance in Autocad, then I think you are overthinking this.

The primary reason for creating separate assemblies is to help your development. 


Not sure I can agree with that.

Assemblies are loaded on demand, if and when they're needed.

For example, the assembly that provides the managed wrapper for
images (RasterImage) will never be loaded if you do not create a
managed wrapper for a raster image.

The main advantage to multiple assemblies is that they're only
loaded if and when they're actually needed, and never loaded
if they're never needed.

Seperating assemblies into functional units, where the code in
each may not be needed depending on what a user does, can
be of great benefit in terms of performance.

Title: Re: Refactoring
Post by: mcarson on January 15, 2009, 03:26:31 AM
Hmmmm.... you say you've not been coding long, yet you've got an
assembly that's 700KB in size.

What, might I ask, do you have in the assembly?

Quite a lot.
For starters, I designed a Layer Control System to assist users follow company CAD standards. This compiled (if my records are correct) at 146KB. I moved from this to adding various methods to plot a PDF, DWF and to assist with QA issuing of drawings.
While this was going on, all the users (I now manage 253 users) were dropping hints and suggestions about rewriting lisp is .NET. Off that went. So after coding a lot of generic methods, inheriting some AutoCAD class entities, the assembly had grown to around 700KB.

My next task is to create some sort of Project Control system that links AutoCAD and what the user is creating to a MSSQL2008 database across 15 sites. Given that the current code is 700kb, how long might it be until I reach 1MB, 2MB ?!

If you are only worried about performance in Autocad, then I think you are overthinking this.

The primary reason for creating separate assemblies is to help your development. 


I don't believe that I am overthinking the performance issue. For example, the CAD users I work for are multi-disciplinary; Architectural, Civil, Structural, Geotechnical etc. Aithough there is crossover between the disciplines, some methods will not be used by all disciplines so are not required to be loaded. This should help with performance as more methods are added.


The main advantage to multiple assemblies is that they're only
loaded if and when they're actually needed, and never loaded
if they're never needed.


The separating of assemblies does help the development process, by splitting the assemblies by discipline or by AutoCAD .NET, MSSQL and others. Update only the changed assembly to all users.
Back to my original question. I have attempted refactoring and ended up endlessly moving namespaces, classes, methods depending on:
I am asking for advice on sitations I might face. I don't want to end up next year with a 10MB assembly in AutoCAD, I would like to start looking at any refactoring now.
Title: Re: Refactoring
Post by: Glenn R on January 15, 2009, 07:01:57 AM
Based on that, I would definately split it up a bit more - put the lisp stuff into a separate one for example if you are able to. Also, make sure to add the assembly level ExtensionApplication and CommandClass attributes where appropriate to improve load time.

From the ARX docs:

Code: [Select]
Using Managed Application Initialization and Load-Time Optimization
 
 
Managed applications can choose to perform initialization or termination tasks by implementing the optional Autodesk.AutoCAD.Runtime.IExtensionApplication interface. This interface provides Initialize() and Terminate() methods. Because managed applications cannot be unloaded manually, Terminate() implementations are called only when AutoCAD exits.

If your application defines a large number of types, you can optimize its load-time performance by implementing IExtensionApplication and using two optional custom attributes. These attributes—ExtensionApplication and CommandClass—help AutoCAD find the application's initialization routine and command handlers.

Any managed application can use these attributes. However, their optimizing effects are measurable only in larger applications.

Cheers,
Glenn.
Title: Re: Refactoring
Post by: sinc on January 15, 2009, 09:40:41 AM
If you are only worried about performance in Autocad, then I think you are overthinking this.

The primary reason for creating separate assemblies is to help your development. 


Not sure I can agree with that.

Assemblies are loaded on demand, if and when they're needed.

For example, the assembly that provides the managed wrapper for
images (RasterImage) will never be loaded if you do not create a
managed wrapper for a raster image.

The main advantage to multiple assemblies is that they're only
loaded if and when they're actually needed, and never loaded
if they're never needed.

Seperating assemblies into functional units, where the code in
each may not be needed depending on what a user does, can
be of great benefit in terms of performance.



I don't really see how you said anything different than I did.
Title: Re: Refactoring
Post by: It's Alive! on January 15, 2009, 10:46:30 AM
IMHO, Load, initialize, cache everything you can, Loading assemblies and JIT times are painfully slow.

700k Wow  8-)
Title: Re: Refactoring
Post by: TonyT on January 15, 2009, 12:34:24 PM

I don't really see how you said anything different than I did.


You said:

Quote

The primary reason for creating separate assemblies is to help your development. 


IMO, that isn't the primary reason.

The primary reason is to avoid loading code that will either never
be used, or be used occasionally.

There's no question that structuring an app into multiple assemblies
helps in development (Visual Studio can really bog down with large
assemblies), but I can't concurr with that being the 'primary' reason
for doing it.

Title: Re: Refactoring
Post by: TonyT on January 15, 2009, 12:35:21 PM

The separating of assemblies does help the development process, by splitting the assemblies by discipline or by AutoCAD .NET, MSSQL and others. Update only the changed assembly to all users.


Please re-read what I said. While it may simplify deployment,
that isn't the main advantage or purpose.

The main advantage is that you don't load code that will never
be used, or only be used occasionally.

Quote

Back to my original question. I have attempted refactoring and ended up
endlessly moving namespaces, classes, methods depending on:
  • Discipline
  • AutoCAD Entity/Object changing adding
  • Database code

I am asking for advice on sitations I might face. I don't want to
end up next year with a 10MB assembly in AutoCAD, I would like
to start looking at any refactoring now.


Well, I would never build a single assembly that serves multiple
disciplines, especially if some of them do not use any of the
code that others use, which seems to be the case here.

Generally, I structure my assemblies in the same fashion that
I structure my code. For example, I have many classes that
I use in most of my applications. They go in an assembly that
I can then reference in each application that needs the code
(which in some cases, is almost every app I write).

Depending on the app and how extensive it is, I may build a
single assembly for the app (and reference common/reusable
library code from them), or I may build multiple assemblies for
the app, where each contains certain functionality.

For example, I have apps that make use of UI controls that
I've written, and I have other apps that have hardly no UI
at all. So, I put the UI controls in their own assembly, and
reference them from any assemby that needs them.  In some
cases, there can be 4 or 5 assemblies with some that are
dependent on others, and dependencies that may go 2 or 3
levels down.

It ultimately depends on how much reusable code you have,
and from your description, it seems that you may not have
very much, which would also explain why you have a 0.7 MB
assembly.

Title: Re: Refactoring
Post by: Glenn R on January 15, 2009, 03:59:57 PM
'Lazy loading', a phrase which I think Tony touched on in another recent thread here if memory serves, is definately worth thinking about, especially early on in the development cycle, if you expect your application to grow in size and complexity. You can apply this technique to assemblies, state data etc.

An example:

Several years ago I designed a company wide app, that was project specific and was for the compliance with company standards. In the companies I've worked for, there could be upwards of 100 projects on the go at any one time. This was controlled through an XML configuration file, which held, amongst other things, the PROJECTNAME setting for the project/job, the reference paths for the PROJECTNAME setting, template (DWT) and drawing standards file (DWS) to be used, blah blah.

For all the projects defined, I definately did NOT want to load into memory, whenever AutoCAD was spun up, each and every DWT/DWS file that I needed. So, I implemented a 'lazy loading' scheme, whereby when a drawing was opened, it was scanned for the PROJECTNAME system variable, which was then checked against my generic collection of class objects that were already loaded. If it was there, I could do my mojo, if not, load in the DWT/DWS and whatever else I needed, then do mojo. The theory here was that a draughtsman woud rarely exceed working on a dozen or more projects in one AutoCAD session, so I didn't need to load in, potentially hundreds of, albeit small, DWT/DWS files or anything else I had persisted to disk, for a given project/job.

Enough of my ranting.
Title: Re: Refactoring
Post by: mcarson on January 15, 2009, 04:14:34 PM
Thanks TonyT, exactly the kind of response I am looking for - an example of what has been done in the past.
Sorry sinc, I was in agreement with much of what you said. Just attempting to convey the issues.
Daniel - I have noticed that loading assemblies on demand can be annoyingly slow

Stuck between a rock and a hard place!

GlennR - thanks for the pointer. I am implementing the same concept with linking the drawings in AutoCAD with Projects in a MSSQL database. 'Lazy loading': phrase for future reference!

I'll have another look at the code I have (I do have a large number of reusable methods, perhaps too many overloads!) and look at separating the AutoCAD Entity code, i.e. the code that accesses Autodesk.AutoCAD.DatabaseServices into a different assembly than the Sql database code.
After this it may be a good idea to create additional assemblies for each discipline, which reference the AutoCAD Entity code assembly.

So 5 assemblies so far.

LayerControl and ProjectControl, I suppose could go in one assembly since this code is for company standards helpers.

6 assemblies. I'll autoload them all until I research performance issues that do occur.

Thanks guys, I needed a push in the right direction.
Title: Re: Refactoring
Post by: kdub_nz on January 15, 2009, 05:08:34 PM
< ...> So 5 assemblies so far.

LayerControl and ProjectControl, I suppose could go in one assembly since this code is for company standards helpers.

6 assemblies. I'll autoload them all until I research performance issues that do occur.

Do you mean Autoload  (Demand load) or load at startup.

I'm loath to load much at startup that will slow down things like scripted material extraction, batch plotting, or simple viewing of a drawing (read only or otherwise)
Title: Re: Refactoring
Post by: TonyT on January 15, 2009, 11:17:46 PM

I have noticed that loading assemblies on demand can be annoyingly slow


All assemblies are loaded on demand. They are not loaded any other way,
unless you explicitly load them using Assembly.Load()/LoadFrom().

Assemblies referenced by a loaded assembly will not necessarily be loaded
until the code running in the referencing assembly references something in
the referenced assembly.

So, your comment leaves me scratching my head, because allowing
the framework to do what it is supposed to do, should not be annoyingly
slow, if you consider how much longer you would have to wait, if you
were to explicitly load every assembly that would otherwise be loaded
on demand.

The only issue with demand loading, is that it can occur at any time,
including during user interaction, which can result in a noticable delay
on a slower system (an example of that is AutoCAD 2009's WPF tooltips).

Title: Re: Refactoring
Post by: Kerry on January 16, 2009, 11:13:23 PM

not completely unrelated ..

http://blogs.msdn.com/ericlippert/archive/2009/01/16/future-proofing-a-design.aspx

Fabulous Adventures In Coding
Eric Lippert's Blog
Future-Proofing A Design