진실 1: Smalltalk는 느리다

May 29, 2005 06:08
 
많은 사람들이 Smalltalk는 느리다고 한다. 정말 그렇게 느린가?
 
결론부터 말하면, 그렇다Smalltalk는 느리다.
 
그러나 위의 한 문장을 보고 바로 이 글을 그만 읽으려고 생각한다면 내가 여러분이 '단편적인 사람'이라고 생각해도 화내지 말자. ^^
속도에 대해서 이야기를 할 때에는 필연적으로 '비교'를 해야 한다. 도대체 느리다면 얼마나 느린 것이고, 빠르다면 어느만큼 빠른가?
 
빠른 속도를 자랑하는 경주용 자동차빠른 속도를 자랑하는 경주용 자동차
빠른 속도를 자랑하는 경주용 자동차
편안하게 운전할 수 있는 승용차편안하게 운전할 수 있는 승용차
편안하게 운전할 수 있는 승용차
 
여러분이 일반적으로 사는 도시라는 환경 속에서 일상적으로 이용한다면 이 둘 중에 어느 것을 택할 것인가? 곰곰히 생각하며 아래 글을 끝까지 읽어주시기를, 정중하게 부탁드리는 바이다.
 

1. 벤치마크 테스트

 
벤치마크의 대명사, 하노이의 탑벤치마크의 대명사, 하노이의 탑
벤치마크의 대명사, 하노이의 탑
 
SmalltalkSmalltalk
Smalltalk
의 속도를 비교할 때 자주 등장하는 언어가 
CC
C
언어이다. C언어에 비해서 Smalltalk는 느리다고 말한다. 그리고 그것은 사실이다.
아시다시피, C언어에서는 소스 코드를 번역할 때(compile-time) 모든 것이 이미 결정이 되어 있다. 자료형(data type)도 고정되어 있고, 함수도 그렇다. 이미 번역을 할 때 컴파일러는 모든 것을 알고 있다. 따라서 C에서 만든 프로그램은 실행 속도가 빠르다. 실행 시간에 무언가를 결정할 일이 없기 때문이다.
반면 Smalltalk에서는 소스 코드를 번역할 때 결졍되어 있는 것은 거의 아무 것도 없다. 모든 것은 번역할 때가 아니라 실행할 때(run-time) 그제서야 결정된다. 지금 번역하고 있는 소스 코드가 어떤 형태의 객체를 사용할지도 모르고, 내가 보낸 메시지를 받은 객체가 어떻게 반응할지 전혀 알 수 없다. 결국 Smaltlalk로 만들어진 프로그램은 실행될 때 여러 가지 상황을 직접 판단해서 결정을 내려야 한다.
프로그램이 실행될 때 하는 일을 놓고 보면 아무 것도 하지 않고 주어진 대로만 실행하는 C언어가 이리 저리 상황 파악을 하면서 실행하는 Smalltalk 언어보다 더 빠른 속도를 낼 수 밖에 없는 구조이다.
이것을 가장 극명하게 나타내어 주는 상황이 바로 벤치마크(benchmark)다. 벤치마크는 모든 상황을 미리 정해놓고, 그 상황에서 얼마나 빨리 특정한 계산을 수행하는가를 측정하는 것이다. 잘 알려진 하노이의 탑, 에라토스테네스의 채 등 순전히 연산 능력만 검증하는 여러 가지의 벤치마크들을 C와 Smalltalk로 돌려보면 100% C언어의 압승으로 끝난다. 이런 상황에서 Smalltalk는 참패의 고배를 마실 수 밖에 없다.
 

2. 절반은 놀고 있는 CPU

