6 ms·
No, it's due to performance. C++ oop is somewhat close to the idea (purists don't say that it's not) without sacrificing too much perf. Objective-C spends like
by adamnemecek 8y ago
No, it's due to performance. C++ oop is somewhat close to the idea (purists don't say that it's not) without sacrificing too much perf. Objective-C spends like half of CPU time in objc_msgSend. And that's ignoring the cost of "far" jumps.
- jacquesm 8y agoAnd Smalltalk - for much the same reasons - has some pretty quirky code in the VM to be able to make the concept of message passing between objects work fast enough to do real work. There is a pretty sharp dividing line in the VM between 'the elegant stuff' and 'the hack to make it all work', where the primitives are activated. Smalltalk primitives and their classes are of necessity implemented outside of the language, they 'just work' and you can not inspect their implementation within the VM because that would require you to reflect on its own implementation, which it can not do for obvious reasons. So even though Smalltalk is 'self aware' to an extreme degree that self awareness does not extend all the way to the bottom, and I don't see how that would be possible anyway. At some level you will have to make the jump between the CPU you'd like to have (the one executing Smalltalk directly) to the one that you actually have. There is this guy: http://www.merlintec.com/lsi/jecel.html http://www.merlintec.com/lsi/jecel.html who has been working on a ST hardware implementation for a long time, I am not aware of its current status. But note that even in that situation you will still be limited, but then not at the level of the VM builtins but at the level of the CPU instruction set implementing the primitives. Ideally Smalltalk would be able to transcend the boundaries of the computer it runs on sending messages to other computers with proper error handling, that would be some kind of hybrid between the BEAM and the Smalltalk VM.
- rgrau 8y agoI guess it's not the same kind of introspection because it adds a level of indirection, but I've heard stories of the VM itself being implemented in something called "slang"[1] that's a kind of lower level smalltalk that easily compiles to C, but can be interpreted in smalltalk itself (via an Interpreter class that is perfectly normal smalltalk). Information is quite sparse on that topic, and my knowledge is quite fuzzy there but I'd love to find more info on that (in case anyone can provide links.) 1. http://wiki.squeak.org/squeak/slang http://wiki.squeak.org/squeak/slang
- scroot 8y agoWhen Pharo and Squeak people do VM development, they do it inside a special image equipped with the VMMaker package [1]. What this package has is both "slang" -- which can easily compile to C -- and an emulator running the development VM inside the smalltalk image. So with some exceptions, VM development occurs almost exclusively inside Smalltalk itself. In fact, this is how Alan Kay, Dan Ingalls, and others brought Squeak to life from an old Apple Smalltalk implementation. They touched C directly as minimally as possible and took the Smalltalk concept very seriously. [1] http://pharo.gemtalksystems.com/book/Virtual-Machine/Building/VMMakerTool/ http://pharo.gemtalksystems.com/book/Virtual-Machine/Buildin...
- jecel 8y agoWhen the original Smalltalk-80 "blue book" came out in 1983, it included a complete listing of a reference implementation of the virtual machine. http://sdmeta.gforge.inria.fr/FreeBooks/BlueBook/ http://sdmeta.gforge.inria.fr/FreeBooks/BlueBook/ Instead of using Pascal or C, the code was written in a subset of Smalltalk-80 itself. This subset (later named Slang in the Squeak project in 1996) doesn't use objects nor polymorphism. It only deals with an Array of integers and only uses a few control structures, so every expression has a C equivalent. The first VM implementers at Apple, DEC, Tektronix and HP manually translated this code into Pascal, assembly or C as their starting point and then evolved their code from there. Much later it was shown that this code could actually run inside Smalltalk-80. http://ftp.squeak.org/docs/OOPSLA.Squeak.html http://ftp.squeak.org/docs/OOPSLA.Squeak.html
- scroot 8y agoYeah anyone reading this who is curious should really check out the Blue Book, it is fantastic. There is a follow up book called "Smalltalk-80: Bits of History, Words of Advice" that discusses some of those early VM implementations
- derefr 8y ago...which is not all that strange. If you were using a Lisp machine (or, say, IBM z/OS), and you wanted to do POSIX software development, you'd probably 1. use your own POSIX machine to cross-compile a POSIX ABI simulator for the target OS; and then 2. deploy a POSIX sandbox to the target, with POSIX tools like gcc inside, and continue work on things like the POSIX ABI simulator in there.
- pjmlp 8y agoWell even the standard C library is impossible to implement 100% in plain ISO C without resorting to language extensions or Assembly.
- jecel 8y agoThanks for mentioning my project! I am still working on the design of Smalltalk hardware, but this year I have expanded that a bit to include efficient emulation of other machines (such as x86 or ARM) and not just the Smalltalk VM. Note that in Self many of the implementation tricks needed to make Smalltalk run fast were eliminated. And I see no reason why the number of primitives can't be as few as 12 or so. The rest are needed either for speed (but a good compiler can let normal Smalltalk code do the same job) or to talk to the operating system (but a Smalltalk on "bare metal" doesn't need that).
- AceJohnny2 8y ago> Objective-C spends like half of CPU time in objc_msgSend. Profile or GTFO
- adamnemecek 8y agoPick and app and I will profile it.
- AceJohnny2 8y agoiTerm2? During a 'cat' of a 1MB text file. Or Sublime Text, from launch, opening a 1MB text file, modify 10 chars at the beginning, save, and exit. Edit: NVM, it's written in C++
- davidgay 8y ago> Or Sublime Text, from launch, opening a 1MB text file, modify 10 chars at the beginning, save, and exit. Edit: NVM, it's written in C++ It doesn't use a "gap"? Or some other appropriate text-editing data structure?
- derefr 8y agoI think the parent commentor was referring to the problem that happens when you go to save. (Which is, really, just a problem with how filesystems only allow files to be represented as little seek(2)able character devices. If there was an API that would let a userland program treat a [sparse] file's data as a vector of extents—and arbitrarily manipulate that vector, such as by creating a new raw on-disk extent, writing data to it, and then prepending it to the file's extents list—then this performance problem would disappear, without any filesystem even having to change its data architecture.)
- mpweiher 8y agoNope. Even with badly written Objective-C that tends to max out at around 16% visible in the profiler. And with "badly written" in this context, I mean code that treats the hybrid language Objective-C as a pure OO language. objc_msgSend() is generally not the performance problem in Objective-C code, and the amount of stupid stuff done based on the misconception that it is is truly astounding. That includes CoreFoundation ("it's C, so it must be fast, oh but we need flexibility, so let's use a CFDictionary...") and Swift, which manages to be slower than Objective-C at just about everything. And yes, I've done the measuring: http://www.mypearsonstore.com/bookstore/ios-and-macos-performance-tuning-cocoa-cocoa-touch-9780321842848?xid=PSED http://www.mypearsonstore.com/bookstore/ios-and-macos-perfor...
- chadcmulligan 8y agoWhen Objective C was originally written, there were no L2 caches etc, Would you say the performance penalty objc_msgSend caused then compared to now was greater? I remember looking into it back then and it was regarded as to slow compared to C or C++, but hardware has changed. Is the hardware now more optimised to handle Objective C, than 20 or 30 years ago would you say? (Looks an interesting book by the way - now on my reading list :-) )
- mpweiher 8y ago"As expected, the object-oriented version is slower; about 43% slower, primarily due to the extra overhead of message passing. [..] This overhead is approximately 2.5x that of calling a function and far slower than accessing memory directly with a C expression" -- OOP, and Evolutionary Approach, Brad Cox 1986 Note the comparison to memory access. Nowadays, an actual memory access (that doesn't hit the caches) is more than an order of magnitude slower than a message-send. So if you can save a single DRAM access by performing 10 message-sends, you will come out ahead. So yes, the changes in hardware, particularly the relative changes have made a huge difference. For a lot of programs today, the stuff that comes between stalls waiting for DRAM is essentially free. Also, Apple has continuously optimised objc_msgSend(), it is quite a beast these days. Things that make Objective-C/Cocoa code slow are multitude, certainly the prevalence of NSDictionary (and CFDictionary) and other forms of keyed accessing, particularly because NSString, while a great implementation for user-facing Unicode strings, is extremely heavyweight for use as a symbol. Then there are call-return based APIs where streaming would be more appropriate (NSJSONSerialization/NSPropertyListSerailization) and the fact that APIs that look like they would be streaming (keyed archiving, swift coding) actually build NSDictionaries underneath). CoreFoundation was also quite the disaster, performance-wise (more than 2x regression compared to pre-CF Foundation), with Foundation itself also a significant regression, partly because it eliminated convenient collections for C types except bytes (NSData). Integer or float arrays are trivial to add ( https://github.com/mpw/MPWFoundation/blob/master/Collections.subproj/MPWIntArray.m https://github.com/mpw/MPWFoundation/blob/master/Collections... ) and 100 - 1000x faster than NSArrays of NSNumbers. The binary property list format is capable of both random access (lazy loading...) and of directly encoding object graphs, but the APIs don't expose those capabilities. Stepstone Objective-C had stack allocation for objects, this was eliminated by NeXT and not reinstated by Apple. So objects require heap allocation. Etc. While I also agree that Objective-C was regarded as too slow compared to C++ in particular, that was never really true. Just as a small example, I did image processing in Objective-C, and yes, if you were to apply OO and message-sending on a per-pixel level, you'd be in a world of pain. But even at scan-line granularity, the overhead was already less than 1%, so in the noise. My Objective-C Postscript interpreter is faster than the Adobe interpreter (C-based last I checked) used by Apple at basic language-oriented tasks such as arithmetic/loops. And of course, you wouldn't really want to use the OO part of Objective-C for operations on low-level C types such as or integers, the syntax is not really inviting compared to C for that sort of stuff. So I always thought that the hybrid nature (coarse-grain objects, connecting C-level implementations) worked really well, for both expressiveness and performance. The XML Parser example in the book shows how you can combine low-level C character processing with messaging-APIs to get both amazing performance (significantly faster than libxml2) and extremely convenient/powerful APIs. IMHO :-)