Anonymní profil Kartmen – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Anonymní profil Kartmen – Programujte.comAnonymní profil Kartmen – Programujte.com

 

Příspěvky odeslané z IP adresy 88.103.206.–

Honza
.NET › grafika GDI vs GDI+
11. 4. 2022   #390133

Díky, večer se na to kouknu. Myslel jsem něco jako https://stackoverflow.com/questions/4080719/placing-images-and-strings-with-a-c-sharp-combobox , kde si obrázek a text umístí podle potřeby. Zrovna toto je příklad, něčeho co jinak nejde, nebo nevim jak. U DataGridViewu nejdou třeba sdílené buňky a následně umístit text svisle na střed lichého počtu řádků (mimo řádek DGV). Mně by se hodil jednoduchý výpis textu, ale ve stylu tabulky (nejlépe DGV vůbec nepoužít, ale třeba jen textbox), ale v textboxu nejde text, natož několik textů umisťovat tak, aby vše ve sloupci začínalo na stejném pixelu. S vlastním vykreslením by to snad šlo, ale na to je právě potřeba znát přesné rozměry textu.

Honza
.NET › grafika GDI vs GDI+
11. 4. 2022   #390129

Je to z .NET Framework 4.8. Ale pochybuju, že by se s Windows.Forms do coru někdo předělával.

Honza
.NET › grafika GDI vs GDI+
11. 4. 2022   #390127

Dál jsem našel v třídě WindowsGraphics

            //
            // DrawText returns a rectangle useful for aligning, but not guaranteed to encompass all
            // pixels (its not a FitBlackBox, if the text is italicized, it will overhang on the right.)
            // So we need to account for this.
            //
            IntNativeMethods.DRAWTEXTPARAMS dtparams = null;
 
#if OPTIMIZED_MEASUREMENTDC       
            // use the cache if we've got it
            if (MeasurementDCInfo.IsMeasurementDC(this.DeviceContext)) 
            {
                dtparams = MeasurementDCInfo.GetTextMargins(this,font);
            }
