Jaký zákazník je lepší?

…tvorba web aplikací. Aplikací, NE osobních stránek!

Zrovna dneska něco plácám v praci. Já tenhle pixel hunting zrovna nemusím. Už jsem dělal plno aplikací a tak jsem se zamýšlel co je vlastně lepší. Je to obyčejný zákazním co ničemu nerozumí nebo to je nejlépe grafik, který ví co chce a chce to přesně.[MORE]

U zákazníka je výhoda v jisté toleranci výstupního vzhledu, sám zákazním ma velmi mlhavou představu co by chtěl. Nevýhodou je naopak nejasnost zadání, změny za běhu (a to prosím radikální a neslučitelné s koncepcí předchozí) a potom tvrdohlavé prosazování kokotin, které si myslí že budou cool, super, in. NE nebudou. Když chce zákazním černé pozadí a jezdící text tak je to na facku.

A teď druhá barikáda. Graficky vzdělaný člověk :), má návrh, ví co chce, dělá s jabkem a nenechá si do ničeho kecat. Výhody jsou minimální. Přesné zadání, přesné šablony, přesná funkcionalita (většinou), a nevýhody: bože, je to grafik, takže font, velikost musí sedět, rohy většinou kulaté u všeho, průhlednost naprosto všude, animace, otočky, piruety. A vše pod taktovkou přesně na pixel. Ve všech prohlížečích. Bleh. A rozhodně si nenechá vymluvit, že html na takové prasení není stavěné, přeci když to ve svém fotokrámě mohl namalovat, tak mi už do toho nějak ty data dostat umíme.

Odpověd na otázku. Ani jeden, jeden horší než druhej. Silné osobnosti ocení někoho, komu mohou vtlačit vlastní návrh. Já nejradši dělám na sebe a za sebe.

Triky s TreeView v .NET Compact Framework

článek je psaný a validní pro .NET Compact Framework (CF) v 2.0 a jazyk vb.net

Sepsal jsem tipy pro celořádkový výběr, přidání události click, doubleclick a v neposlední řadě velmi užitečné barvení řádků/pozadí.

Trik pro černé pozadí a bílý text

Tento problém má jednoduchý základ. Pokud vytvoříte objekt TreeView v CF není podporována vlastnost .BackColor. Samotné VS studio vás na to upozorní. Tím pádem není možné měnit barvu pozadí. První možností je[MORE] napsat vlastní TreeView odvozený z Object. Druhé řešení jsem zvolil já.

Každý přidávaný TreeNode má povoleny vlastnosti pozadí a barvy fontu. Proto je potřeba vytvořit a nastavit asi takhle:
Dim node As New TreeNode
node.Text = "aa"
node.ForeColor = Color.WhiteSmoke
node.BackColor = Color.Black
TreeView.Nodes.Add(node)

Tím máme černé pozadí.

Problémy

Černá barva je jen pod textem samotným. V CF není vlastnost pro nastavení FullRow. To lze obejít přidávání hodně (hodně hodně) mezer za zobrazený text. Něco jako +” “. Prasečina, ale funguje. Potřebujeme výsledky. Výkonostně to není problém. Vzniká tím druhotný problém s horizontálním posuvníkem. Ten nelze vypnout a tak je možnost ho buď skrýt jinou komponentou (mimo form) nebo napsat inteligentní algoritmus, který řádek doplní jen určitým potřebným množstvím mezer. Já volím první.

A poslední problém, který je potřeba vyřešit pro černé pozadí? I když bude TreeView prázdný musí být vyplněn položkami a to přesně počtem, které se vejdou na jeho výšku. Výška musí být násobek výšky řádku. Prázdné položky budou dělat černo a když začnou přibývat data, lze prázdné odebírat. Samotný algoritmus ať si každý udělá jak potřebuje.

Trik pro přidání OnClick a DoubleClickeventu(události)

TreeView nemá událost OnClick a občas by se mohla hodit :). Zase máme víc možností.