그런데 여러분이 오늘 처음 컴퓨터를 켜서 이 글을 읽을 때까지 도대체 어떤 일을 했는지 되돌아보자.
Windows 환경에서 여러분이 이 글을 읽는다면 우선 웹브라우저를 열고 페이지가 모두 표시되기를 기다린 다음 웹페이지에서 이 글을 발견하고 클릭한다. 그러면 네트워크에서 이 글의 내용을 받아서 웹브라우져에 뿌리고 결국 여러분들은 스크롤을 해 가면서 이 글을 보게 된다.
그런데 글을 읽던 중 갑자기 [메일 도착 알리미]에서 새 메일이 도착했다고 하자. 그러면 여러분은 이 글을 잠시 미뤄두고 도착한 새 메일을 읽으려 할 것이다. 메일을 다 읽었는데 때마침 갑자기 친구가 와서 CD를 한 장 궈달란다. 여러분은 CD 굽는 프로그램을 이용해서 CD를 구워준다. 위에서 말한 작업을 수행하는 시간을 잘 계산해 보면 컴퓨터의 CPU가 끊임없이 무언가를 계산하기 보다는 시간의 절반 이상을 [기다리는데] 쓰고 있다는 걸 알 게 될 것이다.
Windows 2000이나 XP를 사용하는 사람이라면 지금 당장 [Ctrl-Alt-Del] 키를 눌러서 작업 관리자의 [성능] 탭을 열어보자. 그리고 위에서 말한 것처럼 웹도 탐색해 보고 이것 저것 프로그램을 돌려보기 바란다. 그런 뒤에 다시 [작업 관리자]를 보자.
 
이것이 성능 탭. 놀고 있는 CPU 보이는가?이것이 성능 탭. 놀고 있는 CPU 보이는가?
이것이 성능 탭. 놀고 있는 CPU 보이는가?
 
놀랍게도 CPU는 전체 능력의 절반 정도 밖에 발휘하지 못하고 있다. 그 이유는 바로 CPU가 무언가를 계산하는 것보다 언제나 무언가를 [기다리는] 시간이 더 많기 때문이다.
여러분이 CPU의 동작 속도만큼 키보드를 빨리 칠 수 있는가? 웹페이지의 링크를 클릭할 때 네트워크로 전달되는 정보가 CPU의 동작 속도만큼 빠를 수 있는가? 심지어는 CPU와 가장 밀접하게 연결되어 있다는 RAM도 CPU의 동작 속도를 완전히 따라잡지 못하고 있다. 자, 이래도 단순한 벤치마크 결과로 언어의 성능을 단정지을 수 있는가?
 

3. 세상에 공짜란 없다

맞다. 세상엔 정말 공짜라는 게 없다. 무언가를 얻기 위해서는 반드시 그에 대한 무언가를 버려야 한다. 이것은 IT 분야에 몸담고 있는 사람 뿐만 아니라 모든 사람들이 풀어야 하는 문제이다. 이것과 저것, 양쪽을 얻기 위해서 절충하는 것, 그게 어렵다는 거다. 이걸 영어로는 trade-off라고 한다더라.
C언어가 저만큼의 속도를 얻기 위해서 다음의 몇 가지를 버렸다.

- 프로그램의 유연성

모든 것이 번역할 때 결정되어 버린다. 실행할 때의 상황이 변하면 그만큼 적응하기 어렵다. 새로운 변수가 생길 때마다 프로그램의 복잡도는 올라간다.

- 개발자의 편리성

컴파일러가 좀 더 빠른 실행 코드를 만들어 내기 위해서 '인간의 생각'보다 '컴퓨터의 생각'을 강요한다. 포인터가 과연 사람들의 사고에 적합한 개념인가? 실행 시간에 생기는 각종 문제들을 지적해 줄 수도 없는 컴파일러의 번역 시간 자료형 검사를 피하기 위해서 난무하는 수 많은 형변환(type casting)연산자가 프로그램의 신뢰도를 높일 수 있는가? 모든 것을 한꺼번에 번역해야 하는 컴파일 방식의 언어에서 학습과 검증에 모두 다 탁월한 성능을 보이는 '대화식 개발법'을 쓸 수 있는가?
 
결국 C언어는 속도와 유연성, 두 가지 중에 속도를 택했다. 이는, C언어를 고스란히 계승한 C++의 경우도 다르지 않다. C++ 역시 속도와 유연성 두 가지를 놓고 상당히 고민한 흔적이 보인다. 그러나 C++의 경우 역시 속도를 최우선으로 생각했다. C++를 만든 Bjame Stroustrup 씨의 철학은 얼마나 통일되고 유연성 있게 객체지향 개념을 지원하느냐 보다는 얼마나 빠른 코드를 만들어낼 수 있는가에 집중되어 있다.
 
The C++ Programming Language. 이 책에 분명히 기록되어 있다.The C++ Programming Language. 이 책에 분명히 기록되어 있다.
The C++ Programming Language. 이 책에 분명히 기록되어 있다.
 
 
이처럼, '빠르다'라는 속도를 얻어내기 위해서 C나 C++를 비롯한 대부분의 언어들은 너무나 많은 대가를 치렀다. Smalltalk가 이들 언어에 비해서 속도가 느리다고해서 과연 성능마저 떨어지는 언어라고 말할 수 있을가?
 