#endif
 
            if (dtparams == null) 
            {
                dtparams = GetTextMargins(font);
            }
 
            //
            // If Width / Height are < 0, we need to make them larger or DrawText will return
            // an unbounded measurement when we actually trying to make it very narrow.
            //
 
            int minWidth = 1 + dtparams.iLeftMargin + dtparams.iRightMargin;
 
            if( proposedSize.Width <= minWidth ) {
                proposedSize.Width = minWidth;
            }
            if( proposedSize.Height <= 0 ) {
                proposedSize.Height = 1;

Takže si to z fontu nějaký interní margin dopočte.

Honza
.NET › grafika GDI vs GDI+
11. 4. 2022   #390125

Když se podíváš do střev Frameworku, tak interně System.Windows.Forms  používá toto:

        internal override Size GetPreferredSizeCore(Size proposedConstraints) {
            if(FlatStyle != FlatStyle.System) {
                Size prefSize = base.GetPreferredSizeCore(proposedConstraints);
                return AutoSizeMode == AutoSizeMode.GrowAndShrink ? prefSize : LayoutUtils.UnionSizes(prefSize, Size);                
            }
 
            if (systemSize.Width == InvalidDimensionValue) {
                Size requiredSize;
                // Note: The result from the BCM_GETIDEALSIZE message isn't accurate if the font has been
                // changed, because this method is called before the font is set into the device context.
                // Commenting this line is the fix for bug VSWhidbey#228843.
                //if(UnsafeNativeMethods.SendMessage(hWnd, NativeMethods.BCM_GETIDEALSIZE, 0, size) != IntPtr.Zero) {
                //    requiredSize = size.ToSize(); ...
                requiredSize = TextRenderer.MeasureText(this.Text, this.Font);
                requiredSize = SizeFromClientSize(requiredSize);
 
                // This padding makes FlatStyle.System about the same size as FlatStyle.Standard
                // with an 8px font.
                requiredSize.Width += 14;
                requiredSize.Height += 9;
                systemSize = requiredSize;
            }
            Size paddedSize = systemSize + Padding.Size;            
            return AutoSizeMode == AutoSizeMode.GrowAndShrink ? paddedSize : LayoutUtils.UnionSizes(paddedSize, Size);
        }

Ale tak jako vždy je ten kód téměř nekonečný chain metod, které dřív nebo později stejně volají nějaké dll, takže vytahnout z toho něco je peklo.

Honza
.NET › grafika GDI vs GDI+
11. 4. 2022   #390123

#40 JerryM
To řešení, kdy se pomocí podtržítek ty mezery odfiltrují bylo někde (nejspíš na stackoverflow) nejlépe hodnocené řešení, ale možná máš lepší. Problém je, že té funkci na měření předáváš jen string a font, tam nikde margin/padding nevidim. Měl by tedy vyjít rozměr viditelných pixelů stejný jako je text zobrazený třeba pomocí Labelu? Neměřím prostor pro text v controlu, ale měřím jen od prvního viditelného pixelu textu do posledního, což vyjde dobře pokud se odstraní ta anonymní mezera. O samotný control nejde, to je jen něco co mi text vykreslí, abych ho mohl kontrolně oměřit, je jedno jaké hodnoty má margin/padding, to text jen nějakým směrem posune, ale viditelná oblast pixelů textů je stále stejná. 

Honza
.NET › grafika GDI vs GDI+
11. 4. 2022   #390121

Možná ještě takhle: počáteční záhada byla, proč funkce z obou typů rendererů vrací jiný počet pixelů šířky než kolik jinak opravdu má ten Label s textem "AAAAA". Teď už vim, že za to můžou mezery před a za textem, než že by bylo něco špatného na použité funkci.

Honza
.NET › grafika GDI vs GDI+
11. 4. 2022   #390120

Tak téma začalo dotazem GDI vs GDI+, což jsem konečně pochopil jak to je. Přesné měření textu záleží na rendereru, což je souvislost s GDI/GDI+. DataGridView byla podotázka na konkrétní použití, stejně jako Label používají v rámci Window Forms stejný renderer. Třeba to použiju na něco komplikovanějšího, kde si overloadnu vykreslovaní nějakého controlu, nebo části. Proč to musíš řešit na co to kdo použije, nebo jestli vůbec, tak min. je dobré aspoň trochu vědět jak to interně funguje.

Honza
.NET › grafika GDI vs GDI+
10. 4. 2022   #390117

#34 JerryM
Jenom z tebe, by ses po těch fóréch jinak proklatě nudil. 

Honza
.NET › grafika GDI vs GDI+
9. 4. 2022   #390113

#29 JerryM
To si asi trochu mimo, koukni se na ten kód metody výše. Tam jde přeci jako parametr jen string a font, o nějakém Marginu to nemá ani páru.

Honza
.NET › grafika GDI vs GDI+
9. 4. 2022   #390112

#24 JerryM
Jsem psal, že to za mě ten sloupec spočte sám, ale lepší je metoda GetPreferredWidth. Měl jsem to nastavené jak píšeš, ale tam to funguje jen pokud se sloupce do DataGridViewu vejdou a nevěděl jsem jak nezávisle na tom jak je šířka DataGridViewu zrovna nastavena (stačila pro všechny sloupce, nebo ne) zjistit potřebnou šířku, která se nemusí shodovat s nastavenou a naopak až podle těch šířek nastavit DataGridView.

Jinak ono to má tu možnost přizpůsobovat šířku aktuálně zobrazeným buňkám, to musim vyzkoušet jak to vypadá.

Honza
.NET › grafika GDI vs GDI+
9. 4. 2022   #390109

#22 BDS
label.Text = "AAAAA";

Spíš jsem to chtěl nějak zkontrolovat, což se dělá blbě, když to vrací jiný rozměr než má viditelná oblast textu. Vždy to bylo větší, protože to na začátek a konec vkládá nějakou mezeru.

Na to co chci teď je to asi jedno, ale pokud je potřeba třeba text v nějakém místě zalomit (na konci řádku), tak mi přijde lepší rozložit text na slova a postupně připočítávat slova a ' ' bez těch mezer navíc. Než testovat stále delší část stringu včetně mezer.

Honza
.NET › grafika GDI vs GDI+
9. 4. 2022   #390105

#21 JerryM
Potřebuju to teď nějak rychle "odfláknout", jestli to poběží pomalu nevadí. Hlavně napsat co nejméně kódu a spíš použít něco hotového. Zatím zkusím nepoužívat hned celý DataGridView, ale jen jeho sloupec, který za mě max. šířku spočte a podle jednotlivých sloupců nastavit rozměr DataGridView a padla :)

Napadá mě ale jestli jste někdo neviděl, nebo si nedokážete představit tabulku, která rozděluju šířku mezi sloupce podle aktuálně viditelného obsahu? Při scrolování by se tedy šířky sloupců měnily podle toho co je zrovna ve viditelné oblasti, celkové okno by mělo pevný rozměr. Byl by to moc velký chaos? Jsem něco takového asi nikde neviděl.

Honza
.NET › grafika GDI vs GDI+
9. 4. 2022   #390101

#17 BDS
Líp by měl vždy vypadat GDI+, nebo ne?

Honza
.NET › grafika GDI vs GDI+
9. 4. 2022   #390100

Já aspoň myslím, že potřebuju měřit text, abych docílil toho, že např. controlu DataGridView následně podle toho nastavim šířku. Normálně to funguje opačně, je nějak nastavena šířka a vnitřní logikou se obsah vykreslí. Třeba to i samo dokáže nastavovat jednotlivé šířky sloupců podle obsahu (podle nejširšího textu ve sloupci), ale jen do limitu daného celkovou velikostí controlu. Mým způsobem bych šířku sloupců spočetl sám, podle toho nastavit celkovou šířku controlu a na pevno nastavit i jednotlivé šířky sloupců. Následně podle velikosti controlu nastavit velikost okna formuláře. Zjednodušeně se ve výsledku vykreslí okno, ve kterém je vidět celý obsah všech sloupců.

