Re: Slow application startup when using a theme

2012-01-09 Thread Eric Wasylishen
Hi Fred,

On 2012-01-09, at 2:26 PM, Fred Kiefer wrote:

> On 09.01.2012 20:59, Eric Wasylishen wrote:
>>> That would probably works but what about changing how +imageNamed:
>>> works ?
>>> 
>>> When this method is called with a image name lacking an extension
>>> (ie 'GNUstep' or 'common_arrowLeft'), it tries to find a existing
>>> file by adding any know extension and calling a NSFileManager
>>> method, and this 3 times (main bundle, theme bundle and then every
>>> Images directory in the system). With bitmaps existing only in the
>>> system directories this is extremely costly as it tries something
>>> like 500 paths before the good one. (And I know you understand all
>>> that, I'm just filling the blanks for the others who might be
>>> interested, sorry :o)
>>> 
>>> Couldn't we inverse the thing and check if one of the existing file
>>> in the directories has an extension known to be an image type ? I
>>> mean : list the files in the main bundle, look for the ones with a
>>> matching name (ie 'common_arrowLeft') and then check if the
>>> extension is none. The list of file in a bundle could also be
>>> cached.
>>> 
>>> Worth trying ?
>> 
>> That sounds like a good idea.
>> 
>> Much of the overhead when using Neos is caused by the section of
>> -[GSTheme activate] which loads all images in the theme.
>> 
>> Here are some tests: startup Ink with default theme: 51k syscalls
>> startup Ink with Neos.theme: 183k syscalls startup Ink with
>> Neos.theme, with GSTheme.m lines 473 to 539 commented out: 95k
>> syscalls.
> 
> I am not completely sure why this code is that way. What I remember is
> that we need to override all the already loaded images.
> But there was more to it. It could have to do with unloading an image
> and restoring the previous image state.
> I hate the way we deal with images in themes and have often stated this,
> but haven't come up with a better idea up to now.

I didn't like the current approach either…  I just committed a rewrite of how 
theme images are handled which gets rid of theme proxies entirely, and 
eliminates the code in -[GSTheme activate] and -[GSTheme deactivate] which were 
setting/restoring images.

Now, when a name is set on an NSImage instance, it also subscribes to the theme 
change notification. When an NSImage receives this notification, it does the 
name-to-path lookup again that +[NSImage imageNamed:] did, and reloads itself 
(discarding all reps) if the path has changed.

It's a fairly major change but I tested Gorm, GSTest, SimpleAgenda, and tried 
switching between the GNUstep default theme, Neos, and Etoile's Nesedah theme 
while the apps were running, and all images seemed to update properly.

>> Fred, even if we implement image filter services support and move the
>> ImageMagick support to a service, +[NSImage imageNamed:] would still
>> do just as much work because it uses [NSImage imageFileTypes], which
>> would include the types supported by filter services.
> 
> This is correct and it is what I already stated. My suggestion here was
> to rewrite imageNamed: to first check the unfiltered images and only
> later the filtered ones.

Ah, I agree that sounds like a good idea.

>> How about adding caching to NSBundle? It already caches the budle
>> info.plist, why not the directory listing of the resource directory?
> 
> Here the question is what should we cache?

I'm not sure. The preliminary caching Richard just added makes a big difference 
as I reported (95% reduction in system calls, when using Neos.theme and the 
ImageMagick image rep is installed.)

>> Also, it might be nice if NSBundle would have a private method:
>> -(NSArray*)pathsForResource: (NSString*)name ofTypes:
>> (NSArray*)types;
> 
> Yes, this is exactly the method we should be using. That way we could also 
> resolve the problem of inconsistent localisation, that is the case where we 
> have localisation files with different extensions and for some cases fall 
> back to the non localised versions, because they get found
> first.

Ok, great. I'm not going to attempt this right now but it would be nice to do 
at some point.

>> which given a name like @"common_ArrowRight" and a types array
>> (@"tiff", @"png", … ) would return an array of paths to any matching
>> resources in the bundle, and it would do so efficiently using a cache
>> of the directory contents.
> 
> Sounds great, I am just wondering how Apple gets by without this method?

