From: Shawn Hargreaves Newsgroups: comp.os.msdos.djgpp Subject: Re: Style AND speed in C++? How? Please, I need some radical ideas on this one! Date: Sat, 19 Apr 1997 16:38:51 +0100 Organization: None Distribution: world Message-ID: References: <5j8ue0$8gg AT nr1 DOT toronto DOT istar DOT net> NNTP-Posting-Host: talula.demon.co.uk MIME-Version: 1.0 Lines: 88 To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp Precedence: bulk Jeff Weeks writes: >Video_Template *video; >video = new S3_driver; >video.setmode(); [snip] >I've tested this and the virtual functions seem to be exactly 2 times >slower! While style is a big concern, so is speed... so virtual >functions are a no go I think. Well, when I encoutered this problem in Allegro I opted for using virtual functions: I can't see any other way to handle different hardware architectures! Although I had to roll mine by hand rather than using that nice 'virtual' keyword, as I was working in plain 'ole C :-) Like you, I was initially quite concerned about the speed implications of this, but profiling showed it to have a negligible impact on performance. Versions of Allegro up to 2.1 used direct function calls, and I only added the virtual function indirection in v2.1 to support the new mode-X resolutions. On my 486-dx33, the change caused about a 5% slowdown in the putpixel() function, which didn't concern me unduly as such a tiny function is a useless thing to profile in any case. With more complex routines like hline() and rectfill(), it was less than quarter of a percent slower, and I couldn't measure any speed difference with blit() and the sprite drawing routines. So I wouldn't worry about it. When you say your virtual functions are 2 times slower, what are you doing in these functions? Sure, the actual function call will take longer, but proportional to the amount of time spent executing the code inside the function, is that really such a significant thing? Another trick I found useful is to seperate the main drawing routines from the hardware bank switching code. The drawing code is called by user programs, so it has to use the normal C calling convention, and you will often be able to reuse the same functions on many different types of hardware (in Allegro I have a regular 256 color putpixel function, a mode-X putpixel, and I'm currently adding 15, 16, and 32 bit putpixels. Apart from that, the same code works on any chipset). The bank switch code, though, differs on every card, and is typically only called by other of your own routines (eg. by the putpixel() function). It is a rather different case, as it can frequently be called in tight, optimised inner loops. I found it useful to implement my own calling convention for the bank switch function. I store the function pointers directly in my BITMAP structure, rather than relegating them to the vtable along with all the other virtual functions, which wastes 8 bytes of memory per bitmap but cuts out a level of indirection from the function call, and I call them from asm with a specialised register calling convention (line number in eax, bitmap pointer in edx, and the bank switcher isn't allowed to clobber any registers except eax). It can be a bit of a pain to work with these restrictions, but given the types of places a bank switch is typically used, it gave some spectacular speed improvements over using a regular C function... >I should also mention that in time, Video_Template will have a static >function called "autodetect" which will return a pointer to one of the >drivers detected. Is it then possible to do something like this: > >Video_Template *video >; >video = new Video_Template::AutoDetect(); Sure, you can do that. You'd just need to make the AutoDetect() function a static member. I'd try something like: In each derived class, have a static function along the lines of BOOL Detect(); Then your AutoDetect goes something like: static Video_Template * Video_Template::AutoDetect() { if (VideoS3::Detect()) return new VideoS3; else if (VideoCirrus::Detect()) return new VideoCirrus; else etc; return NULL; } Then your initialise code would just become: Video_Template *video = Video_Template::AutoDetect(); -- Shawn Hargreaves - shawn AT talula DOT demon DOT co DOT uk - http://www.talula.demon.co.uk/ Beauty is a French phonetic corruption of a short cloth neck ornament.