Windows mají možnost volby mezi výkonem a vzhledem, možná to taky souvisí s tím jaký renderer se používá, ale nic jsem k tomu nenašel. Jen, že systém má k dispozici GDI, GDI+ a DirectX.

Honza
.NET › grafika GDI vs GDI+
8. 4. 2022   #390097

#14 JerryM
1) Já bych rád ale to není na mě, zatím jsem neprotlačil ani aby se do databázi nezapisovala čísla ID jako string (navrch unicode).

2) Při servisování existujících kódů spočívající v odstranění chybky, malém vylepšení atd. to nemá cenu celé přepisovat.

Honza
.NET › grafika GDI vs GDI+
8. 4. 2022   #390094

#12 gna
Díky za odpověď.

Ještě mam dotaz ohledně systému Windows.., ten myslim od XP používá GDI+ a tedy UseCompatibleTextRenderings(true) znamená renderování shodné se systémem?

Honza
.NET › grafika GDI vs GDI+
8. 4. 2022   #390092

Našel jsem něco co není ideální, ale aspoň nějak to ve starém dobrém System.Windows.Forms funguje.

int sirkaPodtrzitek = TextRenderer.MeasureText("__", label.Font).Width;
int sirkaSpatne = TextRenderer.MeasureText( label.Text , label.Font).Width;
int sirkaPresne = TextRenderer.MeasureText("_" + label.Text + "_", label.Font).Width - sirkaPodtrzitek;
Honza
.NET › grafika GDI vs GDI+
8. 4. 2022   #390091

#9 JerryM
Neobvyklé úplně ne, respektive na netu je dost diskuzí kde se to řeší, ale nic co bych považoval za dokonalé.

Tu rychlost jsem psal jako údajný důvod vývoje GDI+, jinak mě netrápí. UI mam v GDI, nebo GDI+, tak to prostě musim použít. Také nevim jestli jste někdo řešil třeba "zalamování" textu a počítání výšky řádku sloučené buňky v Excelu. Aspoň v mojí verzi Excelu jsem na to nic rozumného, tedy přímo pomoci API nenašel a opět co jde ohledně toho najít na netu se točí kolem těchto tříd.

Honza
.NET › grafika GDI vs GDI+
8. 4. 2022   #390089

#3 JerryM
Žádnou komplikovanou grafiku nepotřebuju, vlastně zatím hlavně něco co dobře spočte délku textu. Tedy jestli pomocí TextRenderer.MeasureText, nebo třída Graphics instance.MeasureString. Ale ani jedno neodpovídá měření, nejspíš proto, že obojí připočítává i nějaké pixely před a za textem. Nevíte někdo jaký algoritmus to používá?

Honza
.NET › grafika GDI vs GDI+
8. 4. 2022   #390088

#5 gna
Takže tím je to divný, nejprve používali novější GDI+ a pak kvůli kompatibilitě přešli na GDI?

Další divné věci jsem četl ohledně důvodu vývoje GDI+, kde píšou kvůli rychlosti, ale co jsem viděl testy tak je GDI rychlejší, ale zase GDI+ vypadá lépe, protože používá různé efekty (další důvod je, že není hardwarově akcelerované).

Honza
.NET › grafika GDI vs GDI+
7. 4. 2022   #390081
Kartmen
.NET › Formy a vlákna
15. 5. 2021   #387927

1) Jal jsem psal, jde o příklad jak, navíc v MessageBoxem jsem tabulky nikdy nezkoušel vypsat.

2) Psal jsem, že je to něco jako ErrorProvider, což je child okno, kde se vypíše nějaký seznam událostí. Je to komponenta, tedy něco co se dá použít na libovolném místě, není to samotný program, spíš něco co bude v nějaké knihovně, kterou program použije. Nikde jsem nepsal o vytváření formulářů mimo designer, opět jako ErrorProvider, se při použití zadá nějaký control z libovolného UI a v nějakém odstupu od něj se do tohoto UI doplní PictureBox (tento jeden si to tedy vytvoří samo mimo designer), který se v případě, že je v zapsána nějaká událost zobrazí.

Uživatel této třídy (formu) nemusí používat přímo vlákna, klidně může používat pohodlnější tasky.

Neprováděj jsem nějaký sofistikovaný dlouhodobý test, ale za pomocí dvou různých locků to nyní funguje, ale není to moc pěkné, takže řeším jestli to jde líp.

Co je na locku špatného?

Stejně tak co je špatného na těch starých formulářích? Co jsem koukal na zdrojové soubory technologie, které je za mě napsána dost dobře, tedy od základu v C++ pro jednotlivé typy procesorů, s podporou více vláken a až vyšší objekty v C#, tak forms tam mají také ty staré (jen používají dědičnost). Je to soft co pracuje s 3D grafikou, takže spousta komplikovaných výpočtů. Možná to jen vyvíjejí delší dobu (každý měsíc několik updatů) a staré věci se jim nechce přepisovat, kdo ví.

Požití Sleepu mi přijde nesmyslné, tím nejde na nic čekat, nevím přeci jestli operace bude trvat 10ns, nebo 1s, od toho jsem tam ty locky, že to čeká tak dlouho, dokud se neuvolní.