Not sure, perhaps they use a private method as well.

Regards,

Eric
___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
https://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: Multiple _OBJC_Module in the same shared library/framework, not so good

2012-01-09 Thread Nat!

Am 08.01.2012 um 15:48 schrieb Richard Frith-Macdonald:
Hi Richard

>> 
>> ---
>> A class’s +load method is called after all of its superclasses' +load 
>> methods.
>> A category +load method is called after the class's own +load method.
>> In a +load method, you can therefore safely message other unrelated classes 
>> from the same image, but any +load methods on those classes may not have run 
>> yet.
> 
> Your third point here does not follow from the others  ... unless by 'safely' 
> you are talking about a very specific case:

I'd agree if.., but these are not my words. That's a snippet from the NSObject 
documentation.
(http://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/clm/NSObject/load)

> You can call methods in unrelated classes in the same compilation unit, as 
> long as those methods do not (directly or indirectly) call other methods 
> which do not obey the same rule.
> So, yes you can construct code which works to call various methods from 
> +load, but it's so fragile that calling it 'safe' would be perverse.

:)

> 
> In practice that boils down to the rule that you can't safely call any ObjC 
> code from within +load (irrespective of whether you are talking about Apple 
> or GNU) ...

See above documentation snippet, can't agree with you there with respect to 
Apple. I _can_ safely message some other classes there.

I can also not agree with you on GNU, because I can't believe, that self could 
be nil during a GNU +load. If it can't be nil, then logically there exists a 
class, with a subset of your projects objc code callable. What this subset is, 
I will try to deduce form here-on.
 

As David said "+load actually comes with the strongest guarantee, because it 
guarantees not to be run until after all superclasses have been loaded." 


IF +load is called, then it comes with this guarantee. 
BUT +load may also not be called at all...


I tested the following two cases. The first is just a class Y, being dependent 
on X.

libX.so:
X;
+[X load]

libY.so:
Y:X;
+[Y load]

main:   main.o libX.so  libY.so 

   and

main:   main.o libY.so  libX.so 


Both result in the +load order

+[X load]
+[Y load]

And it works, due to quite an effort on the runtime part, because the +load of 
subclass may need to be delayed, for the superclass to appear.


Here is the example, where it fails. Two independent classes A,B and two 
categories on A,B.

libA.so:
A;
+[A load]
+[B(A) load]

libB.so:
B;
+[B load]
+[A(B) load]

main:   main.o libA.so  libB.so

or

main:   main.o libB.so  libA.so


Depending on the link order, either +[B(A) load] or +[A(B) load] is silently 
discarded. Ouch!

(Or are categories then broken as a whole ? I will assume that just +load is 
broken, for the rest of this missive.)


So aside from +load on categories being broken, what else can be said about the 
environment of a class or a category in the current GNU runtime with random 
link order when getting the +load message ?

1) For a class or a category, all superclasses are present, therefore all 
superclasses +load have executed. This allows your code to message your class 
and your superclasses, but you need to be sure, that said message is not 
implemented in a category and that the called message itself isn't calling 
outside the inheritance chain. (If you subclass NSObject, you strictly speaking 
can't message NSString or call a method that calls NSString.) 


2) Q: If the superclass is NOT in the same image, then can it be said, that all 
classes in the image, the superclass resides in, have +loaded ?   

   A: No, because some of them may be delayed for their superclass.

3) Q: If it is known, that this other class residing in the image of my 
superclass has a common superclass with my superclass (f.e. my class subclasses 
either NSResponder or NSScreen in AppKit, which are both subclasses of NSObject 
in Foundation). Is it then known that the other class must also have +loaded ? 

   A: Maybe! 

Imagine two class hierarchies placed into three images

X:Y:Z
  A:Z

lib1.so: X
lib2.so: Y A
lib3.so: Z

--- dlopen lib1.so
X gets delayed (Y)
--- dlopen lib2.so
Y and A get delayed (Z)
--- dlopen lib3.so
Z appears 
+[Z load]
now
+[Y load]
and either
+[X load] +[A load]
or
+[A load] +[X load]