4. 속도만큼 중요한 것들

물론, 지금이 1970년대에서 1990년대라면 당연히 '속도'가 최우선이 되어야 한다. 10년전만 하더라도, 컴퓨터로 어떤 일을 해내기 위해서는 상당히 빠른 속도의 컴파일러형 언어가 필요했다. 그러나, 하드웨어의 성능은 눈부시게 높아지고 있으며 메모리의 가격또한 싸지고 있다.
Smalltalk가 지향하던, 그래픽 사용자 중심 환경,, 대화식 환경, 개발자와 사용자가 모두 '즐기면서' 프로그래밍을 할 수 있는 환경, 그 환경을 구현하기 위해서, 과거에는 너무나 많은 비용을 지불해야 했다. 결국 비싸고 느린 하드웨어의 한계 때문에, Smalltalk는 주목을 받지 못했다.
그러나, 오늘날 빠르고 값싼 하드웨어와 수십 메가바이트의 데이터를 아무렇지도 않게 주고 받는 요즈음에 있어서 '속도'를 얻기 위해 잃어야 했던 것을 다시 찾으려는 노력이 이루어지고 있다. 바로 유연성, 사람 중심 환경, 대화식 환경. 그렇다. 이 모든 개념은 이미 Smalltalk가 표방했던 개념들이다.
맞다. 바로 진정한 객체지향의 개념들이 이제서야 비로소 실현되려 하고 있다. 여러분이 사용하고 있는 Windows와 같은 GUI 운영 체계, 모든 개발 환경이 한 곳으로 모인 통합 개발 환경(IDE), 익스트림 프로그래밍과 검증 중심(test driven) 프로그램을 위한 대화식 개발 환경, 쓰지 않는 객체를 자동으로 치워주는 쓰레기 수집기(Garbage Collector), 프로그램의 실행 상태를 실시간으로 알 수 있게 만들어 주는 각종 디버그 정보들과 실행시간 자료형 정보(Run-time type Information: RTTI), 보다 더 안전한 프로그램의 실행을 위해서 존재하는 가상 기계까지.... 과거에는 '빠른 속도'를 얻기 위해 버려지거나 희생되었던 개념들이 지금에 와서 다시 각광을 받으며 제 위치를 찾아가고 있다.
놀라운 사실은, 저 위에 나열했던 모든 것이 바로 Smalltalk 언어와 환경, 바로 그것의 특징이라는 것이다. 분명히 오날늘에 와서는 '속도'와 더불어 중요한 것들이 있다. Smalltalk는 '빨라야 한다'는 생각에 의해서 버려지거나 무시되어 왔던 수많은 특징들을, 30년 동안 묵묵히 가지고 있었고, 비록 자기 자신은 그 존재조차 알리지 못했을지라도, 자신이 가지고 있던 개념들을 여러 분야에 하나씩 빌려주면서 지금까지 그 명맥이 이어져 온 것이다. 이래도, Smalltalk가 빠르지 않다는 이유만으로 성능이 떨어진다고 말할 수 있는가?
 

5. 기초를 흔들면 쉽게 무너지기 마련...

