Wie mache ich mein win32 Prog. kleiner?
-
hi ihr alle!
Ich habe mal so ein winApi Programm unter VC6 vom Wizard erstellen lassen. Die variante "hello World" jetzt sehe ich das das Programm im Speicher 1024 kb einnimmt, ich konnte im code nirgendwo was finden wo das festgelegt ist, scheint eine standardreservierung zu sein oder so.
Wie kann ich denn dieses Programm nun kleiner machen, das es weniger speicher frißt?? Werde aus dem source nicht richtig schlau. Gibts da irgendwo ein gutes tutorial wie die winapi funkt??
herzlichen Dank
l00P
-
Zeig mal deinen Code. Außerdem interessiert mich die Version deines VC6 (Std.,Prof. oder Enterprise) davon hängt nämlich viel ab.
Die beste Optimierung immer wenn es um Platz geht: Projekte->Einstellungen->MFC in einer gemeinsam genutzen DLL verwenden
BTW: Hat nicht viel mit WinAPI an sich zu tun ~> MSVC
MfG SideWinder
-
Mich würde nur interessieren warum gerade 1024 kb im Speicher reserviert sind und woher dieser wert kommt...
Also hier mein code:
// sdfsdfs.cpp : Defines the entry point for the application. // #include "stdafx.h" #include "resource.h" #include <stdio.h> #define MAX_LOADSTRING 100 // Global Variables: HINSTANCE hInst; // current instance TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text // Foward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // TODO: Place code here. MSG msg; HACCEL hAccelTable; // Initialize global strings LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_SDFSDFS, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_SDFSDFS); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; } // // FUNCTION: MyRegisterClass() // // PURPOSE: Registers the window class. // // COMMENTS: // // This function and its usage is only necessary if you want this code // to be compatible with Win32 systems prior to the 'RegisterClassEx' // function that was added to Windows 95. It is important to call this function // so that the application will get 'well formed' small icons associated // with it. // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_SDFSDFS); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = (LPCSTR)IDC_SDFSDFS; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); return RegisterClassEx(&wcex); } // // FUNCTION: InitInstance(HANDLE, int) // // PURPOSE: Saves instance handle and creates main window // // COMMENTS: // // In this function, we save the instance handle in a global variable and // create and display the main program window. // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; // Store instance handle in our global variable hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, /*SW_HIDE*/nCmdShow); UpdateWindow(hWnd); return TRUE; } // // FUNCTION: WndProc(HWND, unsigned, WORD, LONG) // // PURPOSE: Processes messages for the main window. // // WM_COMMAND - process the application menu // WM_PAINT - Paint the main window // WM_DESTROY - post a quit message and return // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; TCHAR szHello[MAX_LOADSTRING]; LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING); switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: Add any drawing code here... RECT rt; GetClientRect(hWnd, &rt); DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER); EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
-
Also hier meine Version - 16Kb mit sämtlichen optimierungen die ich auf die Schnelle erreicht habe :D:
#include <windows.h> LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int nShowCmd) { WNDCLASS wndclass; wndclass.cbClsExtra=0; wndclass.cbWndExtra=0; wndclass.hbrBackground=static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)); wndclass.hCursor=LoadCursor(NULL,IDC_ARROW); wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION); wndclass.hInstance=hInstance; wndclass.lpfnWndProc=WndProc; wndclass.lpszClassName=TEXT("Hello World"); wndclass.lpszMenuName=NULL; wndclass.style=CS_VREDRAW|CS_HREDRAW; RegisterClass(&wndclass); HWND hwnd=CreateWindow(TEXT("Hello World"),TEXT("Hello World"),WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL); ShowWindow(hwnd,nShowCmd); UpdateWindow(hwnd); MSG msg; while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return(msg.wParam); } LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam) { switch(message) { case WM_PAINT: PAINTSTRUCT ps; BeginPaint(hwnd,&ps); RECT rect; GetClientRect(hwnd,&rect); DrawText(ps.hdc,TEXT("Hello World"),-1,&rect,DT_SINGLELINE|DT_CENTER|DT_VCENTER); EndPaint(hwnd,&ps); return(0); case WM_DESTROY: PostQuitMessage(0); return(0); } return(DefWindowProc(hwnd,message,wparam,lparam)); }
Das liegt aber größtenteils nicht am Code sondern am MSVC (Projekt->Einstellungen)
MfG SideWinder
-
Meinst du jetzt eigentlich die Dateigröße oder den Arbeitsspeicher-Verbrauch?
-
odernie schrieb:
Meinst du jetzt eigentlich die Dateigröße oder den Arbeitsspeicher-Verbrauch?
Oha offenbar meint er ja den Arbeitsspeicherverbrauch und ich die Dateigröße. Hmm *nachseh*: 2644KB Speicherverbauch.
Also 1024 ist wohl nur eine Schnapszahl.
MfG SideWinder
-
Einfach mal das Fenster minimieren und staunen, wie wenig Speicher verbraucht wird.
Alternative könntest Du regelmäßig SetProcessWorkingSetSize mit -1 für den zweiten und dritten Parameter aufrufen, beispielsweise in WM_ENTERIDLE. Das geht aber ganz arg zu Lasten der Performance.
Eventuell bringt es auch etwas, die Stack-Size herunterzudrehen.
Aber was ist denn überhaupt das Problem? Was soll das?
-
16kb ??? Da kann ich ja gleich in VB schreiben.
Geht doch auch mit 1kb:
.386 .model flat, stdcall ;32 bit memory model option casemap :none ;case sensitive include 1kBDialogTest.inc include windows.inc include kernel32.inc include user32.inc include Comctl32.inc include shell32.inc includelib kernel32.lib includelib user32.lib includelib Comctl32.lib includelib shell32.lib DlgProc PROTO :HWND,:UINT,:WPARAM,:LPARAM .const IDD_DIALOG1 equ 101 .data Hello db "Hello World!",0 .code ALIGN 4 DlgTemplateOffset: ; X:\radasm\Masm\Projects\1kBDialogTest\binres 154 bytes db 1,0,255,255,0,0,0,0,0,0,0,0,64,8,200,16 db 2,0,6,0,6,0,76,0,50,0,0,0,0,0,32,0 db 58,0,41,0,0,0,8,0,0,0,0,1,77,0,83,0 db 32,0,83,0,97,0,110,0,115,0,32,0,83,0,101,0 db 114,0,105,0,102,0,0,0,0,0,0,0,0,0,0,0 db 0,0,1,80,18,0,31,0,38,0,17,0,235,3,0,0 db 255,255,128,0,69,0,120,0,105,0,116,0,0,0,0,0 db 0,0,0,0,0,0,0,0,1,0,0,80,2,0,3,0 db 72,0,17,0,233,3,0,0,255,255,130,0,49,0,107,0 db 66,0,32,0,33,0,0,0,0,0 start: invoke DialogBoxIndirectParam,400000h,offset DlgTemplateOffset,NULL,addr DlgProc,NULL invoke ExitProcess,0 ;######################################################################## DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM mov eax,uMsg .if eax==WM_COMMAND .if word ptr[wParam]==1003 invoke MessageBox,0,offset Hello, offset Hello,MB_OK jmp @F ;Quit! .endif .elseif eax==WM_CLOSE @@: invoke EndDialog,hWin,0 .else mov eax,FALSE ret .endif mov eax,TRUE ret DlgProc endp end start
-
Blumentopf schrieb:
16kb ??? Da kann ich ja gleich in VB schreiben.
Geht doch auch mit 1kb:
.386 .model flat, stdcall ;32 bit memory model option casemap :none ;case sensitive include 1kBDialogTest.inc ...
Na toll, ich rede aber schon noch von C/C++ und nicht von Assembler
MfG SideWinder
-
konstruktive Beiträge lese ich da, ich meine allerdings den RAM Bedarf, kann man wohl nicht mit Codereduktion verkleinern oder?
Das mit dem Assembler gefällt mir - echt heavy
-
Dann geh mal dort hin:
http://radasm.visualassembler.com/
da gibts nen visual assembler for windows editor mit dem machst du ein
assembler window in 30 sekunden. 1kb klein.
Dann brauchst du noch den masm32 microsoft compiler, den gibts gratis bei
http://www.movsd.com/ ---> MASM32 Download
-
ist sicher interessant, habs mir kurz angesehen, kam aber nichts dabei heraus, wer mich mal mit der materie befassen - danke
-
Was soll denn jetzt der Assembler-Quatsch? Mit was willst Du das vergleichen, mit SideWinders Beispiel? Wieviele DialogBoxen siehst Du denn da?
Außerdem ist mit 16k noch lange nicht Ende der Fahnenstange. Ich habe SideWinders Code fast ohne Änderung in eine 2k exe compiliert (VC6).
-
ich vergleich garnichts, will einfach nur wissen woher diese 1024 k ram belegung bei einem normalen generierten hello world winapi kommen...
-
l00P schrieb:
ich vergleich garnichts,
Dich habe ich auch nicht gemeint.
l00P schrieb:
will einfach nur wissen woher diese 1024 k ram belegung bei einem normalen generierten hello world winapi kommen...
Es werden eine ganze Reiche an Kernel- und User-Objekten erzeugt. Die brauchen nunmal Speicher. Deine MessageQueue bekommst Du auch nicht umsonst. Allein die GDI Handle-Table belegt 268K in Deinem Adressraum.
Da aber auch viele Bereiche von verschieden Processen gemeinsam benutzt werden (z.B. die GDI Handle-Table), ist das wirklich kein Problem.
[edit] Zusätzlich werden auch noch Dlls in Deinen Adressraum gemappt. In Deinem Fall mindestens user32.dll und kernel32.dll. Die belegen natürlich auch noch. [/edit]
-
-King- schrieb:
Was soll denn jetzt der Assembler-Quatsch? Mit was willst Du das vergleichen, mit SideWinders Beispiel? Wieviele DialogBoxen siehst Du denn da?
Außerdem ist mit 16k noch lange nicht Ende der Fahnenstange. Ich habe SideWinders Code fast ohne Änderung in eine 2k exe compiliert (VC6).
Ich habs zwar vorhin bloß "schnell, schnell" optimiert aber auf 2k komm ich auch nicht runter - wie geht das? Was hast du da noch eingestellt?
@King: Ihn interessiert ja auch gar nicht wie man den Speicherverbrauch verringern kann sondern warum es gerade 1024K sind - was imho jetzt geklärt ist: Rein zufällig, es könnten genauso gut 1025K sein.
Diese Diskussion auf "Mach das Prog kleiner" hab ich angefangen, da ich zuerst an den Plattenplatz gedacht habe.
MfG SideWinder
-
SideWinder schrieb:
Ich habs zwar vorhin bloß "schnell, schnell" optimiert aber auf 2k komm ich auch nicht runter - wie geht das? Was hast du da noch eingestellt?
Das Übliche:
#pragma comment(linker, "/OPT:NOWIN98") #pragma comment(linker, "/MERGE:.rdata=.text") #pragma comment(linker, "/MERGE:.data=.text") #include <windows.h> LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); EXTERN_C int __cdecl WinMainCRTStartup(VOID) { ExitProcess(WinMain(GetModuleHandle(NULL), NULL, NULL, SW_SHOW)); } int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int nShowCmd) { . . .
Rein zufällig, es könnten genauso gut 1025K sein.
Das nun gerade nicht, ein Vielfaches von 4K wird es schon sein.
-
-King- schrieb:
SideWinder schrieb:
Ich habs zwar vorhin bloß "schnell, schnell" optimiert aber auf 2k komm ich auch nicht runter - wie geht das? Was hast du da noch eingestellt?
Das Übliche:
#pragma comment(linker, "/OPT:NOWIN98") #pragma comment(linker, "/MERGE:.rdata=.text") #pragma comment(linker, "/MERGE:.data=.text") #include <windows.h> LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); EXTERN_C int __cdecl WinMainCRTStartup(VOID) { ExitProcess(WinMain(GetModuleHandle(NULL), NULL, NULL, SW_SHOW)); } int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int nShowCmd) { . . .
Rein zufällig, es könnten genauso gut 1025K sein.
Das nun gerade nicht, ein Vielfaches von 4K wird es schon sein.
Okay, okay ;).
MfG SideWinder
-
aha, das heißt also kleinermachen wäre zu aufwendig und bringt nicht viel. Weißt du zufällig wie man ein Programm als Dienst laufen lassen kann und welche nachteile ich dadurch hätte? Ich muß nämlich ein logging tool schreiben das keine Oberfläche hat und maximal durch ein icon im Tray zu finden ist, wie würdest du das anstsellen??
Gruß
l00P
-
l00P schrieb:
aha, das heißt also kleinermachen wäre zu aufwendig und bringt nicht viel. Weißt du zufällig wie man ein Programm als Dienst laufen lassen kann und welche nachteile ich dadurch hätte? Ich muß nämlich ein logging tool schreiben das keine Oberfläche hat und maximal durch ein icon im Tray zu finden ist, wie würdest du das anstsellen??
Gruß
l00PDas kommt drauf an: Soll das Tool ein Dienst sein oder nicht? Da liegt ja schon eine grundlegende Entscheidung die du treffen musst.
MfG SideWinder
-
Durch einen Service hast Du keine Nachteile. Nur das mit dem Icon solltest Du Dir verkneifen. Ich halte nichts von Diensten, die mit dem User interagieren. Du bist besser dran, wenn Du Deinen Dienst frei von Fenstern hälst.
Die Administratoren wissen auch so, wie sie den Dienst starten und stoppen können.