Buď se použije nízkoúrovňové GetFocus (viz msdn) nebo se použije nějaká existující událost a obalí se logikou. Na to je vhodná událost AfterSelect. Za běhu přidáme pomocí AddHandler TreeView.AfterSelect, AddressOf MojeFunkceClick. Samotná MojeFunkceClick vypadá asi takhle Sub MojeFunkceClick(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewEventArgs). Když tedy někdo označí položku v PDA spadne to do týhle funkce. Zde máme k dispozici e proměnou, v které je například e.Node.Tag nebo e.Node.Text. Můžeme napsat logiku na ignorování našich černých prázdných řádků. Taky sem můžeme vyrobit funkce na mazání řádku atd. Ovšem aby mohl AfterSelect opět fungovat musíme TreeView.SeletedNode = nothing. Tím jsme vyrobili onclick. DoubleClick bude vyžadovat nějakou proměnou a timeout abychom mohli realizovat ten dvojklik. Nechám to na každém.

FullRow a barevně označený řádek

S předchozí funkcí TreeView.SelectedNode= nothing přijdete o označený řádek. Proto je vhodné, uchovat si který že to byl řádek kliknut a při vykreslování položek do TreeView změnit barvu pozadí/textu a tak dále. Dá se s tím docela kouzlit. Dělat multiselect a podobně. A ten FullRow. V dokumentaci je samotná funkce jen pro velký framework a ještě s jistými omezeními. Jak jsem psal výše, stačí k textu přilepit hodně mezer a je vystaráno.

Technické problémy

Koukám koukám, začnu si užívat léta a hned se všechno na hostingu vysere. Nejdřív bylo něco s web serverem, k tomu padlo ftpko a když už to jede tak se zase posrala sql databáze. K tomu jsem migroval na novější wordpress, kterej je nějakej doprcanej a na serveru mu chyběly soubory. A završil jsem to překopírováním databáze z localhostu s vadnými nastaveními, takže to celé nějak umřelo. Že já nebloguju na nějakém tom “systému”. Jenže na to jsem moc tvrdohlavej programátor, kterej má rád, když má kontrolu nad stránkama. A pořád lepší když to občas pojede, než aby to měl někdo cizí v pazourách. Konec, tečka, vykřičník.

A do třetice jsem objevil ještě jeden zádrhel. Tak jsem trochu zapracoval na SQL Cache pro wordpress a už to všechno pěkně funguje. Celý tenhle Cache plugin je geniální věc, každou query do databáze odchytí a hledá, jestli nebyla už provedena. Jestli jako jo, tak natáhne ze souboru výsledek query a samotný dotaz do DB nedělá. Funguje to parádně a v běžném provozu to zcela databázi nepotřebuje.

Optimalizace v PDA (Compact Framework)

Za oknem léto. To každej musel zaregistrovat. Není tudíž mnoho času rozšiřovat maxigeniální myšlenky. Radši jezdím, cvičím, jím, spím a tak dále. Teď zpět k dnešnímu tématu. Několikátý měsíc, čistě pracovně, rozšiřuju svoje vědomosti o taje a zákoutí .NETího Compact Frameworku pro PocketPC alias PDA, MDA. O víkendu jsem vyvíjel novou knihovnu pro asynchronní připojení. Ta minulá byla trošku zrezlá. A když bylo dopsáno dostal jsem naprosto geniální nápad.

Vlastní dialog

Ano. Nápad byl vcelku prostý. Do skinovací knihovny přidám podporu pro vlastní dialogové okno. Samozřejmě zcela grafické. Znáte dnešní standard, na něco kliknete, celá obrazovka ztmavne a vyskočí dialog s nějakou fajnovou hláškou. Po odkliknutí to zase všechno odtmavne a jede se dál.

Úkol snadný, ne ovšem na velmi omezené platformě PDA. Tady neexistuje poloprůhlednost. Tady plno věcí neexistuje. První co jsem tedy vymyslel, byla jednoduchá FAKE aplikace, která měla předem připravené obrázky ztmaveného pozadí. Toto řešení má ovšem zásadní problém. Neumožňuje být jakkoliv flexibilní. A taky, pokud budu dialog volat odjinud, než jsem si předkreslil, nebude grafika souhlasit.

