Friday, August 24, 2018

How to avoid slash before hash?

I'm using the jquery-router-plugin and run into a problem. I've created a Link tag with a hashbang like this:

Click

and added this route (mainContent is a simple div):

$.router.add('/hello/:foo', function(data) {
    $("#mainContent").html("Hello "+data.foo+"!");
});

The problem is that the browser calls this (not working):

http://{url}/#!/hello/world

instead of this (working)

http://{url}#!/hello/world

How can I get the Browser to use the working URL?

EDIT 1:

When I click the link it calls:

http://localhost/#!/hello/world

But it has to call:

http://localhost#!/hello/world

Monday, August 20, 2018

Performance of metal function multiple call

i make rigid body simulation for iPhone/iPad with using Apple Metal. To do this, i need to make many calls of kernel functions, and i see, that it takes a long time, opposite to CUDA for example. I implemented Metal kernel function call, like it describes in Apple tutorial

let commandQueue = device.newCommandQueue()

var commandBuffers:[MTLCommandBuffer]=[]
var gpuPrograms:[MTLFunction]=[]
var computePipelineFilters:[MTLComputePipelineState]=[]
var computeCommandEncoders:[MTLComputeCommandEncoder]=[]

//here i fill all arrays for my command queue
//and next i execute it 

let threadsPerGroup = MTLSize(width:1,height:1,depth:1)
let numThreadgroups = MTLSize(width:threadsAmount, height:1, depth:1)

for computeCommandEncoder in computeCommandEncoders
{
    computeCommandEncoder.dispatchThreadgroups(numThreadgroups, threadsPerThreadgroup: threadsPerGroup)
}

for computeCommandEncoder in computeCommandEncoders
{
    computeCommandEncoder.endEncoding()
}

for commandBuffer in commandBuffers
{
    commandBuffer.enqueue()
}

for commandBuffer in commandBuffers
{
    commandBuffer.commit()
}

for commandBuffer in commandBuffers
{
    commandBuffer.waitUntilCompleted()
}

I am do up to few dozens metal kernel functions every frame, and it works too slow. I tested it with empty kernel functions - and it shows me, that the problem are in Swift part of execution. I mean, when i want to execute kernel function in CUDA, i just call it like usual function and it works very fast. But here i must make many actions for every execution of every function every frame. May be i don't know something, but i want create all additional objects one time, and then just make something like

 commandQueue.execute()

to execute all kernel functions.

Am i rights in my actions to execute many kernel functions, or there is some other way to do it faster?

Solved

I have a few projects that use multiple shaders in a single step. I only create a single buffer and encoder but multiple pipeline states; one for each compute function.

Remember that MTLCommandQueue is persistent, so only needs to be created once, so my MetalKit View's drawRect() function is roughly this (there are more shaders and textures being passed between them, but you get an idea of structure):

let commandBuffer = commandQueue.commandBuffer()
let commandEncoder = commandBuffer.computeCommandEncoder()

commandEncoder.setComputePipelineState(advect_pipelineState)
commandEncoder.dispatchThreadgroups(threadgroupsPerGrid, 
    threadsPerThreadgroup: threadsPerThreadgroup)

commandEncoder.setComputePipelineState(divergence_pipelineState)
commandEncoder.dispatchThreadgroups(threadgroupsPerGrid, 
    threadsPerThreadgroup: threadsPerThreadgroup)

[...]

commandEncoder.endEncoding()
commandBuffer.commit()

My code actually iterates over one of the shaders twenty times and still runs pretty nippily, so if you reorganise and to follow this structure with a single buffer and a single encoder and only call endEncoding() and commit() once per pass, you may see an improvement in performance.

May being the operative word :)


Sunday, August 19, 2018

PHP Udp socket close not freeing system resources

I am using the following piece of code in a php script to process incoming data over http and forward it to another module and waits for the response. It then closes the socket.

