Miniprofiler isn't profiling assignment statements / fast steps - asp.net-mvc-4

I'm using the StackExchange Miniprofiler with ASP.NET MVC 4. I'm currently trying to profile an assignment to a member variable of a class with an expensive expression that generates the value to be assigned. Miniprofiler doesn't seem to want to profile assignment statements. I've simplified my code to highlight the error:
public ActionResult TestProfiling()
{
var profiler = MiniProfiler.Current;
using (profiler.Step("Test 1"))
Thread.Sleep(50);
int sue;
using (profiler.Step("Test 2"))
{
sue = 1;
}
if (sue == 1)
sue = 2;
using (profiler.Step("Test 3"))
{
Thread.Sleep(50);
int bob;
using (profiler.Step("Inner Test"))
{
bob = 1;
}
if (bob == 1)
bob = 2;
}
return View();
}
N.B. the if statements are simply to avoid compiler warnings.
Test 1 and Test 3 get displayed in the Miniprofiler section on the resulting page. Test 2 and Inner Test do not. However if I replace the contents of either Test 2 or Inner Test with a sleep statement they get output to the resulting page.
What is going on here? Even if I replace the simple assignment statement inside one of the non appearing tests i.e.
using (profiler.Step("Test 2"))
{
ViewModel.ComplexData = MyAmazingService.LongRunningMethodToGenerateComplexData();
}
with a more complex one, the Test 2 step still doesn't get output to the rendered Miniprofiler section. Why isn't Miniprofiler profiling assignment statements?
Edit: code example now corresponds to text.
Edit2: After further digging around it seems that the problem isn't with assignment statements. It seems that whether something gets displayed in the output results is dependent on how long it takes to execute. i.e.
using (profiler.Step("Test 2"))
{
sue = 1;
Thread.Sleep(0);
}
Using the above code, Test 2 is not displayed in the Miniprofiler results.
using (profiler.Step("Test 2"))
{
sue = 1;
Thread.Sleep(10);
}
Using the above code Test 2 is now displayed in the Miniprofiler results.
So it seems my LongRunningCodeToGenerateComplexData turns out to be quite quick... but is it expected behaviour of Miniprofiler to not show steps that take a really small amount of time?

Just click on "show trivial" on the bottom right of the profiler results.
this should show all actions lesser

It seems the problem was that Miniprofiler isn't displaying results for steps where the execution time is less than 3ms.
Edit: From the Miniprofiler documentation.
TrivialDurationThresholdMilliseconds Any Timing step with a duration less than or equal to this will be hidden by default in the UI; defaults to 2.0 ms.
http://community.miniprofiler.com/permalinks/20/various-miniprofiler-settings

Related

Slick plain sql query with pagination