Řešení

Po nějakém tom pátrání v dokumentaci jsem pomocí PInvoke sesmolil funkci, která: sejme aktuální obrazovku PDA, uloží do bitmapy. Bitmapu potom pixel po pixelu přepočítá na “tmavé barvy” (prakticky snižuje saturaci a jas) a na tuto bitmapu doprostřed nakreslí obrázek již samotného dialogu – nějaký fancy rámeček s dialogem. Myšlenka geniální, po splácnutí preview dokonce i funkční, no bohužel smrtelně pomalá. Moje představa byla tuto operaci stihnout tak do 50-100ms. Jak dalece jsem se mýlil.


[MORE]

Optimalizace začíná

Nebudu to zdržovat. Celý proces trval neuvěřitelných 10 sekund. Za všechno mohl kód bitmap.GetPixel(x,y). A k němu reverzní SetPixel. Tyto neskutečně neoptimalizované funkce není radno používat. To už jsem věděl z dob programování grafických prvků v C++.

Zapátral jsem a od MVP lidí z MSDN jsem se dozvěděl optimalizační tipy. Základem je použít Bitmap.LockBits a UnlockBits. Tím se dostaneme přímo k nemanagované paměti bitmapy a můžeme začít řádit jak je libo. Výstupem je bajtové pole jednotlivých subpixelů(R,G,B). Pro rozlišení 240×320 je velikost pole nějakých 240*320*3=230400 pixelů. Toliko bodů je třeba nějakým způsobem zanalizovat a přepočítat (jas, kontrast, barevnost atd).

Bláhově jsem říkal, máš vyhráno. Celý proces se zrychlil na neuvěřitelných 180ms. Stačilo tedy napsat funkce na transformaci pixelu a bylo. Napsal jsem tedy vlastní RGB<->HSB transformační funkce. Sem se s nima patlal víc jak den, přetížené, patřičně okomentované, prvotřídní práce. V tuhle dobu jsem ještě netušil, že PDA je potřeba optimalizovat. Když jsem ověřil, že funkce fungují korektně, prostě jsem do smyčky s pixely vložil něco takového

ColorTransform.RGBToHSB(R, G, B, dH, dS, dB)
dB = dB * 0.4
dS = dS * 0.7
ColorTransform.HSBToRGB(dH, dS, dB, R, G, B)

Kód fungoval perfektně, výstupem bylo přesně to co jsem požadoval. Ale ouha. Transformace a násobení každého pixelu sežralo neuvěřitelných 5150ms. A tak jsem začal hledat, proč tomu tak je. Zakomentoval jsem tu část s násobením a hnedka jsem byl o pár sekund rychlejší. Už bylo jasno. Procesor v PDA stěží sčítá, natož násobí 32bit float číslo. A tak jsem přemýšlel dál.

Různá řešení

  • převést pixel na šedou a rozkopírovat do všech kanálů
  • vzít jeden kanál, dělením ztmavit a rozkopírovat do ostatních
  • sečíst všechny kanály a výsledek vydělit nějakým větším číslem
  • počítat jen sudé řádky/sloupce a výsledek rozkopírovat
  • počítat jen nutnou oblast, ostatní vynechat

Každý z těchto nápadů o něco a některé i slušně zrychlily vykonávání, ale stále jsem se pohyboval nad hranicí jedné sekundy a to bylo nepřijatelné. Musí se to počítat v reálném čase. Především výsledky s jedním kanálem vypadaly nadprůměrně hnusně. I to bych překousnul, jenže časy neodpovídaly.

No a tak jsem do noci seděl nad problémem, pořád si prohlížel hodnoty pixelu před ztmavením a po ztmavení a přemýšlel, jak tuhle hodnotu spočítat bez násobení, dělení, sčítaní. Jo a pak mě to samozřejmě trklo. Bitový posun. Není to přesné, nemá to moc možností, ale funguje to pekelně rychle kdekoliv. Tím jsem byl v podstatě hotov. Vzal jsem součet barev jednoho pixelu, shiftnul o 4 a rozkopíroval. 280ms. Super. Výstup cca dobrý.