기초가 탄탄하면 그 위에 세워진 집은 쉽게 무너지지 않는다. 튼튼한 기초 위에 세워진 집은 아름다우며 그 구조가 명확하고 언제나 통일성을 갖는다. 설령 그 집을 증축한다 하더라도 기초가 튼튼하기 때문에 아무런 문제 없이 증축할 수 있다.
C++는 '객체지향'을 지원하기 위해서 만들어졌으면서도 너무나 쉽게 객체지향의 '토대'를 내던져버렸다. 다분히 살아있는, 동적인 객체의 세계를 '소스 코드'와 '실행 파일' 속에 꽁꽁 얼려서 가두어 버린 언어가 C++다. 처음 C++ 언어가 만들어질 당시, 이와 같이 꼭 필요한 개념들이 '속도 향상'이라는 미명 아래 폐기되어 반영되지 못했다. 하지만 객체지향의 특성을 제대로 살리기 위해서 결국 C++ 언어는 비싼 대가를 치르고 자기가 버린 것들을 다시 주섬 주섬 담기 시작했다.
객체의 활동성에 치명상을 입힌 정적인 함수 호출을 보상하기 위해 상당히 무겁고 느린 virtual 함수를 도입했다. 강제적으로 접근권을 제어하는 public, protected, private 때문에 객체의 설계와 구현에 어려움을 느낀 나머지 이들 접근 제한 지정어들을 완전히 무시해버리는 friend를 도입했다. 정적 자료형 언어의 한계에서 벗어나서 좀 더 다형성을 잘 지원하기 위해서 실행 코드의 크기가 쉽게 커지고, 디버깅이 곤란한 템플릿(template)을 도입했으며, Smalltalk의 컬렉션 라이브러리를 본딴 STL을 도입했다. 실행 시간에 객체의 신원(identity)을 파악해야하는 이 당연하고 필수적인 기능을 구현하기 위해서 C++ 표준화 위원회에서는 최근에 부랴부랴 RTTI에 관련된 지정어와 연산자, 라이브러리를 추가했다.
결국 C++ 언어가 걸어온 길을 되짚어 보면 처음에는 '속도'를 중요시한 나머지 언어 명세에서 제거되었거나 기능이 축소된 부분들이 시간이 지남에 따라 다시 언어에 더해지고 이것은 언어의 문법과 라이브러리, 통일성을 갉아먹는 존재가 되었다.
C++ 언어가 간결하다고 누가 감히 말할 수 있는가? 결국 애초에 있어야만 할 것들을 버린 대가를 C++는 너무나 톡톡히 치르고 있으니 정말 통탄할 노릇이다.
이런 언어의 부담은 결국 그대로 개발자들이 져야 할 짐이 되고 만다. 프로그램의 문제 영역에 관심을 기울여야 할 개발자들이 지금도 C++의 문법(syntaxt)과 의미(sementic)와 문맥(context) 속에서 허우적 거리는 지금이 이 상황을 두고 '아비규환'이라고 하면 지나친가?
Smalltalk는 속도 때문에 이러한 것들을 버리지 않았다. 비록 느리게 돌아가지만, 완벽함을 추구헀고 대중에게 외면을 받았지만 통일된 일관성을 추구했다. Smalltalk는 컴파일러의 비위를 맞추기 위해 필요했던 정적 자료형 검사를 과감히 버렸다. 모든 변수는 사용하기 전에 선언되어야 함은 물론이지만 변수의 자료형까지 미리 못박아 버릴 필요는 없다. 보라! 저 수많은 언어가 단순히 '정적 자료형'이라는 특성 하나 때문에 진정한 다형성을 구현하지 못하고 있는 저 안타까운 현실을! 강제 형변환 연산자, template 등이 바로 이런 정적 자료형 언어의 산물이다.
사람들은 "실행 시간에 언제나 자료형을 검사해야 하므로 느리다"고 말한다. 물론 BASIC, LISP 등 기타 동적 자료형 언어에서는 이 말이 맞는지 모른다. 하지만, Smalltalk에서는 실행시간에 자료형을 검사하는 일 따위는 하지 않는다. 아니, 할 필요가 없다. Smalltalk의 객체가 실행 시간에 메시지를 받으면 제일 먼저 하는 일은 해당 객체의 메서드 사전(method dictionary)에서 해당하는 메시지에 맞는 메서드를 찾는 일이다. 이 사전은 빠른 탐색 알고리즘인 hash table이어서 대부분 한 번에 메서드의 유무를 검출한다. 만약 해당하는 객체에(정확히는 그 객체의 클래스에) 메서드가 없다면 해당 객체의 수퍼클래스(superclass)에 있는 메서드 사전을 뒤진다. 대략 계승 관계가 10단계 정도의 깊이를 가진다는 최악의 상황이라도 10번 정도만 메서드를 검색하면 결국 해당 메서드의 유무를 알 수 있다.
C++의 virtual 함수는 어떤가? 물론 구현 방법에 따라 차이는 있지만 vtable을 사용한다고 가정하면 virtual 함수들은 선언된 순서대로 함수 포인터 테이블에 저장된다. 그리고 만약 virtual 함수가 호출되면 이 함수 테이블을 선형적으로 하나씩 검색해서 해당하는 함수 포인터가 가리키는 함수의 내용을 실행하는 방식이다. 가령 virtual 함수 10개를 가진 클래스가 10개의 깊이로 상속되어 있다면 최악의 경우에 100 번을 검색해야만 원하는 멤버 함수를 찾을 수 있다. 오죽하면 C++ 책들에서 virtual 함수를 사용하는데 신중을 기할 것을 역설하고 있다. Virtual 함수가 객체에게 활동성을 부여하는 기본 중의 기본이라는 것을 망각한 체....
Smalltalk는 기초적인 객체지향의 토대를 훼손하지 않으면서 자신의 느린 속도를 어떻게 하면 만회할 수 있을까에 온 힘을 모았다. 이를테면, 한 번도 중첩(overriding)되지 않은 메서드의 경우 내부에서 C++와 같은 정적 함수로 처리하고 Integer와 같은 기본 primitive 자료형의 경우 외부에서는 일반 객체와 동일하게 처리하지만 내부에서는 객체 포인터의 변형으로 구현하는 방식이다. 또한, 전형적인 가상 기계(virtual machine)에서 동작하는 방식에서 발전하여 Smalltalk 코드를 바로 기계어로 컴파일하는 방식의 Smalltalk도 구현되어 있다. 즉, 겉으로 드러나는 개념의 추상화에는 절대로 손을 대지 않고 그것을 구현할 때 가장 최적의 방법을 찾으려 노력했다.
이러한 Smalltalk의 접근 방법은 오늘날 눈부신 하드웨어의 발전에 힘입어 비로소 그 가치를 속속 드러내기에 이른다. Smalltalk가 느리다고 생각되면, 지금 당장 Dolphin Smalltalk를 받아서 실행해 보기 바란다.
 
 
 