Je to teprve druhá věc co jsem s vlákny kdy dělal a v práci to ani nepotřebuju, spíš zvídavost. Prvně jsem zkoušel obecnou třídu pro výpočty pomocí vláken. Třída má svůj zásobník akcí a postupně je umisťuje podle priorit na vlákna tak, aby byla stále vytížená a tam to invokuje akce ze zásobníku. Co jsem zkoušel udělat pomocí toho pro kontrolu třeba HeapSort, tak to má i na milionech prvků stejný výsledek, jako řazení co je ve frameworku. Požívá to také jen locky a ManualResetEventy

3) Dělam si to složitý, ale bojuju s tím :) Cože oni se prací dají peníze i vydělat, já jim za to ještě platím :)

Co o tom vím, tak system ma svůj ThreadPool, pokud se používají Tasky, tak na to systém použije vlákno odsud, pokud tam není, tak vytvoří nové. Pokud si program vytvoří svá vlákna, tak jsou mimo, ale asi by tam šla dát, nikdy jsem to nepotřeboval. Na počtu vláken moc nezáleží, běžně ve windows běží mnohem větší počet vláken než kolik vláken má procesor a systém si sám řídí, jaké vlákno kdy obslouží, částečně to jde snad ovlivnit nastavenou prioritou vlákna. Pro jistotu jsem ale dělal o jedno vlákno méně než kolik jich procesor má.

Kartmen
.NET › Formy a vlákna
15. 5. 2021   #387923

#5 JerryM

Jak jsem psal, tak já WPF používal, ale ve firmě se nepoužívá, proto jsem se ptal v čem jsou ostatní novější věci lepší, já v tom moc rozdíl nevidím. Dotaz byl tedy spíš na ty rozdíly než na vlákna, třeba se mi pak WPF podaří spíš protlačit...

Dotaz ohledně DataGridViewu jako Excel se pokusím namalovat.

Připojen obrázek.

Pokud nerozumíš původnímu dotazu, tak jo nenapsal jsem to moc detailně, jestli že to snad někdo, kdo se s tím setkal pochopí, ale klidně to víc rozepíšu, jen aby pak zase někdo četl dlouhý text.

Kartmen
.NET › Formy a vlákna
15. 5. 2021   #387922

#3 gna
Radši jsem dal i ten konstruktor na vlákno UI. Přišlo mi, že když to tak nebylo, tak se děly divné věci, jako třeba form.InvokeRequired hlásil false i pro jiná vlákna než bylo to UI. Taky mě vrtá v hlavě, jaký je asi rozdíl v podmínkách 

if (this.InvokeRequired) //this je form
  this.Invoke(...);

vs

if (_vlaknoUI != Thread.CurrentThread.ManagedThreadId) //_vlaknoUI je v konstruktoru formu zapsane ID
  this.Invoke(...);

S tou frontou by byla práce navíc, ale teoreticky by se neblokovala vlákna a mohla pokračovat v práci minimálně do zahlcení fronty.

Jak teď s vláknama začínam, tak hledam nějaký vzor, nebo šablonu, jak to do budoucna dělat a pokud možnost, aby to nepřidávalo kódu navíc, šlo se v tom vyznat a fungovalo to. Aktuálně dělam něco jako ErrorProvider jen trochu lépe nastavitelný než je v těch starých formulářích. Tedy libovolné vlákno může poslat info o události a můj form ji zobrazí, přičemž vše kromě samotného Invoku třeba se zápisem do TextBoxu se děje na jiném vláknu a ostatní vlákna musí čekat než se předchozí akce dokončí.

 Příklady akcí, které běží na libovolném vláknu, které pouze pro zápis do controlů používají invoke a aby se nemíchaly invoky různých akcí, tak je tam lock. Fungovalo by to bez locků, pokud by se invokovali rovnou celé ty metody, ale pak to byl jednovláknový program. 

    private void AkceZapisText(List<string> text)
    {
      lock (_akceLock) //dokud neprobehne cely cyklus, tak nesmi zacit jina akce
      {
        foreach (var item in text)
        {
          //...
          Form.Invoke(delegateZapisDoTextboxu, item); //logika okolo je v nejakem vlaknu, jen samotny zapis se invokuje
          //...
        }
      }
    }

    private void AkceSeradSeznam()
    {
      lock (_akceLock) //dokud neprobehne cely cyklus, tak nesmi zacit jina akce
      {
        Form.Invoke(delegateOdstranZapsane); //stavajici seznam odstrani
        List<string> razene = _seznam.Sort(); //nejake serazeni dat
        foreach (var item in razene) //zapis serazeneho seznamu
        {
          //...
          Form.Invoke(delegateZapisDoTextboxu, item); //logika okolo je v nejakem vlaknu, jen samotny zapis se invokuje
          //...
        }
      }
    }
Kartmen
.NET › Formy a vlákna
13. 5. 2021   #387895

