Performance of an application - it’s not the tool, but the person

Frankly speaking, I was still benchmarking Qt and Lazarus on making my application with Qt, and yesterday I concluded. It was not the tool or language itself, but the users’ capabilities which determines the performance of an application. Whether it be Pascal or C++, LCL or Qt, if the programmer generates spaghetti code, the application SHALL SURELY slow down. In my recent benchmarks, if I use only the same routine and algorithms, time elapsed was always the same between two environments by 1/1000 seconds. So, anyway the problem is pilot, whether the personal trooper be Gespenst or Alteisen(?).

So finally I chose Object-Pascal based Lazarus. Though I have used Qt in my development, as I continue my benchmark with the hope in Pascal language, I could assure myself if the programmer has enough capabilities then tools are just ‘tools.’ Of course I’m a huge fan, or Otaku(….. :P) of Pascal language. Though it does not have features as rich as Qt does, which is overwhelming, I can easily and more simply implement those features, and the my performance of implementation was similar to that in Qt. So I’m going with Lazarus, which is surely my best partner.

But I don’t want to say that Qt is poor. It’s still great library. Personally, the structure of Qt is the most beautiful after Delphi VCL. But restrictions in 3rd party libraries due to the structure of the library itself as well as its unique preprocessing represented by moc makes me hesitate to choose the environment as my favorite. And debugging is yet another problem - Now I encountered memory leak, and I don’t see any solution with features provided by QString. When I load a data of a few hundred megabytes into RAM, in 32bit environment application hangs with “out of memory” error. I’d like to do manual garbage collection, but the memory manager Qt uses didn’t allow me to do that. It’s like a bit unfit clothes to me.

So, I planned to start rebuilding the application by making some libraries for features not implemented in base library, but now I become lazy and tired….. I don’t want to do anything right now. Baaaaaaah. -o-

Would there be anything that excites my passion?

프로그램의 성능, 문제는 도구가 아니라 사람

그동안 프로그램을 짜면서 Qt와 Lazarus의 성능을 계속 벤치마킹하고 있었는데, 어제 최종적으로 결론을 내렸습니다. 결론인즉 프로그램의 성능을 좌우하는건 도구나 언어가 아니라 그걸 쓰는 사람의 역량이더군요. 파스칼이든 C++이든, LCL이든 Qt든 간에 쓰는 사람이 프로그램을 베베 꼬아놓으면 결국 프로그램도 버벅대게 마련이더군요. 이번에 완전히 같은 루틴을 쓰면서 테스트해보니 결과값이 양쪽 모두 1/1000초까지도 거의 동일하게 나왔습니다. 결국 게슈펜스트나 알트아이젠이나 문제는 파일럿이에요(응?).

그래서 저는 그냥 Object Pascal 기반의 Lazarus로 가기로 했습니다. 그동안 계속 Qt로 개발을 수행했지만, 파스칼에 대한 일말의 희망을 놓지 않고 꾸준히 벤치마킹한 결과 프로그래머가 능력이 되면 도구는 말 그대로 도구일 뿐이더군요. 물론 제 자신이 파스칼을 좀 심하게 사랑하는 파스칼빠(….. :P)이기도 하죠. 비록 Qt처럼 말이 안 나올 정도로 풍부한 기능을 제공하지는 않지만, 그런 기능을 훨씬 더 간단하게 구현할 수 있을 뿐더러, 구현 후 속력이 Qt의 속력과 거의 비슷하다는 것을 고려한다면 제게 최적의 개발도구는 Lazarus인 것 같습니다.

Qt는 매우 훌륭한 라이브러리입니다. 개인적으로는 Delphi의 VCL 이후 가장 아름다운 hierarchy라고 생각합니다만, moc으로 대표되는 Qt만의 preprocessing과 기타 구조적인 문제로 인해 3rd party library의 사용에 제약이 발생하는 경우가 있습니다. 그리고 디버깅도 어렵습니다 - 지금 만드는 프로그램도 memory leak이 발생하는데, QString에서 제공되는 함수들로는 이런 문제를 해결할 수 있는 방법이 보이지 않습니다. 수백 MB에 이르는 데이터를 통채로 메모리에 올려서 작업하다보면 32bit에서는 얼마 안 되어 바로 메모리 부족으로 프로그램이 터져버리더군요(…..). 가능하면 메모리 관리자로 바로 접근해서 garbage collection을 수동으로 수행하고 싶은데, Qt는 메모리 관리를 자체적으로 따로 수행하는지라 이것도 실질적으로는 불가능하고….. 좀 답답하더군요.