R = (R + G + B)
R = R >> 4
G = R
B = R

Pak jsem zkusil ještě jednu úpravu a kupodivu, zrychlení a zlepšení výstupu. 255ms

R = R >> 3
G = G >> 3
B = B >> 3

Chybné cesty

Bitový posuv je tak rychlá operace, že i uvažované vynechání (nepočitání) určité oblasti, je pomalejší, než vše nechat přetáhnout posuven. Samotná režie na vyhodnocení, jestli pixel je v oblasti nebo není, je ohromná. To jsem dokonce procházení pole přepsal s doporučenými Int32 jakožto nejrychlejší možný datový typ. Počítání X a Y se samozřejmě musí provádět už v samotném cyklu nikoliv až pomocným výpočtem uvnitř cyklu. Ta režie je tak veliká, že ani vynechání všech pixelů nestačí na kompenzaci zpomalení. Tady by museli přijít taky nějaký optimalizace. Například rozdělit bitmapu pomocí BitBlt na více menším a ty zpracovávat. Nebo vyhodnocovat pozici pixelu jen občas :-/

Přikládám nějaký obrázky, jako ukázku, co je možné a za jakou dobu získat optimalizací. Rozhodně je při takových masových akcích dobře přemýšlet co a jak. Vyplatí se to. V mém případě nejde o přesné zobrazení, oko je blbý, takže je to v pohodě. Nedovedu si představit rychlost při tranformacích s maticí. Tady prostě neplatí běžná pravidla. A teď jsem dostal nápad na parádní prohlížeč obrázků :)

Reálné nasazení

Po doplácání algoritmu do mojí grafické knihovny, jsem vyzkoušel některý scénáře použití a ukázalo se to neskutečně nepoužitelný. Načtení dat z XML, vytvoření prvků, screenshot, transformace a vykreslení, to všechno zabírá víc jak sekundu času. A to je na kliknutí velká prodleva. Nakonec jsem to vyřešil vtlačením vrstvy mezi objekty. Tím se starám o cachování a preload dat. Ještě to bude chtít nějakou inteligenci pro preload. Takhle všechno zabírá moc ramky.

Život programátora, první díl

Dneska jsem se rozhodl napsat něco ze zákulisí mého pracovního procesu. Už nějaký ten rok dělám programátora pro britskou společnost. Jméno není dúležité, stejně ji u nás nikdo nezná. Takže si celý dny sedím v kanclu, datluju do kompu a při tom si všímám, že i tahle profese má určité zákonitosti, schválnosti.

[MORE]

#1

Když mám složitý problém, stačí zajít na záchod a řešení vždy vymyslím. Stačí vlastně odejít od kompu a nápady se sypou. Bohužel čím je menší pravděpodobnost, že si řešení poznamenáte, tím lepší řešení přichází.

#2

Těsně než usnu, vždy přijdu na řešení problému a nebo ještě lépe, vynaleznu novou a naprosto geniální funkcionalitu. Samozřejmě, že počítač už neběží a zvedat se taky nechci.

#3

A prozatím poslední objev. Vždy když mám v mozku geniální myšlenku, konstrukci, algoritmus, tak se mi chce děsně srát a prostě musím běžet na mísu. Čím větší myšlenka, tím větší nutkání. A na míse platí pravidlo jedna, takže většinou geniální myšlenka je ještě víc zgeniálněná :) a po příchodu ke kompu téměř nerealizovatelná.

Dodatek