It would be known, that A has loaded before X, if it is guaranteed that delayed 
subclasses (Y A) of a class (Z) are maintained on a FIFO queue on a placeholder 
of that class (Z). (Or some similiar mechanism)

4) Q: If 3) is true, is it then known that categories of A,Y,Z, that reside in 
the dependent images, have +loaded before X ?
   A: No, not without nontrivial additional effort.



> you need to stick to C code in order to avoid someone (perhaps you) coming 
> back to the code later and inadvertently breaking it by modifying one of 
> those other meth

Re: Slow application startup when using a theme

2012-01-09 Thread Philippe Roussel
Le lundi 09 janvier 2012 à 22:18 +0100, Philippe Roussel a écrit :
> Le lundi 09 janvier 2012 à 20:51 +, Richard Frith-Macdonald a
> écrit :
> > On 9 Jan 2012, at 19:59, Eric Wasylishen wrote:
> >  
> > > How about adding caching to NSBundle? It already caches the budle
> > info.plist, why not the directory listing of the resource directory?
> > 
> > I hacked in some quick/dirty cacheing in NSBundle.  Does it make
> > enough difference to be worth doing properly rather than reverting?
> 
> Application startup is now a little under 2 seconds down from 3 without
> your changes. Better but still slow.

After removing the caching code in [GSTheme -activate] mentioned by
Eric, application startup with Neos is only 0.1 second slower than with
the default GNUstep theme. That's an improvement !

Thanks,
Philippe



___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
https://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: Slow application startup when using a theme

2012-01-09 Thread Fred Kiefer

On 09.01.2012 20:59, Eric Wasylishen wrote:

That would probably works but what about changing how +imageNamed:
works ?

When this method is called with a image name lacking an extension
(ie 'GNUstep' or 'common_arrowLeft'), it tries to find a existing
file by adding any know extension and calling a NSFileManager
method, and this 3 times (main bundle, theme bundle and then every
Images directory in the system). With bitmaps existing only in the
system directories this is extremely costly as it tries something
like 500 paths before the good one. (And I know you understand all
that, I'm just filling the blanks for the others who might be
interested, sorry :o)

Couldn't we inverse the thing and check if one of the existing file
in the directories has an extension known to be an image type ? I
mean : list the files in the main bundle, look for the ones with a
matching name (ie 'common_arrowLeft') and then check if the
extension is none. The list of file in a bundle could also be
cached.

Worth trying ?


That sounds like a good idea.

Much of the overhead when using Neos is caused by the section of
-[GSTheme activate] which loads all images in the theme.

Here are some tests: startup Ink with default theme: 51k syscalls
startup Ink with Neos.theme: 183k syscalls startup Ink with
Neos.theme, with GSTheme.m lines 473 to 539 commented out: 95k
syscalls.


I am not completely sure why this code is that way. What I remember is
that we need to override all the already loaded images.
But there was more to it. It could have to do with unloading an image
and restoring the previous image state.
I hate the way we deal with images in themes and have often stated this,
but haven't come up with a better idea up to now.


Fred, even if we implement image filter services support and move the
ImageMagick support to a service, +[NSImage imageNamed:] would still
do just as much work because it uses [NSImage imageFileTypes], which
would include the types supported by filter services.


This is correct and it is what I already stated. My suggestion here was
to rewrite imageNamed: to first check the unfiltered images and only
later the filtered ones.


How about adding caching to NSBundle? It already caches the budle
info.plist, why not the directory listing of the resource directory?


Here the question is what should we cache?


Also, it might be nice if NSBundle would have a private method:
-(NSArray*)pathsForResource: (NSString*)name ofTypes:
(NSArray*)types;


Yes, this is exactly the method we should be using. That way we could 
also resolve the problem of inconsistent localisation, that is the case 
where we have localisation files with different extensions and for some 
cases fall back to the non localised versions, because they get found first.



which given a name like @"common_ArrowRight" and a types array
(@"tiff", @"png", … ) would return an array of paths to any matching
resources in the bundle, and it would do so efficiently using a cache
of the directory contents.


Sounds great, I am just wondering how Apple gets by without this method?

___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
https://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: Slow application startup when using a theme