$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_bind($sock,$host,$port) or die("");
if (!socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1)) {  
echo socket_strerror(socket_last_error($sock));
exit;
}
$arrOpt = array('l_onoff' => 1, 'l_linger' => 1);
socket_set_block($sock);
socket_set_option($sock, SOL_SOCKET, SO_LINGER, $arrOpt);
$address = gethostbyname($host);

$msg = $url;
$len = strlen($msg);
socket_sendto($sock, $msg, $len, 0, $remotehost, $remoteport) ;
socket_recvfrom($sock, $buff, 1000, 0, $host, $newport);
socket_close($sock);

The problem faced is that the response is received correctly and the socket_close error is also returning a success(output of socket_last_error). But after that if I do a netstat I see the port being in used and the process (output of /proc/pid/status) is in sleep state. This behavior is random in nature and I am using PHP version 5.3.8 on a Amazon EC2 cloud.

Solved

its about TIME_WAIT ... to free the socket

in Linux run # /proc/sys/net/ipv4/tcp_fin_timeout to find out .... (default 60 sec)

more about


Saturday, August 18, 2018

iOS swift: change imageview image in the middle of rotation animation

I have an opening book animation: https://streamable.com/n1c0n

And I want to on 90 degrees my image has changed.

I use this code:

var book1ImageViewI : UIImageView
let book2ImageViewI : UIImageView

book1ImageViewI = UIImageView(frame: CGRect( x: self.view.frame.size.width / 2 - 140, y: (self.view.frame.size.height / 2) - ( (self.view.frame.width / 2) / 2 ), width: ( (self.view.frame.width / 2) / 8) * 7, height: self.view.frame.width / 2))

book2ImageViewI = UIImageView(frame: CGRect(x: self.view.frame.size.width / 2 - 140, y: (self.view.frame.size.height / 2) - ( (self.view.frame.width / 2) / 2 ), width: ( (self.view.frame.width / 2) / 8) * 7, height: self.view.frame.width / 2))


book1ImageViewI.image = UIImage(named:"attachment_83090027.jpg")
book2ImageViewI.image = UIImage(named:"0a6752b7cd35fc441c152238ee5078384d--antique-books-rabbit-hole.jpg")

book1ImageViewI.layer.anchorPoint = CGPoint(x: 0, y: 0.5)
book2ImageViewI.layer.anchorPoint = CGPoint(x: 0, y: 0.5)

var transform = CATransform3DIdentity
transform.m34 = 1.0 / -2000.0
book1ImageViewI.layer.transform = transform

UIView.animate(withDuration: 1.5, animations: {
    book1ImageViewI.layer.transform = CATransform3DRotate(transform, -.pi/2, 0, 1, 0)
})
{
    (bCompleted) in
    if (bCompleted) {
        book1ImageViewI.layer.transform = CATransform3DRotate(transform, -.pi/2, 0, 1, 0)
    }

    UIView.animate(withDuration: 1.5, animations: {
        book1ImageViewI.layer.transform = CATransform3DRotate(transform, .pi*0.999, 0, 1, 0)
        book1ImageViewI.image = UIImage(named:"0a6752b7cd35fc441c1528ee5078384d--antique-books-rabbit-holer.png")
        }, completion: {
            (bFinished) in
            //Whatever
    })
}

self.view.addSubview(book2ImageViewI)
self.view.addSubview(book1ImageViewI)

Everything works fine. But on 90 degrees animation slightly delayed.

I want to get animation like this without delay: https://streamable.com/q2bf6

How to do it?

P.S. In second animation use this code:

UIView.animate(withDuration: 3,  delay: 0.0,
                       options: [], animations: {

    DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
        book1ImageViewI.image = UIImage(named:"0a6752b7cd35fc441c1528ee5078384d--antique-books-rabbit-holer.png")
    }

    book1ImageViewI.layer.transform = CATransform3DRotate(transform, .pi, 0, 1, 0)

    self.view.layoutIfNeeded()

    }, completion: {_ in

})

But this code does not fit. Because images changes not on 90 degrees. Sometimes earlier. Sometimes later.

