Re: WTF? How can this work?
Re: WTF? How can this work?
- Subject: Re: WTF? How can this work?
- From: Chris Kane <email@hidden>
- Date: Sun, 19 Aug 2001 18:12:55 -0700
On Sunday, August 19, 2001, at 01:05 PM, Erik M. Buck wrote:
Remind me what new features were added to Foundation to justify the
changes.
Other than
NSURL and related
Key-value coding & NSClassDescription
Scripting
only misc tweaks have been made to Foundation's API. There are other
more indirect features, like string objects now handling more encodings
and the like. Now, English-using developers running in English may not
care, but now handling Korean, Simplified Chinese, and Traditional
Chinese (and others) is very nice for Korean and Chinese speakers. (I
suppose that opens up additional potential markets for 3rd party
developers.)
But I don't see that any correlation between implementation and features
is required here. Sometimes new feature helps o
From a Cocoa developer's point of view,
how did the implementation changes and the introduction of Core
Foundation
dramatically improve the frameworks ?
I don't understand this fetish some people have for blaming
CoreFoundation. How was this conclusion arrived at? Yes, if you sample
or profile (though timings with that latter shouldn't be trusted with
all the non-profilable libraries on the system), you see most of the
time spent in CoreFoundation -- because the Foundation implementation
uses that. If Foundation didn't, all the time would be in Foundation
and people would say "Geez, Foundation is slow".
nm the OpenStep 4.2 binary (or Mac OS X Server 1.x) and grep for
'NSSimple'. Among the hits will be NSSimpleSet and NSSimpleDictionary.
These were the C-API implementations of NSDictionary,
NSMutableDictionary, NSSet, NSMapTable, and so on. What CoreFoundation
did was take those and drop them into another framework.
Now, we've certainly made implementation changes since then. I have
this feeling (but don't actually know now) that the secondary hash
function in the case of sets and dictionaries may be more subject to
catastrophic degradation in some cases than the previous one was, even
though it is often better in the general case. And, since the backing
store of mutable dictionaries accounts for a good chunk of typical apps'
heaps, we discarded one CPU-related optimization for a memory
optimization, and the dictionary type things now take about 2/3rds (and
sets 1/2) of the memory they used to OpenStep; however, the equality
function (-isEqual:) for the keys will now tend to be called more (how
much more depends on how good the key hash is). [System-wide memory use
is in a much more critical state than CPU time.] Those are examples.
But these are changes we might have made in Foundation's implementation
had the implementation remained there. They have nothing to do with
CoreFoundation particularly.
Indeed, there have been other benefits to CoreFoundation:
- NSConcreteDictionary and NSConcreteMutableDictionary used to have many
overridden methods with the same implementation, but since the two
classes didn't inherit from one another, they had copy-paste copies of
the methods; so much for reuse
- often hacks with overridden -retain/-release methods were required to
deal with reference cycles due to retaining collections; now with CF
collections that can be configured (1) to allow NULL and (2) not retain
objects, some code has been able to be simplified (I'm thinking of
CFArray here mostly)
- if we hadn't pulled the run loop model down to CoreFoundation, we
would have either had two separate event subsystems, or one designed
more around the models of Carbon which NSRunLoop would have had to adapt
to (if there were to be only one) and who knows what might have been
lost in such a transition; NSRunLoop ends up on a much more capable and
feature-ful base
- Cocoa paradigms have been brought to Carbon developers, which eases
the migration path for them; if you've already parked yourself in the
Cocoa camp and aren't budging, this doesn't directly benefit you (in
fact, you may have to wade through more "what do the square brackets
mean?" messages on the mailing lists), and may mean more competition
starting out on the 10th floor ;-);
[however, if easing the transition results in more Cocoa programmers
out there, that may have indirect benefits; if one assumes for a moment
that Apple is influenced by microeconomic-type considerations, then more
Cocoa developers might cause more relatively more documentation
resources to be applied to Cocoa doc than Carbon doc (which is in a
pretty good state); or, you want ObjC APIs to QuickTime? the best people
to do those are the experts in QuickTime, the QuickTime group, and the
more Cocoa developers the more likely that might be]
[since most of you are probably not on the Carbon lists on which this
has happened: a fun anecdote here is that some Carbon developers in the
past couple years have complained that some Carbon APIs are wrong or bad
because they don't follow the CoreFoundation Create/Copy/Get memory
ownership conventions or use reference counting, and have requested that
new APIs be provided which do.]
Yes, there have been a few new bugs in Foundation which were actually
bugs in CoreFoundation. But there have also been some bugs fixed due to
that transition.
And, because CF's collections support more features than NS collections
(such as being able to be used from CFM apps, which doesn't apply to or
benefit the ObjC API), there are some performance hits due to that. But
there have also been some good recoveries of those hits in 10.1 (even
while retaining the features). And some more coming after 10.1.
Now why convert NS implementations to use CF implementations? Well,
besides the simple answers of less code to maintain and less hot code
required to run (instead of a hot NSDictionary implementation and a hot
CFDictionary implementation, there's just a hot CFDictionary
implementation and a tiny hot NSDictionary implementation), a common
implementation gives us a bigger lever to make improvements; if you
think that a novel approach to hashing done in CoreFoundation would not
necessarily be done also to Foundation (after all, aren't you arguing
"why was something fixed which wasn't broken?"); but Foundation doing
reasonably doesn't mean there wasn't room for improvement (see DO
example below too). There is the possibility of indirect leveraging of
work done on the open-sourced CoreFoundation as well (though useful
submissions have been rare so far).
And if anyone wants to complain about the speed of the CF bits that
Foundation is based on, they're all (except CFPreferences) in Darwin to
look at, compile, test, and tune to your hearts' content.
The performance of Foundation is now
atrocious. How could things be slowed down so much ? A 450 MHz G4
performs
worse that a 266MHz Pentium II running substantially the same Foundation
code. That is embarrassing!
This depends on what you're looking at, and what you're doing. Launch
time has certainly suffered, due to the additional frameworks. Many
operations in dyld are O(N) in the number of libraries (because it was
designed and optimized more for the situation at NeXT).
Also, be wary of getting sucked into the Photoshop
PPC-2x-faster-than-Pentium miasma generated from stage. (Plus remember
that Pentium IIs didn't have the really deep pipelines that are going to
kill the P4. ;-)) Cocoa apps aren't float or integer computation-bound,
they're memory and I/O bound, and they use the Velocity Engine not at
all (unless the developer is doing that themselves), thus benefit not at
all. It may just be more paging which is hurting the G4. Well, there
are so many different and complex factors here that it's not really
worth getting into this rat's nest.
There have been may other changes to the Cocoa stack that don't involve
CoreFoundation. For example, the Scripting feature requires pulling in
new frameworks, though we do that dynamically when needed, but this also
unfortunately pulls in some frameworks indirectly that we don't need due
to the layering of the system. Or, to deal with the HFS file system,
and the additional features it has and/or users expect, we've had to
convert code in Foundation more and more to use the lower layers of
Carbon, which has many internal layers of its own; deleting a file is
not your simple unlink() anymore. [Some backtraces nowdays can be quite
breath-taking.] Or, to deal with the Mach 3.0 conversion, the built-in
Mach port-based DO transport was ported, but had to preserve the old DO
semantics in the face of Mach API changes which didn't preserve the old
semantics; it works, but not nearly as quickly as it might (but why fix
it when it works? CFMessagePort, which has more internal clients than
DO, gets the attention [and the number of external clients may be
surpassed DO's by now too, there's no way to know]; if DO was
implemented in the local case to use CFMessagePort, it'd get indirect
attention).
Some of the performance loss has been due to other layers, like the ObjC
runtime. At least problematic optimizations were tossed in 10.0, in
favor of simpler but functioning code. And in a case or two,
optimization has shifted on the CPU vs. memory balance to the memory
side. There are definitely ways to speed up the runtime, if we're
willing to burn the memory. Some very good things have been done in
10.1 to the runtime to speed thing up, particularly launch time spent in
ObjC initialization (some of these were things that could have been done
in OPENSTEP 4.2 too, it's not like they're all things recently
introduced).
Well I could go on with any of these sections, but this message is
already long enough.
Chris Kane
Cocoa Frameworks, Apple