Re: Threads and findUsingPrototype
John Abraham <[email protected]> Fri, 6 Nov 2009 20:18:40 -0700
| Newsgroups | gmane.comp.java.orm.simpleorm |
|---|---|
| Message-ID | <[email protected]> |
Thanks for the feedback! Right now the database is responsible for basically 100% of the run time because the main thread (which is actually querying the dataset, not the database) is always faster than the database query thread. So there's no point speeding up findUsingPrototype (used in the main thread) anymore until we get the database query thread working faster. But that could just be because something odd is happening over in SQL Server. For now, we're able to blame Microsoft for our problems. Maybe we'll try HSQLDB. I wasn't aware that it did hybrid disk/memory operations (our 65 million records will NOT fit into memory all at once), and I wasn't aware that it could process .CSV files directly. Those two features together with a potential speed advantage make it look very promising. Our users like .CSV files for the smaller tables. -- John On 6-Nov-09, at 7:19 PM, [email protected] wrote: > Hello John, > > THREADING > > Your threading approach is OK. > > In normal operation, you would have one session per thread, one > thread per session. This can be overridden in special cases, but > normally there are sanity checks to ensure that it is the case. > Sharing a JDBC connection between threads is certainly asking for > deep trouble. > > Queing the SDataSets is a reasonable approach. There are examples in > the LongTransactionTest as to how to detach and reattach SDataSets. > > An alternative would be to simply have two threads, each of which > does the reading and the processing, and then synchronize to ensure > that only one ever does critical processing at a time. Avoids need > for a queue. > > But generally, I would not introduce complex architectures for > maximum gain of only 30%. > > More importantly, can the processing itself be multi threaded? You > have not indicated the application, so hard for me to know. But a > quad core machine might increase throughput by 400%, much better > than 30% improvement. > > One way to go much faster is to use a Java embeded database. HSQL, > for example can be well over 1000% faster than Oracle. Daffodil, H2 > and JavaDB are probably more reliable, have not tested for speed. > But again, if the database is only consuming 30% of your time, then > maybe not worth it. > > And of course Stored Procedures will be much faster where applicable. > > And of course, make sure you are using the "server" JVM to compile > properly. > > FIND USING PROTOTYPE > > findUsingPrototype is deprecated because we do not want people using > it directly, but it is public because it provides a back door from > SSessionJdbc to avoid creating an object. The main method is > find(meta, keys...). > > But we have not found it to be slow -- the overhead of a couple of > temporary objects is negligible. Are you sure that it really is a > significant bottle neck for you? > > We could make a special case of the common case of a single primary > key. But I prefer to avoid special cases unless a significant > performance benefit could be demonstrated. (The changes would mainly > be in SDataSet. Eg. in find() if (keys.count() == 1) > records.get(key); Bit fiddly because HashTable does key.equals(k) > instead of k.equals(key), so the single key case would be quite > different indeed and need to be implemented consistently.) > > (One thing that is slow is the standard Java implementation of > HashMap. It creates an Entry object for each entry instead of using > odd and even slots in the array. In our case the key and the value > are both the same object. If you felt like writing a new HashMap > implementation that could help a bit. But unfortunately it cannot > implement Map, which has the Entry object implicitly built into it > (very bad design of a core element).) > > Hope this helps, > > Anthony > > At 02:56 AM 4/11/2009, you wrote: > > > > > >I tried to post the message below on Oct 30 but I sent it from the > wrong address, so it didn't get through. > > > >Since then, we haven't had any ideas on how to replace > findUsingPrototype, and would welcome any thoughts on it. (It's > deprecated, so there must be some thoughts to be shared...) > > > >However, we have made some progress on understanding the threading. > It seems the design is to have one session per thread, and one (or > zero) session per dataset, and one current dataset per session. Is > that correct? > > > >If that is the design, then we'd like to have two threads that have > their own sessions, that create datasets containing batches of > records. The batches of records (and their associated datasets) > would be disassociated from the session, then put in a queue for the > main thread to process, and ultimately destroy. > > > >We don't want to create sessions for each batch, just datasets for > each batch. So we'd need to create a new dataset for the session > after the current dataset has been disassociated from the session > (haven't figured out how to do this yet.) > > > >We'd appreciate any comments or suggestions on how to replace > findUsingPrototype (it's too slow) and on how to best use SimpleORM > in a multithreaded application. > > > >-- > >John Abraham > ><mailto:jabraham%40ucalgary.ca>[email protected] > > > >************* > >** Original message (that didn't make it to the list on Friday Oct > 30) ** > > > >Hello there. We have been working at speeding up our SimpleORM > project which processes 65 million records in sequence, in about > 4000 batches. We've profiled the code (using hprof) and would like > to do two things now to increase performance: > > > >1) we'd like to spin off two threads to pre-fetch batches of > records (average batch size 65,000,000/4000 = 16,250) and put the > resulting ArrayLists of SRecordInstances in a FIFO queue. That way > we can process previous batches of records off the head of the queue > on a separate processor while the database is engaged fetching the > next batches for the tail of the queue. The Java program spends > about 30% of its time waiting for the database to return the next > batch and even more time (about 8%) for SimpleORM to create the > resulting ArrayList; we might as well ask for a few batches in > advance. Question: is SimpleORM thread safe for this type of > operation? > > > >2) findUsingPrototype is quite slow for repeated finds of > prefetched records: SDataSet.findOrCreate() has to create the > prototype object, then SDataSet.finder() has to populate its fields, > then there is the processing of SRecordInstance.equals() and > SRecordInstance.hashCode() to find the record in the cache. All of > these together are, I think, about 30% of our runtime. Is there a > way to speed this up? I notice findUsingPrototype() is deprecated, > suggesting that someone already has a new plan for how to do this. > For some of our tables we know the underlying data is static, so our > current plan is to build our own faster hashmaps for certain types > of records (especially those with a single integer primary key), and > check our own cache first before checking SimpleORM's cache. But I'd > rather speed up SimpleORM than work around it. > > > >So those are my two questions: 1) Threadsafe? 2) are there already > ideas or bits of code to replace findUsingPrototype() with something > faster? > > > > > > Dr Anthony Berglas, [email protected] Mobile: +61 4 4838 8874 > Just because it is possible to push twigs along the ground with ones > nose > does not necessarily mean that is the best way to collect firewood. > > <aa7a5a8.jpg>