10000의 factorial()을 구하는 Smalltalk 화면10000의 factorial()을 구하는 Smalltalk 화면
10000의 factorial()을 구하는 Smalltalk 화면
 
90% 이상이 Smalltalk 언어 자체로 쓰여진 환경을 직접 둘러보고 과연 눈에 보일 만큼의 성능 저하가 있는지를 스스로 느껴보자.
 

6. 또다른 개념의 속도: 개발 속도

만약 당신이 다음 두 가지 특성을 지니는 언어가 있다면, 어떤 것을 고를까?
 
  •  A: 개발하는데 1개월이 걸리고, 실행하는데 30초가 걸리는 언어.
  •  B: 개발하는데 4개월이 걸리고, 실행하는데 10초가 걸리는 언어.
 
바로 실행 속도와 함께 중요한 것이 '개발 속도'이다.
현재와 같이 빨리 변하는 사회에서, 개발 주기가 길어진다는 건 절대로 무시 못할 일이다. 최근 어느 지면의 기사를 보면, 기업 환경에서 소프트웨어의 빠른 개발을 위해 스크립트 언어를 쓰는 경우가 점점 늘어나고 있다고 한다. 잘 알다시피, 대부분의 스크립트 언어는 대화식 개발 환경이며 그와 동시에 동적 자료형 언어이다. 결국 보다 더 빨리 프로그램을 개발할 수 있다. 그런데 스크립트 언어는 결국 스크립트 언어일 뿐, 프로그래밍 언어가 아니다.
Smalltalk는 바로 여러분이 내버린 '스크립트 언어'의 특징을 가지고 있는 프로그래밍 언어이다. 엄연히 실행 파일을 만들어 낼 수 있는 언어이다. 간단한 문법, 대화식 개발 환경, 통일된 개념, 살아있는 객체, Smalltalk가 가지는 이러한 특성이 개발 주기를 짧게 만들어준다.
예를 하나 들어보자. 지금 맞춤법 검사기가 내장된 일기장을 개발하고 있다.
  1. 프로그램을 컴파일 하고 실행을 시킨 뒤에 일기장 폼을 열었다.
  1. 틀린 글자를 몇 글자를 입력해보니 맞춤법이 틀린 곳에 빨간 밑줄이 그어진다. 흠, 그런데 그냥 밑줄은 좀 밋밋하다. 빨간 물결줄로 고치는게 좋겠다.
  1. 일단 열려있는 프로그램을 닫은 뒤, 빨간 줄을 그리는 부분을 찾아서 고친다.
  1. 그리고 나서 다시 프로그램을 컴파일 한 뒤 실행한다.
  1. 그리고는 다시 일기장 폼을 열고, 틀린 글자 몇 개를 입력한다. 음,.. 결과가 제대로 반영된 것 같다.