Po nějakém čase zase velký problém.. Pokouším se napsat Form, který by fungoval i v případě přístup z více vláken. Nevím určitě, ale asi je nutné vytvářet všechny Controly přímo ve vlákně kde vznikl Form, tedy konstruktory musí být ve stejném vlákně? Nebo stačí do formu control jen zapsat (Controls.Add) ve stejném vláknu, ale může vzniknout i mimo?

Další problém ale je když vlákna něco odešlou... Jestli jen pomocí locku zajistit, aby probíhala jen jedna akce a posílat Invokem do hlavního vlákna UI to co mění data controlů, nebo radši udělat nějaký zásobník, kam se všechny akce budou zapisovat a Invokovat je až ze zásobníku.

Nejhorší mi přejde ukončení, kdy se něco může právě invokovat, další vlákna čekají na dokončení a přednostně chci všechny akce (tu co probíhá i ty čekající) ukončit a provést ukončení (zavření formu). Problémem tu je, že v hlavním vlákně UI nelze použít žádný lock, nebo jiný způsob čekání na dokončení (ukončení) probíhající akce, protože na tomto vlákně probíhají invoky, což by vedlo deadlocku. Řešil jsem to tak, že jsem ukončení spustil na jiném vlákně a tak čeká na lock, jako ostatní vlákna a jejich akce, které mají signalizováno předčasné ukončení... ale nepřijde mi to moc pěkné, tak jestli není nějaké lepší řešení.

Kartmen
.NET › Knihovna jen z v aktuálním p…
2. 10. 2020   #386731

Ještě jeden důvod mě napadá, občas se stává, že se zákazníkovi dává i zdrojový kód.

Díky za pomoc.

Kartmen
.NET › Knihovna jen z v aktuálním p…
2. 10. 2020   #386726

#5 hlucheucho
To ruční přidávání už dá práci a co teprve řešit nějaké chainy, kdy třída závisí na jiných a ty na jiných... a ani celé třídy nebudou většinou použité. Pokud mají spoustu metod a všeho možného, tak se při použití třídy využívá jen něco málo.

Ber to jako filozofickou otázku, ale začal jsem to řešit, protože mam svou knihovnu, která stále roste a přitom z ní často používam jen zlomek. Jasně šla by rozložit na několik souborů a to už zase není tak pohodlné, stále přemýšlet co je v jaké knihovně. O místo až tak nejde, i když je trochu prasárna z programu co může mít 1MB udělat 100 jen proto, že tam připlácnu spoustu knihoven.

Něco takového by také bylo řešení, aby si sám kompilátor vytahnul jen co potřebuje.

Kartmen
.NET › Knihovna jen z v aktuálním p…
2. 10. 2020   #386720

#2 JerryM
Mam jeden velký hotový projekt, ve kterém je dejme tomu několik tisíc tříd.

Pak mam druhý projekt, na které aktuálně dělam a občas nějakou třídu, metodu, nebo cokoliv z toho velkého projektu použiju a chtěl bych, aby to z toho velkého projektu vycuclo všechen kód, který je nezbytný a jen z toho kódu aby to udělalo knihovnu. Ten druhý, pracovní projekt je něco co se stále mění, podle toho na čem právě dělám, takže pokaždé použiju z velkého projektu jiné části. Normální je udělat z velkého projektu knihovnu, která bude mít několik mega a neřešit, že aktuálně jsem z ní použil 10 řádků kódu. Já se ptam, jestli existuje něco, co by na základě použití dokázalo udělat knihovnu jen z těch 10 řádků.

Kartmen
.NET › Knihovna jen z v aktuálním p…
30. 9. 2020   #386711

Ahoj, je to asi dotaz spíš na Visual studio. Nevíte jestli existuje typ projektu, nebo nějaký způsob, jak by šlo používat něco jako referenční projekt, ze kterého by se po použití nějaké jeho části v "normálním" projektu automaticky překopírovalo vše co je potřeba do projektu, na kterém právě dělám? Něco čím bych se vyhnul ručnímu kopírování, nebo naopak zbytečné používání knihovny, ze které je použito pár řádků kódu. Nebo kdyby šlo vytvořit knihovnu, kde bude jen to co se v projektu opravdu používá.

Kartmen
MS SQL › Import co nejrychleji
22. 9. 2020   #386658

Úplně to nesouvisí s tou databází, ale když měřím čas průběhu přes System.Diagnostics.Stopwatch, který spustím před metodou importu a stopnu to za ní, tak to ukazuje, že ta metoda zabere 30% času. Zatímco Performance profiler CPU, ukazuje že ta metoda má 80% vytížení. Takže mezi tím úplně vztah asi není co? Ta metoda asi jen víc vytěžuje procesor (procesory).

Kartmen
MS SQL › Import co nejrychleji
19. 9. 2020   #386652