해서 오늘부터 부족한 기능부터 라이브러리로 만들고 슬슬 작업을 시작해볼까 했는데….. 의욕이 안 섭니다. 귀찮아요. 모든게 다 귀찮아요. 으어어. -o-

어디 의욕과 투지가 끓어오르게 할만한 뭔가가 없을까요.

How to boot your Linux box on USB media without initrd or initramfs

It is widely known you need initrd or initramfs to boot your Linux box over USB media, namely USB HDD or Flash memory drives, but you can do it without it.

Basically, USB media relies on SCSI driver for its recognition. The problem is that you have to wait for some time to make it recognized, namely one or two seconds or so. And during the time your kernel doesn’t wait for the media to be recognized - yes. it was the “common sense.”

However, you can make your Linux kernel to wait for root devices to be recognized. Simply add “rootwait” option on your kernel boot parameter and everything is done. Or, you can use “rootdelay=NN” option to make some timeout. These options are introduced in kernel 2.6, and I heard that there’s a patch for 2.4 kernels to do the same.

The only problem here is that you can’t make use of UUID or disk labels to recognize the boot media. Dynamic devfs like mdev or udev need to be run to assign UUIDs or read disk labels from each partition. So, chances are that you must rely on traditional static devfs - boot to /dev/sda or so.

Of course there’s a issue that you do may not know which device file is assigned to your boot media on boot. Your /dev/sda can be either SATA or SAS HDD, and there can be more than one - chances are, most of the time your boot media can be assigned as /dev/sdb or sdc or sdd or….. Whatever. In this case, you can compile your kernel to include only SCSI disk driver and USB media only and compile others(SATA, SAS, IDE…..) as modules so that during the initial boot kernel can recognize only USB media and other media can be recognized later on init stage when udev or mdev is populated(=daemon is started).

Hope this helps you simplifying your boot process of Linux from USB media. Good luck!

initrd나 initramfs 없이 리눅스를 USB에서 부팅하기

일반적으로 리눅스를 USB에서 부팅하려면 initrd나 initramfs를 필수적으로 사용해야 되는 것으로 알려져 있습니다만, 실제로는 필요가 없게 만들 수도 있습니다.

기본적으로 USB는 SCSI 드라이버를 통해 자신을 인식합니다. 단지 문제라면, USB 미디어는 커널이 그 존재를 인식하는데 시간이 걸린다는 겁니다(일반적으로 1~2초). 그리고 커널은 그 시간을 기다려주지 않고 무작정 지 멋대로 부팅하다가 부팅할 미디어가 없다면서 멈춰버리죠.

하지만, 커널 2.6에서 추가된 rootwait이나 rootdelay=NN 커널 부팅 옵션을 사용하면 root device가 부팅할 때까지 커널을 기다리게 할 수 있습니다. 무작정 기다리려면 rootwait을, 타임아웃이 필요하다면 rootdelay를 사용하면 됩니다(※Kernel 2.4에서는 이와 관련된 별도의 패치가 필요하다고 합니다).

단지, 한가지 문제점이 있다면, 이런 방법으로는 UUID나 디스크 레이블로 부팅 미디어를 지정할 수 없다는 것입니다. UUID나 디스크 레이블은 mdev나 udev같은 동적 디바이스 파일시스템을 사용하는데, 이를 동작시키려면 initrd나 initramfs가 필요합니다 - 뒤집어서 말하자면, 이 방법을 사용하면 정적인 구형 devfs를 사용하는 방법밖에 없습니다. 이를테면, /dev/sda같은 형태로밖에 부팅 디바이스를 지정할 수 없습니다.
이렇게 되면 가끔은 부팅할 디바이스의 디바이스 파일이 무엇으로 설정될지 감을 잡을 수 없는 경우가 생깁니다. /dev/sda는 SATA나 SAS가 될 수도 있고, 시스템에 따라 1개가 아니라 그 이상의 HDD가 달려있을 수도 있습니다. 이게 sdb가 될지 sdc가 될지 sdd가 될지 뭐가 될지 며느리도 모르는 상황이 될 수도 있다는 거죠(……).