Solved

Apparently, the anchor-point change was quite crucial wherever rotation transform is involved, and it is not straightforward. Every time you change anchorpoint, it alters the UIView position, and we must compensate for this change somehow.

Here is the final version using imageview which works without interruption for me. Apparently, it works with addKeyFrame API as well but for simplicity's sake I kept UIView.animate().

The trick I used is to have smaller duration for first animation and larger one for the second. It almost look like a page flip. You can also play with UIView.animate overrides that provide for UIViewAnimationOptions - such as curveEaseIn and curveEaseOut to make it look like page flip of a book.

It seems to work for me, the only thing is that you can't say it is rotating from the front or back. If your imageview is slant (like the slant book page you show in video), it should be visible and you can simply correct by changing the - to + sign within CATransform3DRotate arguments, or vice versa in animation block.

NOTE:

If it still plays hide and seek, try on real device instead of simulator just in case. There is apparent difference due to GPU execution when it comes to animations.

func pageFlipAnimation()
{
    self.myImageView.image = UIImage.init(named: "firstImage")

    var transform = CATransform3DIdentity
    let transform1 = CATransform3DRotate(transform, -CGFloat(Double.pi)*0.5, 0, 1, 0)
    let transform2 = CATransform3DRotate(transform, -CGFloat(Double.pi), 0, 1, 0)

    transform.m34 = 1.0 / -5000.0

    self.setAnchorPoint(anchorPoint: CGPoint(x: 0, y: 0.5), forView: self.myImageView)

    UIView.animate(withDuration: 0.5, animations:
    {
        self.myImageView.layer.transform = transform1
    })
    {
        (bFinished) in
        self.myImageView.image = UIImage.init(named: "secondImage")

        UIView.animate(withDuration: 0.75, animations:
        {
             self.myImageView.layer.transform = transform2
        })
    }
}

//This should ideally be a UIView Extension
func setAnchorPoint(anchorPoint: CGPoint, forView view: UIView)
{
    var newPoint = CGPoint(x:view.bounds.size.width * anchorPoint.x, y:view.bounds.size.height * anchorPoint.y)
    var oldPoint = CGPoint(x:view.bounds.size.width * view.layer.anchorPoint.x, y:view.bounds.size.height * view.layer.anchorPoint.y)

    newPoint = newPoint.applying(view.transform)
    oldPoint = oldPoint.applying(view.transform)

    var position = view.layer.position
    position.x -= oldPoint.x
    position.x += newPoint.x

    position.y -= oldPoint.y
    position.y += newPoint.y

    view.layer.position = position
    view.layer.anchorPoint = anchorPoint
}

This part of your code conflicts:

(bCompleted) in
    if (bCompleted) {
        book1ImageViewI.layer.transform = CATransform3DRotate(transform, -.pi/2, 0, 1, 0)
    }

    UIView.animate(withDuration: 1.5, animations: {
        book1ImageViewI.layer.transform = CATransform3DRotate(transform, .pi*0.999, 0, 1, 0)
        book1ImageViewI.image = UIImage(named:"0a6752b7cd35fc441c1528ee5078384d--antique-books-rabbit-holer.png")
        }, completion: {
            (bFinished) in
            //Whatever
    })

You set book1ImageViewI.layer.transform = CATransform3DRotate(transform, -.pi/2, 0, 1, 0) at the same time as book1ImageViewI.layer.transform = CATransform3DRotate(transform, .pi*0.999, 0, 1, 0)

Try this instead:

(bCompleted) in
    if (bCompleted) {

         UIView.animate(withDuration: 1.5, animations: {
             book1ImageViewI.layer.transform = CATransform3DRotate(transform, -.pi/2, 0, 1, 0)
             book1ImageViewI.image = UIImage(named:"0a6752b7cd35fc441c1528ee5078384d--antique-books-rabbit-holer.png")
             }, completion: {
                 (bFinished) in
                 //Whatever
         })
    }