I have something like this, using Akka, Alpakka + Slick
Slick
.source(
sql"""select #${onlyTheseColumns.mkString(",")} from #${dbSource.table}"""
.as[Map[String, String]]
.withStatementParameters(rsType = ResultSetType.ForwardOnly, rsConcurrency = ResultSetConcurrency.ReadOnly, fetchSize = batchSize)
.transactionally
).map( doSomething )...
I want to update this plain sql query with skipping the first N-th element.
But that is very DB specific.
Is is possible to get the pagination bit generated by Slick? [like for type-safe queries one just do a drop, filter, take?]
ps: I don't have the Schema, so I cannot go the type-safe way, just want all tables as Map, filter, drop etc on them.
ps2: at akka level, the flow.drop works, but it's not optimal/slow, coz it still consumes the rows.
Cheers
Since you are using the plain SQL, you have to provide a workable SQL in code snippet. Plain SQL may not type-safe, but agile.
BTW, the most optimal way is to skip N-th element by Database, such as limit in mysql.
depending on your database engine, you could use something like
val page = 1
val pageSize = 10
val query = sql"""
select #${onlyTheseColumns.mkString(",")}
from #${dbSource.table}
limit #${pageSize + 1}
offset #${pageSize * (page - 1)}
"""
the pageSize+1 part tells you whether the next page exists
I want to update this plain sql query with skipping the first N-th element. But that is very DB specific.
As you're concerned about changing the SQL for different databases, I suggest you abstract away that part of the SQL and decide what to do based on the Slick profile being used.
If you are working with multiple database product, you've probably already abstracted away from any specific profile, perhaps using JdbcProfile. In that case you could place your "skip N elements" helper in a class and use the active slickProfile to decide on the SQL to use. (As an alternative you could of course check via some other means, such as an environment value you set).
In practice that could be something like this:
case class Paginate(profile: slick.jdbc.JdbcProfile) {
// Return the correct LIMIT/OFFSET SQL for the current Slick profile
def page(size: Int, firstRow: Int): String =
if (profile.isInstanceOf[slick.jdbc.H2Profile]) {
s"LIMIT $size OFFSET $firstRow"
} else if (profile.isInstanceOf[slick.jdbc.MySQLProfile]) {
s"LIMIT $firstRow, $size"
} else {
// And so on... or a default
// Danger: I've no idea if the above SQL is correct - it's just placeholder
???
}
}
Which you could use as:
// Import your profile
import slick.jdbc.H2Profile.api._
val paginate = Paginate(slickProfile)
val action: DBIO[Seq[Int]] =
sql""" SELECT cols FROM table #${paginate.page(100, 10)}""".as[Int]
In this way, you get to isolate (and control) RDBMS-specific SQL in one place.
To make the helper more usable, and as slickProfile is implicit, you could instead write:
def page(size: Int, firstRow: Int)(implicit profile: slick.jdbc.JdbcProfile) =
// Logic for deciding on SQL goes here
I feel obliged to comment that using a splice (#$) in plain SQL opens you to SQL injection attacks if any of the values are provided by a user.

Non-greedy configurations across steps

I'm using late acceptance as local search algorithm and here is how it actually picks moves:
If my forager is 5, it'll pick 5 moves and then get 1 random move to be applied for every step.
At every step it only picks moves that are increasing scores ie greedy picking across steps.
Forager.pickMove()
public LocalSearchMoveScope pickMove(LocalSearchStepScope stepScope) {
stepScope.setSelectedMoveCount(selectedMoveCount);
stepScope.setAcceptedMoveCount(acceptedMoveCount);
if (earlyPickedMoveScope != null) {
return earlyPickedMoveScope;
}
List<LocalSearchMoveScope> finalistList = finalistPodium.getFinalistList();
if (finalistList.isEmpty()) {
return null;
}
if (finalistList.size() == 1 || !breakTieRandomly) {
return finalistList.get(0);
}
int randomIndex = stepScope.getWorkingRandom().nextInt(finalistList.size());// should have checked for best here
return finalistList.get(randomIndex);
}
I have two questions:
In first, can we make forager to pick the best of 5 instead of pick 1 randomly.
Can we allow move to pick that degrades score but can increase score later(no way to know it)?
Look for acceptedCountLimit and selectedCountLimit in the docs. Those do exactly that.
That's already the case (especially with Late Acceptance and Simulated Annealing). In the DEBUG log, just look at the step score vs the best score. Or ask for the step score statistic in optaplanner-benchmark.

Searching through two for loops without repeating the result.

I have a task where I am trying to check an array list of "jobs" against an array list of "machines" (all different types) and if the first three letters off the job match the first three letters off the machine (e.g. a PRT job code could only be assigned to a machine with code PRT). I want it to accept the job but if not I would like it to print out a message saying that there is no available machine. I have only been learning Java for a couple of weeks so this might not be the best way:
public void assignJob() {
for(Job j : jobs) {
String jobCode = j.getCode().substring(0, 3);
for(Machine m : machines) {
String machineCode = m.getCode().substring(0,3);
if (jobCode.equals(machineCode)){
m.acceptJob(j);
System.out.println("The job " + j.getCode() + " has been
assigned to a machine.");
break;
}
else {
System.out.println("Sorry there is no machine available to accept the type of job: " + j.getCode() );
}
}
}
}
The issue I am getting is that it is printing out the message every time it goes around the loop so it will say there is no machine available 3 times before it finds the correct machine the fourth time and then says the job has been accepted. I only really want the message one time and only after it has searched and not found anything.
Any help would be appreciated.
Use a boolean found = false; above the outer for loop, move else part of if statement below the outer for loop and make it an if statement. If you've found your match then set found = true; and break loops. Then check if it is found, display message if not found...

Calling deleteRecord() too often or too fast at a time?

I want to delete all records of the model "Article" (around five pieces). I'm doing it like that:
CMS.ArticlesController = Em.ArrayController.extend
deleteAll: ->
#get("content").forEach (article) ->
article.deleteRecord()
However, while executing, it says after three articles:
Uncaught TypeError: Cannot call method 'deleteRecord' of undefined
It works though when using a little delay:
CMS.ArticlesController = Em.ArrayController.extend
deleteAll: ->
#get("content").forEach (article) ->
setTimeout( (->
article.deleteRecord()
), 500)
Why is that?
(Im using Ember.js-rc.1 and Ember Data rev 11 together with the ember-localstorage-adapter by #rpflorence, but I don't think that matter since I didn't call commit() yet...)
Update 1
Just figured out it also works with Ember.run.once...
Update 2
I opened a GitHub issue: https://github.com/emberjs/data/issues/772
As discussed on GitHub, the forEach()-loop breaks, because it breaks the index while removing items.
The solution:
"Copy" it in another array using toArray():
#get("content").toArray().forEach(article) ->
article.deleteRecord()
The nicer approach, if there was a function like forEachInReverse, is to loop backwards, so even though items are removed, the missing index wouldn't hurt the loop.
I still had issues with the above answer. Instead, I used a reverse for loop:
for(var i = items.length - 1; i >= 0; i--) {
items.objectAt(i).destroyRecord(); // or deleteRecord()
}
This destroys each item without disrupting the index.

Subsonic dynamic query expression

I am having a few issues with trying to live in a subsonic world and being a subsonic girl when it comes to subsonic expressions....
after reading Subsonic Query (ConditionA OR ConditionB) AND ConditionC it would appear i am not the only one with this sort of issue but hopefully someone (the almighty rob??) can answer this.
i am attempting to create an expression in my query based on a looping condition. what i want to achieve (in pseudo code) is something like this:
objQuery.andexpressionstart();
foreach (condition in conditions){
if (condition){
objQuery.and(conditionColumn).isequalto(X);
}
}
objQuery.expressionstop();
my main issue is that each condition that is inside the expression is a different column - otherwise i could just use .In() . i also have extra search criteria (read a fair bit) outside so it can't be outside an expression.
i REALLY don't want to leave the warm coseyness of the strongly-typed-subsonic womb however i think in this instance i might have too... if i DO have to is there a way to add to a subsonic query with a hand typed condition so i don't have to change all the other code in the query (alot of business logic living in subsonic land right now)
As always, thanks for any help
cheers
I haven't the time to test this right now, but I think if you do something like the following should work:
bool isFirstCondition = true;
foreach (condition in conditions){
if (condition)
{
if(isFirstCondition)
{
objQuery.AndExpression(conditionColumn).isequalto(X);
isFirstCondition = false;
}
else
{
objQuery.and(conditionColumn).isequalto(X);
}
}
}
Make sure all your other conditions have been added prior to the loop.