2012-01-09 Thread Philippe Roussel
Le lundi 09 janvier 2012 à 20:51 +, Richard Frith-Macdonald a
écrit :
> On 9 Jan 2012, at 19:59, Eric Wasylishen wrote:
>  
> > How about adding caching to NSBundle? It already caches the budle
> info.plist, why not the directory listing of the resource directory?
> 
> I hacked in some quick/dirty cacheing in NSBundle.  Does it make
> enough difference to be worth doing properly rather than reverting?

Application startup is now a little under 2 seconds down from 3 without
your changes. Better but still slow.

Unrelated : your last change in Source/GSAvahiNetService.m breaks the
build.

Thanks,
Philippe


___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
https://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: Slow application startup when using a theme

2012-01-09 Thread Eric Wasylishen

>> How about adding caching to NSBundle? It already caches the budle 
>> info.plist, why not the directory listing of the resource directory?
> 
> I hacked in some quick/dirty cacheing in NSBundle.  Does it make enough 
> difference to be worth doing properly rather than reverting?
> 

Yes, it makes a big improvement :-)

before caching: startup Ink with Neos.theme: 183k syscalls
after caching: startup Ink with Neos.theme: 11k syscalls

Eric
___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
https://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: Slow application startup when using a theme

2012-01-09 Thread Philippe Roussel
Le lundi 09 janvier 2012 à 12:59 -0700, Eric Wasylishen a écrit :
> Hi,
> Thanks for the report, Philippe; this is indeed a fairly serious problem. :-(
> 
> > 
> > That would probably works but what about changing how +imageNamed:
> > works ?
> > 
> > When this method is called with a image name lacking an extension (ie
> > 'GNUstep' or 'common_arrowLeft'), it tries to find a existing file by
> > adding any know extension and calling a NSFileManager method, and this 3
> > times (main bundle, theme bundle and then every Images directory in the
> > system). With bitmaps existing only in the system directories this is
> > extremely costly as it tries something like 500 paths before the good
> > one. (And I know you understand all that, I'm just filling the blanks
> > for the others who might be interested, sorry :o)
> > 
> > Couldn't we inverse the thing and check if one of the existing file in
> > the directories has an extension known to be an image type ? I mean :
> > list the files in the main bundle, look for the ones with a matching
> > name (ie 'common_arrowLeft') and then check if the extension is none.
> > The list of file in a bundle could also be cached.
> > 
> > Worth trying ?
> 
> That sounds like a good idea.
> 
> Much of the overhead when using Neos is caused by the section of
> -[GSTheme activate] which loads all images in the theme.
> 
> Here are some tests:
> startup Ink with default theme: 51k syscalls
> startup Ink with Neos.theme: 183k syscalls
> startup Ink with Neos.theme, with GSTheme.m lines 473 to 539 commented
> out: 95k syscalls.

This code isn't working correctly then as it's supposed to load the
bundle images and cache them so that [NSImage +imageNamed:] can find
them quickly.
It should minimize the work to load all bitmap as it's using the list of
existing files, something close to what I proposed, instead of trying
every paths on the planet...

Or am I missing something here ?

> Fred, even if we implement image filter services support and move the
> ImageMagick support to a service, +[NSImage imageNamed:] would still
> do just as much work because it uses [NSImage imageFileTypes], which
> would include the types supported by filter services.
> 
> 
> How about adding caching to NSBundle? It already caches the budle
> info.plist, why not the directory listing of the resource directory?
> 
> Also, it might be nice if NSBundle would have a private method:
> -(NSArray*)pathsForResource: (NSString*)name ofTypes: (NSArray*)types;
> 
> which given a name like @"common_ArrowRight" and a types array
> (@"tiff", @"png", … )
> would return an array of paths to any matching resources in the
> bundle, and it would do so efficiently using a cache of the directory
> contents.

Sounds nice.

Philippe


___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
https://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: Slow application startup when using a theme

2012-01-09 Thread Richard Frith-Macdonald

On 9 Jan 2012, at 19:59, Eric Wasylishen wrote:

> Hi,
> Thanks for the report, Philippe; this is indeed a fairly serious problem. :-(
> 
>> 
>> That would probably works but what about changing how +imageNamed:
>> works ?
>> 
>> When this method is called with a image name lacking an extension (ie
>> 'GNUstep' or 'common_arrowLeft'), it tries to find a existing file by
>> adding any know extension and calling a NSFileManager method, and this 3
>> times (main bundle, theme bundle and then every Images directory in the
>> system). With bitmaps existing only in the system directories this is
>> extremely costly as it tries something like 500 paths before the good
>> one. (And I know you understand all that, I'm just filling the blanks
>> for the others who might be interested, sorry :o)
>> 
>> Couldn't we inverse the thing and check if one of the existing file in
>> the directories has an extension known to be an image type ? I mean :
>> list the files in the main bundle, look for the ones with a matching
>> name (ie 'common_arrowLeft') and then check if the extension is none.
>> The list of file in a bundle could also be cached.
>> 
>> Worth trying ?
> 
> That sounds like a good idea.
> 
> Much of the overhead when using Neos is caused by the section of -[GSTheme 
> activate] which loads all images in the theme.
> 
> Here are some tests:
> startup Ink with default theme: 51k syscalls
> startup Ink with Neos.theme: 183k syscalls
> startup Ink with Neos.theme, with GSTheme.m lines 473 to 539 commented out: 
> 95k syscalls.
> 
> 
> Fred, even if we implement image filter services support and move the 
> ImageMagick support to a service, +[NSImage imageNamed:] would still do just 
> as much work because it uses [NSImage imageFileTypes], which would include 
> the types supported by filter services.
> 
> 
> How about adding caching to NSBundle? It already caches the budle info.plist, 
> why not the directory listing of the resource directory?

I hacked in some quick/dirty cacheing in NSBundle.  Does it make enough 
difference to be worth doing properly rather than reverting?


___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
https://lists.gnu.org/mailman/listinfo/gnustep-dev


Re: Slow application startup when using a theme

2012-01-09 Thread Eric Wasylishen
Hi,
Thanks for the report, Philippe; this is indeed a fairly serious problem. :-(

> 
> That would probably works but what about changing how +imageNamed:
> works ?
> 
> When this method is called with a image name lacking an extension (ie
> 'GNUstep' or 'common_arrowLeft'), it tries to find a existing file by
> adding any know extension and calling a NSFileManager method, and this 3
> times (main bundle, theme bundle and then every Images directory in the
> system). With bitmaps existing only in the system directories this is
> extremely costly as it tries something like 500 paths before the good
> one. (And I know you understand all that, I'm just filling the blanks
> for the others who might be interested, sorry :o)
> 
> Couldn't we inverse the thing and check if one of the existing file in
> the directories has an extension known to be an image type ? I mean :
> list the files in the main bundle, look for the ones with a matching
> name (ie 'common_arrowLeft') and then check if the extension is none.
> The list of file in a bundle could also be cached.
> 
> Worth trying ?

That sounds like a good idea.

Much of the overhead when using Neos is caused by the section of -[GSTheme 
activate] which loads all images in the theme.

Here are some tests:
startup Ink with default theme: 51k syscalls
startup Ink with Neos.theme: 183k syscalls
startup Ink with Neos.theme, with GSTheme.m lines 473 to 539 commented out: 95k 
syscalls.


Fred, even if we implement image filter services support and move the 
ImageMagick support to a service, +[NSImage imageNamed:] would still do just as 
much work because it uses [NSImage imageFileTypes], which would include the 
types supported by filter services.


How about adding caching to NSBundle? It already caches the budle info.plist, 
why not the directory listing of the resource directory?

Also, it might be nice if NSBundle would have a private method:
-(NSArray*)pathsForResource: (NSString*)name ofTypes: (NSArray*)types;

which given a name like @"common_ArrowRight" and a types array (@"tiff", 
@"png", … )
would return an array of paths to any matching resources in the bundle, and it 
would do so efficiently using a cache of the directory contents.

Eric



___
Gnustep-dev mailing list
Gnustep-dev@gnu.org
https://lists.gnu.org/mailman/listinfo/gnustep-dev