Ano začínam, ale jak jsem psal, vycházím z existujícího kódu, který snad můžu jen zlepšit, respektive pokud to bude ještě pomalejší, tak můžu nechat ten původní. Vstupní soubor což je export z nějaké databáze, je členěn do těch 100 tabulek. Do toho jak mají vytvořenou tu databázi nevidím, interně to může být mnohem víc tabulek. Evidentně to nikdo moc neřešil a rovnou z toho udělal jednu tabulku, takže normalizováno to není vůbec. Musím zjistit jaká je návaznost dalších programů, které s importovanou databází pracují, ale nejspíš budou vyžadovat buď ty původní kompletní tabulky, nebo předělat kód pokud bych to rozdělil (a nevytvořil z nich opět tu původní). To jestli bude interně databáze přehlednější tedy možná nikdo (uživatel) ani nepostřehne pokud k ní přistupuje přes nějaký program a jeho UI, ale to jestli se to bude importovat 5 minut, nebo hodinu ano.

Kartmen
MS SQL › Import co nejrychleji
19. 9. 2020   #386648

Jasný a databáze bude asi i o dost menší. Má to asi 100 tabulek, které mají tak 20-50 sloupců.

Kartmen
MS SQL › Import co nejrychleji
19. 9. 2020   #386646

Už to asi chápu, rozložit velkou tabulku na několik menších?

Kartmen
MS SQL › Import co nejrychleji
19. 9. 2020   #386645

Být to v mém kódu, tak bych asi zkusil udělat hash všech sloupců a až při shodě hashe testovat na shodnost jednotlivé sloupce. V databázi nevim, ale možná to přesně tak dělá.

Kartmen
MS SQL › Import co nejrychleji
19. 9. 2020   #386644

#19 Kit
Já to nevymýšlel, jen se to snažím přepsat, aby to fungovalo trochu rychleji. Jak by to šlo vyřešit lépe? Mě napadlo, že zkusím ty sloupce klíče aspoň přeházet, aby byl pokud možno první ten (ty), ve kterých je největší šance, že se budou lišit. Další sloupce se pak už snad ani nebudou testovat.

Kartmen
MS SQL › Import co nejrychleji
19. 9. 2020   #386641

Po pár testech bych řek, že je pomalost dána složitostí databáze. Některé unikátní klíče tvoří 6 a asi i více sloupců. Na začátku to běží rychle, ale jak se přidávají data a testuje se unikátnost, tak to zpomaluje.

Pár dotazů:

1) Je lepší narvat co nejrychleji data do databáze a až je v ní vše, tak teprve otestovat unikátnost, nebo to dělat v průběhu, nebo je to jedno a trvá to vždy cca stejnou dobu?

2) Nastavení tabulky je stejné pro všechna připojení, nebo by šlo, aby jednotlivá připojení měla různé třeba defaultní hodnoty sloupců?

Kartmen
MS SQL › Import co nejrychleji
2. 9. 2020   #386557

Jaké optimalizace myslíš? Napadá mě jen zapnout optimalizace v nastavení projektu VS, což nemá žádný vliv, protože v naprosté většině kód běží v externí části (knihovna frameworku kde je SqlBulkCopy). Pak snad jedině přepsat tu knihovnu.

Padlo tu, že by import měl jít prakticky rychlostí čtení... a na to, že se v mém případě už jen čte z paměti a zapisuje do databáze, tak je to teď cca 3MB/s (pokud počítám plnou velikost řádku databáze, řada sloupců je null, nebo jsou texty výrazně kratší než je limit, takže ze zdroje jde cca 1,5MB/s).

Kartmen
MS SQL › Import co nejrychleji
1. 9. 2020   #386551

Asi by taky šlo kontrolu spustit až nakonec, ale přijde mi jestli to není zbytečně složitější, i když to bude databáze na počítači, na kterém je spuštěný program, tak se to nejprve importuje a pak zase exportuje, přijde mi to jako krok navíc a pokaždé se to musí parsovat mezi C# typy a SQL.

Rozdělit to jde, jen je to trochu složitější. Právě jsem zjišťoval jsem jestli to má cenu, jestli je to opravdu rychlejší, když to běží ve více vláknech, protože mi pár lidí tvrdilo že ne. Každopádně to otestuju.

Nevím jak otestovat jestli těch cca 8000 řádků/s je normál, nebo je to bída. Možná je problém v nějakém nastavení databáze.

Kartmen
MS SQL › Import co nejrychleji
1. 9. 2020   #386541

To co jsem posílal bylo bez kontrol (jsou vypnuté), jediné co se tam děje je parsovaní ze stringu. Co jsem testoval, tak to jestli pošlu sql typy, nebo string a ať si to naparsuje databáze, tak překvapivě vyšlo prakticky na stejno.

Drtivá většina testů nesouvisí s tím jestli to proleze do databáze, nebo ne. Třeba řetězec, pokud má správnou délku proleze vždy, ale měl by "dávat smysl", ve výsledku se do databáze často stejně pošle, ale zaloguje se podezřelá hodnota.

Kartmen
MS SQL › Import co nejrychleji
1. 9. 2020   #386539