이 경우 편법을 사용하는 방법이 있습니다. SCSI 디스크 드라이버와 USB media 드라이버만 커널에 포함시키고, 나머지, 그러니까 SATA나 SAS, IDE같은 것들은 모듈로 컴파일해서 udev나 mdev가 동작할 때쯤 인식시키게 하면 커널은 무조건 USB 미디어부터 인식하게 됩니다. 이렇게 하면, USB 미디어가 2개 이상이 되지 않는 한, USB는 무조건 /dev/sda로 인식됩니다.

다들 잘 아시는 방법이시겠지만, 혹시나 모르시는 분들이 있을까봐(사실은 제가 잊어버릴까봐) 이 포스팅에 올려둡니다. 이 방법이 우연히 여기를 방문하시는 분들이 USB로 리눅스를 부팅하는 프로세스를 단순화하는데 도움이 되었으면 합니다.

Order of Rebuilding Complete Toolchain in Linux

First update Linux header files and toolchain components once in following order: linux-header glibc binutils gcc

Now upgrade is made, but still the machine codes are from legacy toolchains. So we’re urged to renew the machine code of toolchain components themselves.

One note: in Gentoo Linux, you have to run gcc-config to check whether the new version is selected as the default compiler, or your Gentoo box will still use the legacy version to compile everything.

The order is as follows - glibc binutils gcc.

The reason to build glibc first? That’s because it affects to the content of binutils and gcc. :P

리눅스 툴체인의 완벽한 리빌드

우선 리눅스 헤더파일을 업데이트하고 툴체인 구성요소를 새로 컴파일한다. 순서는 linux-header glibc binutils gcc 순.

이렇게 하면 일단 업데이트는 끝나지만 툴체인 구성요소들의 기계어 코드는 아직 기존 툴체인이 생성한 코드에 기반하고 있다. 따라서 툴체인 구성요소 그 자체의 기계어 코드도 신버전의 코드로 갱신할 필요가 있다.

참고로, 젠투 리눅스의 경우 이 단계에서 gcc-config를 실행하여 새로 컴파일된 gcc가 선택되었는지의 여부를 확인하고 진행하여야 한다(그렇지 않으면 이전 gcc로 컴파일을 하므로 모든게 도루묵….. -o-).

이후 glibc binutils gcc의 순서로 다시 컴파일.

glibc부터 업데이트하는 이유라면….. binutils와 gcc의 내용에 영향을 주기 때문이려나. :P

How to make import library from DLL(for Visual C++ or MinGW)

Just a note for myself.

How to refine VC++ import library LIB files for DLLs created from Lazarus or MinGW:
  • dumpbin /exports file.dll(dumpbin is included in VC++)
  • Use a text editor to write a def file(e.g. file.def) like the content below:
    EXPORTS
    functiona
    functionb
    functionc
    ……
  • lib /def:file.def to create lib file
  • use the lib file in compilation of application to make the application aware of DLL entry points

To use DLLs from Visual C++ to MinGW, the def files from dumpbin can be compiled into .a files(library files for GCC) with DLLTOOL in MinGW:
  • dlltool -U -d file.def -l file.a
Compatibility note: for compatibility with other compilers and languages(e.g. C++ vs. Pascal), always use stdcall for calling convention and extern “C” in C++ side.

블로그를 이전합니다

뭐, 이런 작은 변방의 블로그에 관심있으신 분들은 아무도 없으시리라 생각합니다만...... (웃음) 블로그 플랫폼을 블로거에서 dev.to로 옮겼습니다. 새 URL은 아래와 같습니다: https://dev.to/teminian 새로운 거처에서 뵙겠습니...

Popular in Code{nested}