Teď například dělám vlastní XML skin Loader pro Compact Framework v .NETu. Myšlenka byla na začátku jednoduchá. Mohl bych napsat nějakou pomůcku, abych nemusel komponenty naklikávat, ale mohl je dynamicky generovat z definičního souboru. Z toho se vyklubal XML soubor. Potom následovala myšlenka, že by těch souborů mohlo být více – jednotlivé obrazovky v PDA. Z toho už nebylo daleko ke skinování. Od toho rychle přisel nápad na podporu různých rozlišení a natočení podle skinu. To vše musí zaštitovat vlastní logovací a debugovací knihovna. Vracíme se k dynamickým komponentám. Ze začátku to byl obrázek na pozadí. Potom přišel klikací obrázkový buton. Následoval transparentní label, dynamický timer, textbox, klikací area. Vše završilo rozhraní pro registraci eventů pro callbacky při akci. Všechno se muselo promítnout v nastavení XML.

A tak z několikahodinové práce, je bezmála měsíc kvalitního kodérství. Vychrlil jsem užásné množstvé tříd a rozhraní. Celé to samozřejmě není u konce. Nápady stále přicházejí. Je ale jasné, že žádný projekt nevypadá na první (ani druhý, třetí) pohled tak veliký, jak ve skutečnosti je

Test: CF karty A-Data Speedy 2GB[ENG]Review: CF card A-Data Speedy 2GB[/ENG]

Dneska si dáme nějaký ten naučný článek, plný informací a poznatků. Bla bla. Koupil jsem jentak na zkoušku kartu Compact Flash A-Data Speedy 2GB. Zajímalo mě, jak je na tom nízkonákladový produkt z pohledu rychlosti.[MORE]

Protáhnul jsem kartu měření v HDtachu, SiSoft Sandrou 2007 a ultimativní utilitou hwBench v3.12. Grafy a výsledku jsou přiloženy. Co k tomu dodat. Karta je poměrně svižná při čtení a jako spouštěcí disk se dá použít bez větších obtíží. Benefit nízké přístupové doby je patrný. Zápis je ovšem věc smrtelná. Doporučuji nastavit maximální velikost sektorů pro alespoň symbolické urychlení. Velké soubory (mp3) už nahrává obstojně. Počet zápisů těžko odhadovat. Kartu jsem nerozebíral, abych se podíval co je uvnitř za paměťový čip.

SiSoft Sandra měření

[GRAPH||Rychlost (SiSoft Sandra 2007) |zápis (kB/s), čtení (kB/s)]
soubor 512B|soubor 32kB|soubor 256kB|soubor 2MB|soubor 64MB
17;1188|1835;9123|4335;9690|5666;10923|6554;10923
[/GRAPH]

hwBench v.3.12 měření

[GRAPH||hwBench v.3.12 |]
čtení|náhodná přístupovka|swapping|installing|Word|Photoshop|copying|F-Prot
10815{min. 10786 kB/s};10914{max. 10914 kB/s}|0,21{min 0,21ms};0,49{max. 0,49}|7640{7640 kB/s}|15331{15331 kB/s}|11300{11300 kB/s}|11108{11108 kB/s}|13069{13069 kB/s}|9740{9740 kB/s}|
[/GRAPH]

HDTach 3 graf rychlosti

HDTach a jemu podobné utility trdošíjně hlásili 10MB/s a ani o mego více. Mohu se domnívat, že to bude hranice karty. Asi rychlost řadiče. Karta byla připojená na IDE kanál a pracovala v DMA režimu.

Závěr

Podle výsledků testů je vidět, že karta není úplně špatná a ve spojení do raid 0 bude podávat naprůměrné výsledku za minimální cenu. Stejně tak bude dobrá pro spouštění portable aplikací. Nehodí se určitě na místa s častým zápisem.

[ENG]

Today, I was thinking of you and bought super cheap (about 15$/2GB) Compact Flash card Speedy 2GB by A-Data. I was wondering how this shitty card is quick.[MORE]

I make some tests with HDtachu, SiSoft Sandra 2007 and super-pimp utility hwBench v3.12. The graphs and results are around. The card is relatively quick in read operations. Writing is disaster. Do not use as write-disc! :) I didn’t disassembly the card so that I don’t know what chip is inside – would be better for more information.

SiSoft Sandra measuring