Vložení prvních 100 000 řádků jako je ten níže do tabulky na mém core i7-4790 3.6GHz trvá 13s, je to odpovídající?

      //object[] _data 
      _data[0] = SqlDecimal.Parse("12345678901"); //9x numeric
      _data[1] = SqlDecimal.Parse("12345678901"); 
      _data[2] = SqlDecimal.Parse("12345678901"); 
      _data[3] = SqlDecimal.Parse("12345678901"); 
      _data[4] = SqlDecimal.Parse("12345678901");
      _data[5] = SqlDecimal.Parse("12345678901");
      _data[6] = SqlDecimal.Parse("12345678901");
      _data[7] = SqlDecimal.Parse("12345678901");
      _data[8] = SqlDecimal.Parse("12345678901");
      _data[9] = SqlDecimal.Parse("12345678901"); 
      _data[10] = SqlDateTime.Parse("2014.12.11 06:32:38"); //2x datatime
      _data[11] = SqlDateTime.Parse("2014.12.11 06:32:38");
      _data[12] = SqlInt16.Parse("0"); //11x smallint
      _data[13] = SqlInt16.Parse("0"); //unikatni 0
      _data[14] = SqlInt16.Parse("0"); //unikatni 0
      _data[15] = SqlInt16.Parse("0"); //unikatni 0
      _data[16] = SqlInt16.Parse("0"); 
      _data[17] = SqlInt16.Parse("0"); 
      _data[18] = SqlInt16.Parse("0"); 
      _data[19] = SqlInt16.Parse("0"); 
      _data[20] = SqlInt16.Parse("0"); 
      _data[21] = SqlInt16.Parse("0"); 
      _data[22] = SqlInt16.Parse("0");
      _data[23] = SqlInt32.Parse("123456"); //4x int
      _data[24] = SqlInt32.Parse("123456"); 
      _data[25] = SqlInt32.Parse("123456"); 
      _data[26] = SqlInt32.Parse("123456"); 
      _data[27] = new SqlChars("x"); //5x nvarchar, delka 10 
      _data[28] = new SqlChars("x"); //delka 100
      _data[27] = new SqlChars("x"); //delka 1
      _data[29] = new SqlChars("x"); //delka 1
      _data[30] = new SqlChars("x"); //delka 1
Kartmen
MS SQL › Import co nejrychleji
31. 8. 2020   #386537

#6 Kit
To jsem nepobral můžeš to trochu rozvést?

Kartmen
MS SQL › Import co nejrychleji
31. 8. 2020   #386533

Myslel jsem, že to stačí obecně, jestli je paralelní import rychlejší a následně to používat na libovolné databáze. Třeba teď mam nějaké, které mají od 100MB, průměr je asi pár giga, ale jsou i terabytové. Struktura je celkem jednoduchá, ale ve všem může být chyba, takže se to před importem testuje, jestli je číslo číslo, datum jestli dává smysl atd, ale to bych neřešil to se provede v jiném vlákně. Výsledek zatím podle CPU profileru VS je, že 80% času trvá externí kód třídy SqlBulkCopy metody WriteToServer pomocí datareaderu. 

Kartmen
MS SQL › Import co nejrychleji
29. 8. 2020   #386531

Omezení hard diskem tu bude, ale i tak je v nastavení řada parametrů, které to nejspíš mohou ovlivnit a které potřebuji nějak optimálně nastavit. Třeba zápis na disk nevím jestli databáze musí nutně dělat v reálném čase, pokud má počítač dost paměti (víc paměti než jak je velká databáze), tak by teoreticky nemusela. Nicméně z disku se načítá soubor s daty, která se do databáze zapisují. Pokud bych načetl databázi rychlostí čtení z disku, tak by mi to pro začátek stačilo :)

Kartmen
MS SQL › Import co nejrychleji
28. 8. 2020   #386529

Ahoj, chtěl bych se zeptat jak co nejrychleji načítat opravdu velké databáze. Moje představa byla, že pro zápis do databáze využiju všechna vlákna procesoru, ale co jsem se z několika zdrojů doslechl, tak to nemá moc cenu a ani to nemusí být rychlejší... je to opravdu pravda? Liší se nějak jednotlivé databáze MS SQL, MySQL, PostgreSQL a další v možnostech urychlení importu? Nebo je pro urychlení lepší zapisovat do několika instancí databáze, protože na současný zápis z více vláken nejsou dělané?

Kartmen
.NET › návrh třídy
17. 8. 2020   #386447

#2 Kit
To byl jen příklad, respektive ona ho klidně může jen načítat, ale nějak se parsuje vstupní formát a nějak se z dat vytváří objekty, nebo se to jen zapíše do databáze. Jde spíš o to, jestli třída určená k jedinému účelu, má (může) to co dělá udělat hned v konstruktoru, nebo jestli má mít spíš nějakou metodu, které to spustí, nebo je to jedno. 

  public class ImportDat
  {
    internal readonly string _nazevSouboru;
    //rada readonly promennych tridy
    //...
    //...
    //...

    public ImportDat(string nazevSouboru)
    {
      _nazevSouboru = nazevSouboru;
      //... treba i delsi kod importu

    }

  }

Vše v konstruktoru, respektive i z něj volám jednotlivé metody, ale už je to delší... Výhody jsou, že vnitřní proměnné třídy mohou použít atribut readonly a kdo bude třídu používat, tak jen vytvoří objekt, nemusí už hledat jakou metodou to ještě spustit.

  public class ImportDat2
  {
    internal readonly string _nazevSouboru;
    //rada promennych tridy
    //...
    //...
    //...

    public ImportDat2(string nazevSouboru)
    {
      _nazevSouboru = nazevSouboru;
    }

    public void Spust()
    {
      //... kod importu
    }

  }