이것이 기존 언어의 개발 방법이었다. 그러나 Smalltlak라면 다르다.
  1. 프로그램을 실행하고 일기장 폼을 열었다. 점진적(incremental) 컴파일로 동작하는 Smalltlak에서는 별도의 컴파일 과정이 필요 없다.
  1. 틀린 글자를 몇 글자 입력해 보니, 맞춤법이 틀린 곳에 빨간 밑줄이 그어진다. 음, 그런데 그냥 밑줄은 좀 밋밋하다. 빨간 물결줄로 고치는게 좋겠다.
  1. 빨간 줄을 그리는 부분을 찾아서 고친다. 아직 일기장 폼을 닫지 않았으므로, 해당하는 폼을 살펴보면 결과가 제대로 반영되어 있다!
이것이 Smalltalk의 힘이다. 프로그램이 이미 실행되는 중이라도 그것을 구성하는 객체의 성격을 언제나 개발자가 원하는 대로 고치거나 더할 수 있다. 어차피 Windows의 페인트 메시지를 받아서 동작하는 객체들로 이루어진 폼이기 때문에 즉석에서 수정해 주면 바로 그 결과가 화면에 반영된다.
이런 대화식 개발 방법은 프로그램에 있는 문제를 쉽게 찾을 수 있게 해 주고 개발하는데 걸리는 시간을 상당히 많이 줄여준다.
만약 납기기한이 4개월인데, Smalltalk로 1개월 만에 작업을 끝냈다면 여러분은 무엇을 할 것인가? 그냥 가만히 놀고만 있을 것인가? 그렇지 않을 것이다. 프로그램의 병목 구간(bottle neck)을 탐색해서 해당하는 구간을 최적화하여 전체적인 프로그램의 성능을 높일 것이다. 혹시 있을지 모르는 버그도 찾아낼 수 있다. 만약 프로그램이 해야 하는 연산량이 많아서 도저히 Smalltalk로는 속도가 안 나오는 최악의 경우가 발생한다면 해당하는 부분을 C언어로 작성한 후 기존 Smalltalk와 붙이면 된다. 이미 프로그램의 모든 로직이 나와 있기 때문에 일부분을 C언어로 옮기는 것은 전체를 다시 짜는 것보다 훨씬 쉽다.
개발 속도가 빠르다는 것은 점점 더 그 가치를 더해가고 있다. C++에서 버려진 개념들, 그것은 다름 아닌 개발 속도를 향상시키고 개발자가 프로그래밍에 전념할 수 있는 환경을 마련해 주며 완성된 프로그램의 신뢰도를 높여주는데 필수불가결한 요소이다.
 
자, 다시 한 번 묻겠다. 당신이 개발자라면, A와 B, 두 언어 중에 과연 어떤 언어를 선택할 것인가? 나는 감히, A언어는 Smalltalk이고, B언어는 C++라고 말하려 한다. 내가 너무 지나친 말을 하는 것인가?
 

7. 마무리...

Smalltalk는 C나 C++와 같은 언어들보다는 분명히 실행 속도가 느리다. 그러나 그 느린 실행 속도를 보상해 줄 수 있는 매우 중요한 요소들이 있다. 여러분이 만약 Java나 C# 프로그래머라면 이 칼럼에 대해서 다른 사람들보다 더 전폭적인 지지를 해 줄 것으로 믿는다. 왜냐하면 Java와 C#은 모두 C++가 버렸던 특성을 다시 되찾기 위해서 열심히 노력한 언어들이며 그를 위해서 약간의 실행 속도의 저하를 기꺼이 감수한 언어들이기 때문이다.
가상 머신과 언어의 구현 성능이 발전하고 하드웨어의 성능이 계속해서 발전하게 되면 결국 속도에 대한 문제도 조금씩 더 나은 결과를 얻을 수 있으리라고 필자는 확신한다.
 
진정한 GUI를 지원하는 첫 번째 Microsoft OS, Windows 95진정한 GUI를 지원하는 첫 번째 Microsoft OS, Windows 95
진정한 GUI를 지원하는 첫 번째 Microsoft OS, Windows 95
 
혹시나 이렇게 긴 글을 읽고도, 아직까지 Smalltalk(그리고 동료 언어인 Java와 C#)의 실행속도가 느리기 때문에 그 활용 가치가 없다고 생각하는 분들이 계시다면 당장 여러분의 컴퓨터를 포멧해버리고 Windows 95를 사용하기 바란다. 왜냐고? Windows 95는 Windows 운영체계 중에 가장 적은 메모리에서 가장 빨리 실행되는 운영체계이기 때문이다.
 
여러분은 경주용 자동차와 승용차 중에 무엇을 선택하겠는가?