Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / C# / March 2008

Tip: Looking for answers? Try searching our database.

Evaluate LINQ immediately

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Peter Morris - 05 Mar 2008 21:48 GMT
from line in order.Lines
select new { Number = line.Number, Qty = line.Quantity }

at this point I deactivate my object cache, which is where line.Number and
line.Quantity are read from, so any subsequent attempts to read those
properties will result in an InvalidOperationException.

So to avoid this I need the anonymous objects created immediately so that no
further attempt is made to read the objects' properties.  How would this be
done?

I tried

var lines = select.......;
lines = lines.ToArray();

but that didn't do the trick either.

Can someone tell me how I would achieve this?

Thanks

Pete
Jon Skeet [C# MVP] - 06 Mar 2008 08:35 GMT
> from line in order.Lines
> select new { Number = line.Number, Qty = line.Quantity }
[quoted text clipped - 13 lines]
>
> but that didn't do the trick either.

In what way? That would certainly have executed the query immediately.
(I prefer ToList myself, but...)

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk

Peter Morris - 06 Mar 2008 09:52 GMT
Aha!

It turns out I was getting a null reference exception for two different
reasons.

Reason 01: Lazy evaluation after the object cache was deactivated.
Solution, use ToArray on the result.
Reason 02: AutoInc property on my class.  Solution, don't try to show the
child list unless the parent object has been saved.

#02 is due to the fact that AutoInc properties are assigned by the DB and
are therefore null until the object has been saved.  Because the error
message was the same I mistakenly thought it was the result of the same
error.

Thanks :-)

Pete
Jon Skeet [C# MVP] - 06 Mar 2008 10:16 GMT
> Aha!
>
[quoted text clipped - 10 lines]
> message was the same I mistakenly thought it was the result of the same
> error.

Ah, right. Yes, I can see how that could happen :)

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk

Christopher Van Kirk - 07 Mar 2008 15:45 GMT
>from line in order.Lines
>select new { Number = line.Number, Qty = line.Quantity }
[quoted text clipped - 19 lines]
>
>Pete

Tangentially, have you looked at the performance of LINQ versus a
similar set of customized code? LINQ looked very attractive to me
until I tried to benchmark it in that way.

Signature

Posted via a free Usenet account from http://www.teranews.com