Nebo je čistější udělat maximálně jednoduchý konstruktor a delší kód mít až v metodě, která se musí extra volat?

Kartmen
.NET › návrh třídy
17. 8. 2020   #386444

Ahoj, mam dotaz na to jestli existují nějaké zásady, ohledně psaní tříd. Sice je to možná obecnější než jen Net, ale používam teď hlavně ten. Uvítám libovolné postřehy, ale aktuálně mi jde o hlavně o toto. Je špatné, vytvářet složitější konstruktory, spíš než to co třída děla rozložit do metod? Mam například třídu, která dostane nějaké nastavení, kde je např. jen cestu ke zpracovávanému souboru. Je lepší udělat konstruktor, který jen přebere nastavení a pro zpracování souboru je následně nutné zavolat nějakou metodu např. Start? Nebo udělat konstruktor, který přebere nastavení a rovnou zpracuje soubor? Třída samotná jen načítá soubor, nic jiného nedělá.

Kartmen
.NET › Nový C# 9.0 :) pro všechny…
4. 8. 2020   #386422
Kartmen
.NET › Nový C# 9.0 :) pro všechny…
4. 8. 2020   #386419

Je tam něco zásadního bez čeho se člověk neobejde, nebo to aspoň znatelně zrychlí práci? Video mi nejde, asi to v práci blokujou:(

Kartmen
.NET › Vlákna, jak je ukončit
6. 3. 2020   #385600

Ok. Ještě menší dotaz na Visual Studio, neznáte někdo dobrý způsob (Addon), na ladění více vláken, kdy chci sledovat jen jedno, nebo několik vybraných vláken a ostatní ne? Zatím jsem vygoogloval jen nic moc řešení, kdy se dají breakepointy na každý řádek a nastaví se podmínka na thread, který chci ladit. 

Kartmen
.NET › Vlákna, jak je ukončit
5. 3. 2020   #385590

Ahoj, chci si zeptat, jestli existuje nějaká dobrá možnost jak ukončit nejlépe jen proceduru (ne vlákno), která již není potřeba. Mam třeba 10 vláken, které počítají to samé jiným způsobem, když nejrychlejší vlákno spočte výsledek, tak ostatní již není potřeba dopočítávat... Nejradši bych chtěl ukončit jen aktuálně spuštěné akce na vláknech a nahradit je jinými, podobně jako když se vlákno nějakou metodou spustí. Nebo to nelze a je nutné, aby časově náročná procedura sama testovala, jestli se nemá ukončit? Nebo použit nic moc řešení a Thread.Abort() a udělat si vlákno jiné?

Kartik
Visual Basic › jde ve VBA přímo uvolnit pam…
11. 10. 2018   #381901

Tam ale vidím jen rušení celých objektu, jsem chtěl vědět jestli je možné zrušit jen část objektu, nebo část pole. Respektive jak v těchto případech pracuje garbage collector, např. když vytvořím pole2, jehož data nasměruju na objekt, nebo data jiného pole, tak jestli se při rušení tohoto pole2 opravdu uvolní paměť, nebo jestli si to pohlídá, že stejnou paměť používá ještě něco dalšího.

Kartik
Visual Basic › jde ve VBA přímo uvolnit pam…
10. 10. 2018   #381895

Snažím se udělat funkci, která dostane jako parametry Ukazatel a Size a mela by uvolnit paměť v tomto rozsahu. Chtěl jsem to udělat tak, že vytvořím pole typu Byte správné velikosti a jako ukazatel na data dam parametr Ukazatel. Takže jen prohodím ve struktuře safeArray ukazatel na data. Plán je takový, že jakmile dojde na rušení funkce, ve které je toto pole, tak to uvolní paměť, kterou potřebuju... ale nějak to nefunguje.

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function VarPtrArray Lib "VBE6" Alias "VarPtr" (var() As Any) As Long 

Private Sub test1()

Dim arr() as long
dim nula as long
dim ptr as long

redim arr(10)
...
ptr=VarPtr(arr(8))
CopyMemory Byval VarPtrArray(arr()),nula,4 'pole má nyní ukazatel 0, takže ho VBA nejspíš samo nedealokuje
test2 ptr, 12

end sub

Private Sub test2(ptr as long, size as long)
'tady chci uvolnit paměť, jestli je to nějak možné

dim delArr() as byte
dim arrPtr as long

redim delArr(size-1)
CopyMemory arrPtr, Byval VarPtrArray(delArr()), 4 'ukazatel na strukturu safeArray
CopyMemory Byval arrPtr+12, ptr, 4 'změna ukazatele na data
'a teď by se teoreticky měla po ukončení funkce paměť pole uvolnit... ale nevim jak přesně funguje garbage collector, jestli paměť neuvolní hned, nebo ji to uvolní ale hodnoty tam zůstanou nebo ?

end sub

 

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý