c# - Performance issuses with nested foreach loops -
i don't know if issue i'm facing due nested loops or due else (bad code, large data). let me explain, hope can helps me figure out:-
i'm working on windows phone 8 app. on launch app makes 3 httpclient calls 3 different pages, converts each response (which html) xml json data(obs!!! works fine , no problems this). @ stage want extract data 3 json , combine extracted data new json saved isolatedstorage later. extraction used multiple foreach loops , linq (here think problem). each foreach loop might between 50 , >500 iterations. extraction process takes 2 mins, think much. below can see code snippet code:-
public async task loaddata() { //baseuri definition.... await cookiehandler.getcookies(baseuri); _reqplist=new requestresponse(); await _reqplist.getresponse(baseuri, plist); // first page request xmlconvertor.converttoxml(_reqplist.response); //first page convert xml var phonelistresponse = xmlconvertor.xmlstring; //second , third page request , convert xml var handler = new datahandler(); await handler.phonelisthandler(phonelistresponse); //first page convert json //second , third page convert json var jobject = jobject.parse(handler.phonelistjson); var jcollection = jobject["tbody"]["tr"].children(); //the start of extracting data using (var stream = new memorystream()) using (var streamwriter=new streamwriter(stream)) using (_jsonw = new jsontextwriter(streamwriter)) { var watch = stopwatch.startnew(); _jsonw.writestartarray(); foreach (var item in jcollection) //first foreach loop (100 iteration) using first page { var arr = item.value<jarray>("td"); if (arr == null) continue; _jsonw.formatting = formatting.indented; _jsonw.writestartobject(); _jsonw.writepropertyname("name"); _jsonw.writevalue(arr[0].value<string>()); #region info array _jsonw.writepropertyname("info"); _jsonw.writestartarray(); // extraction _jsonw.writeendarray(); #endregion #region schedule array await schedulearrayasync(item, handler.schedulejson, handler); // method extract data 2nd page #endregion #region current activity curractivityasync(item, handler.curractivitiesjson); // method extract data 3rd page #endregion _jsonw.writeendobject(); } _jsonw.writeendarray(); watch.stop(); var j = watch.elapsedmilliseconds; await streamwriter.flushasync(); stream.position = 0; using (var streamreader=new streamreader(stream)) { var json = await streamreader.readtoendasync(); } } this.isdataloaded = true; } private void curractivityasync(jtoken token, string jstring) method called 1 time { var arr = token.value<jarray>("td"); var personnamearray = arr[0].value<string>().split(','); if (!_owner.contains(personnamearray[0])) return; var jobject = jobject.parse(jstring); var jcollection = jobject["tbody"]["tr"].children(); _jsonw.writepropertyname("current activity"); _jsonw.writestartarray(); foreach (var array in item in jcollection // second foreach loop (almost 60 iteration) let array = item.value<jobject>().value<jarray>("td") array != null && item.children().count() > 1 select array) { _jsonw.writestartobject(); // extraction _jsonw.writeendobject(); } _jsonw.writeendarray(); } private async task schedulearrayasync(jtoken token, string jstring, datahandler handler) // method called 100 times. { var arr = token.value<jarray>("td"); var personnamearray = arr[0].value<string>().split(','); var jobject = jobject.parse(jstring); var trlist = jobject["tbody"]["tr"]; var selectedarray = default(jarray); var weeknumber = trlist.selectmany(tr => tr.selecttokens("td[1].table.tbody.tr", false)) .selectmany(lk => lk.selecttokens("td", false)) .where(j => (!j.hasvalues) && (j.value<string>().contains("v"))) .select(lo => lo.value<string>()) .toarray(); var pstypeone = trlist.selectmany(tr => tr.selecttokens("td[0].a.#text", false)) .where(hashtext => (hashtext.value<string>().contains(personnamearray[0])) && (hashtext.value<string>().contains(personnamearray[1]))) .select(td => td.parent.parent.parent.parent.parent) .toarray(); if (pstypeone != null) { _jsonw.writepropertyname("schedule"); _jsonw.writestartarray(); _jsonw.writestartobject(); _jsonw.writepropertyname("week number"); _jsonw.writevalue(weeknumber[0].remove(0, 2)); _jsonw.writepropertyname("week days"); _jsonw.writestartarray(); foreach (var day in selectedarray) // 7 itereation { if (day.selecttoken("table", false) == null) continue; _jsonw.writestartobject(); _jsonw.writepropertyname("day name"); var dayname = convert.todatetime(day.value<string>("@id").remove(0, 8)); _jsonw.writevalue(dayname.dayofweek.tostring()); _jsonw.writepropertyname("date"); _jsonw.writevalue(day.value<string>("@id").remove(0, 8)); var assignments = day.selecttoken("table.tbody.tr", false); _jsonw.writepropertyname("assignments"); _jsonw.writestartarray(); //foreach loop 2 start or foreach foreach (var assignment in assignments) // between 1 , 5 iterations { //some extractions if (info[0].contains("slotinfo")) //here new webrequests , extractions { await _reqplist.getslotinfopost(info[1]); xmlconvertor.converttoxml(_reqplist.response); addedinfo = xmlconvertor.xmlstring; await handler.infohandler(addedinfo); var jo = jobject.parse(handler.infojson); addedjtoken = jo.selecttoken("td"); // extractions } } else { // code } } //foreach loop 2 end //some code close array } //foreach loop 1 end //some code close array } }
now considering iterations , method calls, can optimize code processing faster less 2 mins?
edit:-
let me give more info pages parsed in begining of code. first of pages belong online schedule site use @ work. don't have api work with. why need parse httpclient htmlresponse , convert xml json.
second each of pages have complex structure combind bad naming. please @ below:-
<tr class="odd"> <td class="user" onmouseover="userinfo('469');" onmouseout="userinfo(0);" onmousemove="moveslotinfo();"> user one</td> // user 1 needed <td id="day-469-2014-03-31" style="vertical-align: top;"> <table class="ss" cellspacing="1"> <tbody> <tr> <td class="as"> </td> </tr> </tbody> </table> </td> <td id="day-469-2014-04-01" style="vertical-align: top;"> // date needed <table class="ss" cellspacing="1"> <tbody> <tr> <td class="as" style="color: #ffffff; background-color: #4040ff;" onmouseover="this.classname=(document.week_vs_doctor.activityid.value==-1?'sd':'sp');slotinfo('177738',false);" onmouseout="this.classname='as';slotinfo(0,false);" onmousemove="moveslotinfo();">kavaul</td> // kavaul needed </tr> </tbody> </table> </td>
obs!!! demo code make point (i know not functional).
even when convert json still in need adjuctment why decided rewrite json according needs. take @ code snippet shows how need it.
[ { "name": "user name", "info": [ { "signature": "un" }, { "group": "group1" }, { "e-mail": "user.name@group1.com" } ], "schedule": [ { "week number": "14", "week days": [ { "day name": "monday", "date": "2014-03-31", "assignments": [ { "assignment name": "aaa", "assignment time": "07:30 - 16:00", "assignment provider": "bbb, 2014-03-07 16:42" }
obs!!! know json data needs closing, make point.
i think more simple using htmlagility pack traverse html httprequest response.
a custom class represent you're final object serializable attribute , when class has been filled call javascript serializer serialize json object(you may use json converter online convert json in custom class can deserialize json custom object without issues , viceversa).
also there's importan thing: data dimension. if you're working few data more faster if work large data require more time have response , more time processed.
may tell page involded , final json object???
Comments
Post a Comment