Jon Skeet [C# MVP] - 07 Mar 2008 15:54 GMT
On Mar 7, 3:45 pm, Christopher Van Kirk <chris.vank...@fdcjapan.com>
wrote:

<snip>

> Tangentially, have you looked at the performance of LINQ versus a
> similar set of customized code? LINQ looked very attractive to me
> until I tried to benchmark it in that way.

So you've said before, but with *no* details of what you were trying
to do.

As Frans and I discussed (in the same thread) there are certainly
things you could try to do in LINQ to SQL (it's worth specifying which
flavour of LINQ you mean when talking about it, btw) which would give
bad performance, but dismissing the *whole* of LINQ to SQL performance
as poor is a bad idea, IMO.

Search for LINQ in http://blogs.msdn.com/ricom/ for some concrete
figures about LINQ to SQL performance in specific situations.

Jon
Christopher Van Kirk - 07 Mar 2008 16:49 GMT
>On Mar 7, 3:45 pm, Christopher Van Kirk <chris.vank...@fdcjapan.com>
>wrote:
[quoted text clipped - 18 lines]
>
>Jon

I did two tests. The first, below, ordered a list of ints. The ints
themselves were generated randomly, and in no partcular order.

       private void button1_Click(object sender, EventArgs e)
       {

           int i = 0, count = 1000000;

           IList<int> ints = this.GenerateInts(count),
               linqed = new List<int>(),
               sorted;

           int[] ordinals;

           double orderby,
               firstelement,
               nextelement,
               total,
               sorterQuick,
               sorterHeap,
               sorterMerge,
               sorterInsert;

           orderby = firstelement = nextelement = total = sorterQuick
= sorterHeap = sorterMerge = 0;

           HighPerformanceTimer timer1 = new HighPerformanceTimer(),
               timer2 = timer1.Clone() as HighPerformanceTimer;

           timer1.Start();
           timer2.Start();

           var a = ints.OrderBy( p => p, Comparer<int>.Default );

           timer1.Stop();
           
           orderby = timer1.ElapsedSeconds();

           timer1.Start();

           foreach (int val in a)
           {
               if (i == 0)
               {
                   timer1.Stop();
                   firstelement = timer1.ElapsedSeconds();
                   timer1.Start();
               }
               else
               {
                   if (i == 1)
                   {
                       timer1.Stop();
                       nextelement = timer1.ElapsedSeconds();
                   }
               }
               linqed.Add(val);
               i++;
           }

           timer2.Stop();
           total = timer2.ElapsedSeconds();

           System.Diagnostics.Debug.Print("Passed Linq sort
orderby={0}, firstelement={1}, nextelement={2}, total={3}", orderby,
firstelement, nextelement, total );

           ordinals = Sorter.GetOrdinals(count);
           timer1.Start();
           sorted = Sorter.SortPointers<int>( ordinals, ints,
SortMethod.HugeQuick);
           timer1.Stop();

           sorterQuick = timer1.ElapsedSeconds();
           System.Diagnostics.Debug.Print("Passed quick sort {0}",
sorterQuick);
           
           ordinals = Sorter.GetOrdinals(count);
           timer1.Start();
           sorted = Sorter.SortPointers<int>( ordinals, ints,
SortMethod.Heap);
           timer1.Stop();

           sorterHeap = timer1.ElapsedSeconds();
           System.Diagnostics.Debug.Print("Passed heap sort {0}",
sorterHeap);

           ordinals = Sorter.GetOrdinals(count);
           timer1.Start();
           sorted = Sorter.SortPointers<int>( ordinals, ints,
SortMethod.Merge);
           timer1.Stop();

           sorterMerge = timer1.ElapsedSeconds();
           System.Diagnostics.Debug.Print("Passed merge sort {0}",
sorterMerge);

       }

This produced the following output:

Passed Linq sort orderby=1.36772072165396E-06,
firstelement=0.507163260675607, nextelement=1.70756239620126E-06,
total=0.577546772172414
Passed quick sort 0.459738433186191
Passed heap sort 1.21546727261184
Passed merge sort 0.763105243653448

I took this to mean that an order by operation is about 25% slower via
LINQ than doing a comparable quicksort.

The second test was filtering. The code for this is here:

       private void button2_Click(object sender, EventArgs e)
       {
           int i = 0, count = 1000000;

           IList<int> ints = this.GenerateInts(count),
               linqed = new List<int>();

           double whereclause,
               sortthencustomfilter,
               customfilter;

           whereclause = sortthencustomfilter = customfilter = 0;

           HighPerformanceTimer timer1 = new HighPerformanceTimer();

           timer1.Start();

           var a = ints.Where(p => p > count/2);

           foreach (int val in a)
           {
               linqed.Add(val);
               i++;
           }

           timer1.Stop();
           whereclause = timer1.ElapsedSeconds();

           System.Diagnostics.Debug.Print("Passed Linq where filter:
whereclause={0}", whereclause);

           timer1.Start();
           IList<int> newList = new List<int>();

           for (i = 0; i < count; i++)
           {
               if (ints[i] < count / 2)
               {
                   newList.Add(ints[i]);
               }
           }
           timer1.Stop();

           customfilter = timer1.ElapsedSeconds();
           System.Diagnostics.Debug.Print("Passed filter only in {0},
difference={1}", customfilter, 1-customfilter/whereclause);
       }

and the output here:

Passed Linq where filter: whereclause=0.030069347417103
Passed filter only in 0.018763416394604, difference=0.375995224162012

LINQ is 37% slower at picking out elements from a list was what I got
out of this.

At this point I quit looking at it. For my purposes, losing double
digit percentages off performance just isn't acceptable. I suppose
that might be acceptable to others, though.

Signature

Posted via a free Usenet account from http://www.teranews.com

Jon Skeet [C# MVP] - 07 Mar 2008 17:04 GMT
<snip>

> LINQ is 37% slower at picking out elements from a list was what I got
> out of this.
>
> At this point I quit looking at it. For my purposes, losing double
> digit percentages off performance just isn't acceptable. I suppose
> that might be acceptable to others, though.

It's certainly more than acceptable in most cases for me. How often is
the performance of this sort of code actually a bottleneck for you?
It's almost never a bottleneck for me (or most people, I'd suggest) -
whereas the expressive power LINQ provides is huge.

It shouldn't come as a shock that invoking a delegate is slower than
executing inlined code, really. Try making your filter more general and
then see what happens.

(You might want to see how much of the time is spent adding values to
the list, by the way... using IEnumerable<T> and deferred execution is
often more efficient than buffering the whole result in a list.)

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk


Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.