Jump to content
Mike Torrettinni

Why is public class method marked as used, while it's not actually used?

Recommended Posts

I was refactoring some code and removed all calls to a method of a class, but it was still showing 'blue dots' in editor indicating it was still used. The 'blue dots' were removed when I moved the method from public to private section.

 

Here is example and screenshot of 'blue dots' showing as if procedure B is used, but I don't actually call it, I just create a class:

 

image.png.a522a00b2a5eac28c4120cf032471648.png

 

and if I move procedure B to private, the nothing is used:

 

image.png.09d4b4255ae83b1f1781d204caca7af2.png

 

And the code:

 

type
  TDummy = class
  private
    procedure A;
    procedure B;
  end;

procedure TDummy.A;
begin
  Sleep(0);
end;

procedure TDummy.B;
begin
  Sleep(0);
end;

procedure TForm2.FormCreate(Sender: TObject);
var vDummy: TDummy;
begin
  vDummy := TDummy.Create;
end;

 

 

I assume that is by design.

Does somebody know why is procedure B marked as used? I couldn't find resource on this.

 

 

 

Edited by Mike Torrettinni
typo

Share this post


Link to post

While a private method can be accessed only from inside the class and if not used doesn't require a code to be generated (there will be no blue dot). A protected/public/published methods can be used from outside the class and the code will be generated. You can write from another unit:
 

var vDummy: TDummy

begin
  vDummy.B;
end;

 

Share this post


Link to post
11 minutes ago, Lajos Juhász said:

While a private method can be accessed only from inside the class and if not used doesn't require a code to be generated (there will be no blue dot). A protected/public/published methods can be used from outside the class and the code will be generated. You can write from another unit:
 


var vDummy: TDummy

begin
  vDummy.B;
end;

 

Thank you, I do understand that you can call B from outside of the class. Why does it require to generate public method, even if is not actually being used, anywhere? It doesn't do the same with other methods not inside the class like global methods.

Share this post


Link to post
28 minutes ago, David Heffernan said:

Presumably it's because of your RTTI settings, which by default allow public methods to be called from RTTI, but not private.

Exactly. This is one of the reasons why enabling extended RTTI did increase the exe size by a big margin, and why I usually disable it unless I know I will actually need it.

  • Like 2
  • Thanks 1

Share this post


Link to post
1 hour ago, David Heffernan said:

Presumably it's because of your RTTI settings, which by default allow public methods to be called from RTTI, but not private.

Aha, OK, it makes sense.

 

32 minutes ago, Arnaud Bouchez said:

Exactly. This is one of the reasons why enabling extended RTTI did increase the exe size by a big margin, and why I usually disable it unless I know I will actually need it.

I thought it was just generics and unicode that doubled/tripled... the size of executable from Delphi 2009+.

 

Share this post


Link to post

I don't think RTTI doubles or triples the size of your executables. I also think that people worry overly about the size of the executables. Certainly worry about this on mobile platforms, but generally on desktop platforms you should be less concerned of the increases due to RTTI. 

Share this post


Link to post
39 minutes ago, Stefan Glienke said:

I don't see a class method in that code

Isn't a method that is defined in a class, a class method? Should it be class' method?

Edited by Mike Torrettinni

Share this post


Link to post

A method is a routine (procedure/function) that is associated with an object. A class method would be a routine (procedure/function) that is associated with a class.

  • Thanks 1

Share this post


Link to post

OK, I tried defined as class method , I don't notice any difference:

 

image.png.438667323ae97c085a581a31f5c1753c.png

 

As suggested, if I disable RTTI, then the method is really not used (not generated) if not used:

 

image.thumb.png.11071348f99eeb6a22dd70f43c7ab502.png

 

 

Share this post


Link to post
1 hour ago, Mike Torrettinni said:

OK, I tried defined as class method , I don't notice any difference

@Stefan Glienke is not suggesting that you use a class method. He's just pointing out that the title of this topic is misleading.

Share this post


Link to post
2 minutes ago, David Heffernan said:

@Stefan Glienke is not suggesting that you use a class method. He's just pointing out that the title of this topic is misleading.

Aha, I get it now. Well, I tested it anyway, just in case 🙂

Share this post


Link to post
20 hours ago, David Heffernan said:

I don't think RTTI doubles or triples the size of your executables. I also think that people worry overly about the size of the executables. Certainly worry about this on mobile platforms, but generally on desktop platforms you should be less concerned of the increases due to RTTI. 

In projects consisting of numerous DLLs it is a pain though. I wish I could strip it out completely in those projects.

Share this post


Link to post
25 minutes ago, A.M. Hoornweg said:

In projects consisting of numerous DLLs it is a pain though. I wish I could strip it out completely in those projects.