[GRAPH||Speed (SiSoft Sandra 2007) |Write (kB/s), Read (kB/s)]
file 512B|file 32kB|file 256kB|file 2MB|file 64MB
17;1188|1835;9123|4335;9690|5666;10923|6554;10923
[/GRAPH]

hwBench v.3.12 measuring

[GRAPH||hwBench v.3.12 |]
reading|random access|swapping|installing|Word|Photoshop|copying|F-Prot
10815{min. 10786 kB/s};10914{max. 10914 kB/s}|0,21{min 0,21ms};0,49{max. 0,49}|7640{7640 kB/s}|15331{15331 kB/s}|11300{11300 kB/s}|11108{11108 kB/s}|13069{13069 kB/s}|9740{9740 kB/s}|
[/GRAPH]

HDTach 3 speed graph

As you see, the HDTach says 10MB/s and no more. I think, 10MB/s is construction speed of the card. I tested card on IDE channel with DMA enabled.

Conclusion

The card is good for storage and read-only software. You brought lots of fun for some money. Raid 0 would be good. Never use in write-only apps.

[/ENG]

Větrný víkend

To vám teda povím, to byl víkend zase na hovno. Konečně jsem měl po několika měsících volno a vypadalo to, že když teda bude pršet, tak můžu sedět doma a programovat svoje geniální myšlenky, koukat na filmy a cojávím co ještě jsem nestihnul. No to by ale nebylo normální kdyby se to celý neposralo. V sobotu jsem vstal pěkně zvolna na desátou a venku bylo relativně hezky. Trochu vítr a podmrakem. Ale už v jedenáct se přes naše city, přehnala avizovaná větrná smršť. Kolegyně Kyrila. Docela šrumec. No a potom začala pípat UPSka. Nejsem žádná lamka, a tak mám UPSku vybavenou autobaterií pro případ delšího výpadku. Asi tak po půl hodině pípání jsem se rozhodl ukončit trápení a vše jsem vypnul. A to bylo taky to poslední co jsem ten den udělal. [MORE]

Najednou člověk zjistí, jak neskutečně elektřina ovlivňuje život. Nedalo se dělat nic. Do oběda jsem přemýšlel, že bych možná začal číst, ale tfuj. Potom jsem dostal za úkol, vyrobit bramborovou kaši, a tak jsem za zvuků UPSky mixoval kaši. Krásný pocit, když je všude ticho a tma a mě vrčí mixér. Odpoledne jsem se vrhnul na stále odkládané práce. Vytmelil jsem celý smrchový kout. Utřel si prach a uklidil si. A pak jsem se vrhnul na čištění počítačové bedny. O které jsem věděl, že je slušně zanesená a potřebuje odhumusit.

IHS pryč

A jak jsem tak čistil chladiče, napadlo mě, že konečně sundám rozvaděč tepla z procesoru. Na starém jednojádru jsem tuhle operaci už měl za sebou a po nákupu dvoujádra, jsem si nemohl udělat čas. Měl jsem pastu v šuplíku, zalamovák na polici, stačilo jen opatrně gigantické jádro obříznout a sundat kryt. Trochu jsem se bál, abych nesundal nějaký ty kondíky, co jsou nahusto kolem jádra, a u dvoujádra docela u kraje. Vše se vydařilo a procesor je nahatej. Mimochodem, je to ten procesor, co jsem koupil na eBay Pak už jsem nasadit zpátky chladič, rámeček jsem měl už upravený (snížený) a počkat na proud.

Výpadek trval vcelku slušných 5 hodin. Potom už byly jen takové drobné několikaminutové výpadečky. Z toho jasně plyne ponaučení:

Jedna autobaterie k UPSce nestačí. Počítej s nečekaným.

Pro příště bych mohl vylepšit záložní zdroj o nějaké ty superkondenzátory a solární panel by se taky neztratil. Ve větru mě ovšem napadlo mít nějaký větrný generátor, který je přizpůsoben rychlému větru (100km/h a víc). Klasická větrná elektrárna je pěkná věc, ale tohle by mohlo bejt užitečnější.