Why does it make a difference whether or not the code is in a DLL? 

Share this post


Link to post
16 minutes ago, David Heffernan said:

Why does it make a difference whether or not the code is in a DLL? 

If you have many DLLs with bloat is duplicated.

 

Also code size is not something that should be observed from disk size perspective. How do you deliver that code also matters. If you need to make frequent updates to some remote place with poor or expensive Internet connection then every byte counts. Literally.

Share this post


Link to post
47 minutes ago, David Heffernan said:

Why does it make a difference whether or not the code is in a DLL? 

I'm not talking about "a" DLL.  I have a project consisting of lots and lots of (com) DLL's that are used by several other projects in our company. These DLL's have many code libraries in common. The problem is that the RTTI of those libraries gets linked into every one of them.  It adds up.  And since I don't use RTTI at allit's a dead weight multiplied over and over again.

 

I must deploy my software to oil rigs in remote locations and the connections are most often slow and metered, so the bloat is very undesirable.

Share this post


Link to post
1 hour ago, Dalija Prasnikar said:

If you have many DLLs with bloat is duplicated.

Why would it be duplicated? Why would the same RTTI be found in different DLLs?

 

14 minutes ago, A.M. Hoornweg said:

These DLL's have many code libraries in common. The problem is that the RTTI of those libraries gets linked into every one of them.  It adds up.

Why are you singling out the RTTI here? Isn't the fundamental issue that you have duplicated code. If the duplication of the code bothers you, don't have duplicated code. And guess what. You then won't have duplicated RTTI.

 

Or am I missing something?

Share this post


Link to post
8 minutes ago, David Heffernan said:

Or am I missing something?

 

If it's true, is it related to the bloated dcu's with generics reported by Stefan back in the days?

Share this post


Link to post

Let's return the focus on the original question. In the IDE the blue dots represents the lines of codes that might be executed (http://docwiki.embarcadero.com/RADStudio/Sydney/en/Debugging_the_Application_(IDE_Tutorial).

IMHO nobody should expect the IDE will keep which method is where used (especially if you have a project with thousands of units). Another problem could be if you debug a code in a package. There you can have public methods that are used exclusively only from outside of the package. If the IDE would place blue dots only to reachable code from the  active project you would be unable to debug those procedures.

 

Share this post


Link to post

There are several factors - RTTI is one of them, another is generics, in combination they can be quite terrible.

Example: A class is using a TList<something> as a field - TList<T> has RTTI enabled which causes all code for that TList<something> to reside inside the binary even though calls to Add, Delete and alike are inlined and go directly to those non generic TListHelper methods. Now multiply that with all lists and dictionaries in RTL/VCL and your code and you have the issue.

 

Having said that - this is just one case which I was working on as author of a library that makes extensive use of generics and I don't want to be a big contributor to that issue.

 

Putting {$WEAKLINKRTTI ON} into the project file can reduce the bloat a bit because this enables the linker to remove all methods that are not being used. An empty FMX application on Win32 is 8.5MB in release config and contains way over 2MB just from System.Generics.*. With that option you can at least reduce this to 7.4MB (numbers from Delphi 10.1). How that option affects your code depends on your code.

 

During the development of Spring4D I rigorously have used {$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])}{$ENDIF} in a lot of units to at least reduce any bloat from my code but without recompiling the RTL/VCL/FMX you cannot do that for the Delphi code.

  • Like 1

Share this post


Link to post
28 minutes ago, David Heffernan said:

Why would it be duplicated? Why would the same RTTI be found in different DLLs?

 

Why are you singling out the RTTI here? Isn't the fundamental issue that you have duplicated code. If the duplication of the code bothers you, don't have duplicated code. And guess what. You then won't have duplicated RTTI.

 

Or am I missing something?

Of course there's duplicated code, the whole sense of libraries is that they contain stuff meant to be re-used.  I bet that every DLL of mine carries tStringlist, tButton and a thousand common objects more. It's not the duplication of code that bothers me, it's the big block of non-code I didn't ask for. 

 

 

 

 

 

Share this post


Link to post
1 minute ago, A.M. Hoornweg said:

Of course there's duplicated code, the whole sense of libraries is that they contain stuff meant to be re-used.  I bet that every DLL of mine carries tStringlist, tButton and a thousand common objects more. It's not the duplication of code that bothers me, it's the big block of non-code I didn't ask for. 

If you really want to reduce the size of what you deploy then use runtime packages instead of DLLs and you won't duplicate RTL/VCL classes. Likely that would save you far more than you would save by stripping RTTI in the RTL/VCL code that you link, were it even possible for you to do that.

Share this post


Link to post

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

×