Home Blog Page 577

Thou Shalt Not Depend on Me: Analysing the Use of Outdated JavaScript Libraries on the Web

Thou shalt not depend on me: analysing the use of outdated JavaScript libraries on the web Lauinger et al., NDSS 2017

Just based on the paper title alone, if you had to guess what the situation is with outdated JavaScript libraries on the web, you’d probably guess it was pretty bad. It turns out it’s very bad indeed, and we’ve created a huge mess with nowhere near enough attention being paid to the issue. The first step towards better solutions is recognising that we have a problem, and Lauinger et al., do a tremendous job in that regard.

In this paper, we conduct the first comprehensive study of client-side JavaScript library usage and the resulting security implications across the Web. Using data from over 133K websites, we show that 37% of them include at least one library with a known vulnerability; the time lag behind the newest release of a library is measured in the order of years.

Read more at Morning Paper

Persistent Memory Extensions to libstdc++/libc++ by Tomasz Kapela, Intel

https://www.youtube.com/watch?v=uvirBdDE6Fk?list=PLbzoR-pLrL6ovByiWK-8ALCkZoCQAK-i_

Tomasz Kapela of Intel describes the Non-Volatile Memory programming model created by the Storage Networking Industry Association at LinuxCon Europe.
 
 

Easier Persistent Memory Programming with Extensions to libstdc++ and libc++

Persistent memory, unlike volatile memory, retains its contents even if the server has a power failure. However, as Tomasz Kapela, Software Engineer at Intel, points out during his LinuxCon Europe 2016 talk, persistent memory is hard to achieve. Since persistent memory programming is non-trivial, they have been focused on making it easier for the end user and for applications to use persistent memory correctly. 

Kapela starts off by describing the Non-Volatile Memory (NVM) programming model created by the Storage Networking Industry Association (SNIA), which is an organization focused on standards for storage and networking. The NVM programming model basically describes using a persistent memory device that allows you to mmap a file to your virtual memory inside of the process where you can do loads and stores and flushes onto the memory device without really involving the kernel of the file system. 

As part of the NVML team, they have a set of open source libraries designed to work on Linux and tackle the problem of persistent memory programming. The libraries include:

  • libpmem: The basic library, flush to persistence
  • libvmem: Volatile Memory Allocator
  • libvmmalloc: Transparent use of libvmem
  • libpmemblk: Persistent memory carved into blocks
  • libpmemlog: Log file (append-mostly)
  • libpmemobj: Transactional Object Store

To address some of the pain points and limitations of using C for persistent memory, Kapela discussed how they are using C++ to develop persistent memory extensions to libstdc++ and libc++. He talked in detail about how they are encapsulating type info into a smart pointer, and making life easier with RAII and lambdas for transactions. With the increase in container usage, they are also working on a proof of concept for persistent memory containers. 

Watch the video of Kapela’s entire talk to get all of the details about the persistent memory extensions to libstdc++ and libc++.

https://www.youtube.com/watch?v=uvirBdDE6Fk?list=PLbzoR-pLrL6ovByiWK-8ALCkZoCQAK-i_

Interested in speaking at Open Source Summit North America on September 11-13? Submit your proposal by May 6, 2017. Submit now>>

Not interested in speaking but want to attend? Linux.com readers can register now with the discount code, LINUXRD5, for 5% off the all-access attendee registration price. Register now to save over $300!

6 Hot Internet of Things (IoT) Security Technologies

 Last October, Internet service provider Dyn came under an attack that disrupted access to popular websites. The cybercriminals who initiated the attack managed to commandeer a large number of internet-connected devices (mostly DVRs and cameras) to serve as their helpers. As a result, cybersecurity expert Bruce Schneier has called for government regulation of the IoT, concluding that both IoT manufacturers and their customers don’t care about the security of the 8.4 billion internet-connected devices in current use.

Whether because of government regulation or good old-fashioned self-interest, we can expect increased investment in IoT security technologies. In its recently-released TechRadar report for security and risk professionals, Forrester Research discusses the outlook for the 13 most relevant and important IoT security technologies, warning that “there is no single, magic security bullet that can easily fix all IoT security issues.”

Read more at Forbes

The Four Values of a DevOps Transformation

A successful devops transformation sees a change in organisational culture. These changes often come in the way of adoption of specific tools or practices. However, to change culture, you need something more fundamental than just the introduction of new tools, or pushing everyone into Scrum teams.

Just like the agile transformations of the past, there was a difference between ‘Doing Agile’, and ‘Being Agile’. ‘We do standups’ – therefore we are Agile. Are we ‘Doing devops’ or are we ‘Being devops’? Agile cultures have evolved to a deeper understanding that it’s not about the team structure, or even the ceremonies, but it is about the values that they hold.

So if we are to be successful with a devops transformation, what are the values we should be aiming to foster, and why are these important in the first place?

Read more at Cevo

The Cloud Native Application Lifecycle Difference: Continuous Change

Embracing cloud native applications means changing how we think about, develop, and deploy applications. This shift is not just technological. It impacts the structure of organizations, as teams align to common business outcomes.

Analyst Steve O’Grady at Redmonk has a great explanation of cloud native apps:

There is a rough consensus on many cloud Native traits. Containers as an atomic unit, for example. Micro-servicesas a means of both construction and communication. Platform independence. Multiple language support. Automation as a feature of everything from build to deployment. High uptime. Ephemeral infrastructure(cattle not pets). And so on

Read more at The New Stack

ZTE’s Approach to Digital Transformation with Software-Defined Networking

Editor’s Note: ZTE is a Gold-level sponsor of Open Networking Summit 2017, to be held April 3-6 in Santa Clara, CA.

The dawn of new services such as 5G, IoT, AR/VR, e-commerce, connected cars,and more, is driving us to digitalization — a massive transition that also requires the network to change.

ZTE’s Network 2020 Vision, along with the corresponding solutions of ‘ElasticNet’ for Digital Transformation, provides a framework for this future network.

ZTE ElasticNetTM  focuses on ‘Triple-layer re-architectures’:

  • Infrastructure re-architecture: To build up a cloud–and-network converged infrastructure layer that is defined as ‘Elastic Cloud Infrastructure.’

  • Network service re-architecture: To construct a virtualized and open service function layer that is defined as ‘Elastic Cloud ServiceTM’

  • Operation re-architecture: To compose a smartly-operated orchestration layer that is defined as ‘MICT-OSTM’.

Figure 1: Triple-layer Re-architectures of Future Network Architecture.

Empowered by cloud computing technologies, big data and SDN/NFV, ElasticNet involves software-defined networks featuring a layered structure, centralized control and unified management.

The ElasticNet architecture and solutions have been deploying in three typical scenarios to accelerate the network evolution.

Central Office (CO) Re-construction

  • Reconstructing the large number of existing central offices and legacy equipment

  • Utilizing these physical resources for ‘telecom cloud’

  • Transforming legacy networks into SDN and NFV-based networks

ZTE’s CO re-construction solution provides an approach to transforming existing architecture from metro access networks (MANs) to ones based on edge-DCs. The control plane will be separated from the forwarding plane and the functions such as BNG, CPE and OLT will be virtualized and centrally deployed on edge-DCs, and further, the vCDN and vEPC-U will be migrated down to the edge-DCs.

High-performance commodity devices will be utilized as the forwarding plane devices and formed to resource pool so that they are able to meet future requirements for ultra-bandwidth processing. Concurrently, by resource sharing, they are able to reduce the quantity of devices and consequently produce savings in Capex and Opex.

Cloud-Native Based Network Slicing

With the impending arrival of 5G, mobile broadband systems will be full-service networks that integrate multiple technologies to meet various application needs. 5G-oriented network slicing is a mechanism that can be used by operators to support network functions running parallel on the same chip,providing on-demand slicing capabilities.

By introducing NFV enhanced ICT (information and communication technology) PaaS — Cloud WorksTM — ZTE’s ElasticNetTM constructs cloud services by intelligent VNF management and an agile DevOps process. This cloud service platform will attract more developers to promote the innovation of personalized and diversified services.

Network on-Demand

To break through the limits of users’ access to the network resources, ZTE network on-demand solution provides essential applications for network capability exposure. With it, the customer will be able to acquire a range of on–demand services. These DIY services include:

  • Flexible and instant network connection services

  • Options on bandwidths, site locations and QoS levels

  • Customized end-to-end reliable automated leased line services

  • Order of service functions, including NAT, firewalls and DPI

Want to learn more about the network of the future? Register now to attend Open Networking Summit 2017, to be held April 3-6 in Santa Clara, CA. Linux.com readers receive 5% off the “attendee” registration to Open Networking Summit with code LINUXRD5.

How to Deploy Kubernetes on the Raspberry Pi

When I became interested in ARM devices, and in the Raspberry Pi in particular, my first project was an OpenVPN server.

By having the Raspberry Pi as a secure gateway to my home network, I could use my phone to control my desktop and remotely play Spotify, open documents, and a bunch of other fun things. I used an existing tutorial for that first project because I was afraid of piping anything into the command line on my own.

Read more at OpenSource.com

Performance Analysis in Linux

Written by Gabriel Krisman Bertazi, Software Engineer at Collabora.

Dynamic profilers are tools to collect data statistics about applications while they are running, with minimal intrusion on the application being observed.

The kind of data that can be collected by profilers varies deeply, depending on the requirements of the user. For instance, one may be interested in the amount of memory used by a specific application, or maybe the number of cycles the program executed, or even how long the CPU was stuck waiting for data to be fetched from the disks. All this information is valuable when tracking performance issues, allowing the programmer to identify bottlenecks in the code, or even to learn how to tune an application to a specific environment or workload.

In fact, maximizing performance or even understanding what is slowing down your application is a real challenge on modern computer systems. A modern CPU carries so many hardware techniques to optimize performance for the most common usage case, that if an application doesn’t intentionally exploit them, or worse, if it accidentally lies in the special uncommon case, it may end up experiencing terrible results without doing anything apparently wrong.

Let’s take a quite non-obvious way of how things can go wrong, as an example.

Forcing branch mispredictions

Based on the example from here.

The code below is a good example of how non-obvious performance assessment can be. In this function, the first for loop initializes a vector of size n with random values ranging from 0 to N. We can assume the values are well distributed enough for the vector elements to be completely unsorted.

The second part of the code has a for loop nested inside another one. The outer loop, going from 0 to K, is actually a measurement trick. By executing the inner loop many times, it stresses out the performance issues in that part of the code. In this case, it helps to reduce any external factor that may affect our measurement.

The inner loop is where things get interesting. This loop crawls over the vector and decides whether the value should be accumulated in another variable, depending on whether the element is higher than N/2 or not. This is done using an if clause, which gets compiled into a conditional branch instruction, which modifies the execution flow depending on the calculated value of the condition, in this case, if vec[i] >= N/2, it will enter the if leg, otherwise it will skip it entirely.

int rand_partsum(int n)
{
  int i,k;
  long sum = 0;
  int *vec = malloc(n * sizeof(int));

  for (i = 0; i < n; i++)
    vec[i] = rand()%n;

  for (k = 0; k < 1000000; k++)
    for (i = 0; i < n; i++)
      if (vec[i] > n/2)
	sum += n[i];

  return sum;
}

When executing the code above on an Intel Core i7-5500U, with a vector size of 5000 elements (N=5000), it takes an average of 29.97 seconds. Can we do any better?

One may notice that this vector is unsorted, since each element comes from a call to rand(). What if we sorted the vector before executing the second for loop? For the sake of the example, let’s say we add a call to the glibc implementation of QuickSort right after the initialization loop.

A naive guess would suggest that the algorithm got worse, because we just added a new sorting step, thus raising the complexity of the entire code. One should assume this would result on a higher execution time.

But, in fact, when executing the sorted version in the same machine, the average execution time drops to 13.20 seconds, which is a reduction of 56% in execution time. Why does adding a new step actually reduces the execution time? The fact is that pre-sorting the vector in this case, allows the cpu to do a much better job at internally optimizing the code during execution. In this case, the issue observed was a high number of branch mispredictions, which were triggered by the conditional branch that implements the if clause.

Modern CPUs have quite deep pipelines, meaning that the instruction being fetched on any given cycle is always a few instructions down the road than the instruction actually executed on that cycle. When there is a conditional branch along the way, there are two possible paths that can be followed, and the prefetch unit has no idea which one it should choose, until all the actual condition for that instruction is calculated.

The obvious choice for the Prefetch unit on such cases is to stall and wait until the execution unit decides the correct path to follow, but stalling the pipeline like this is very costly. Instead, a speculative approach can be taken by a unit called Branch Predictor, which tries to guess which path should be taken. After the condition is calculated, the CPU verifies the guessed path: if it got the prediction right, in other words, if a branch prediction hit occurs, the execution just continues without much performance impact, but if it got it wrong, the processor needs to flush the entire pipeline, go back, and restart executing the correct path. The later is called a branch prediction miss, and is also a costly operation.

In systems with a branch predictor, like any modern CPU, the predictor is usually based on the history of the particular branches. If a conditional branch usually goes a specific way, the next time it appears, the predictor will assume it will take the same route.

Back to our example code, that if condition inside the for loop does not have any specific pattern. Since the vector elements are completely random, sometimes it will enter the if leg, sometimes it will skip it entirely. That is a very hard situation for the branch predictor, who keeps guessing wrong and triggering flushes in the pipeline, which keeps delaying the application.

In the sorted version, instead, it is very easy to guess whether it should enter the if leg or not. For the first part of the vector, where the elements are mostly < N/2, the if leg will always be skipped, while for the second part, it will always enter the if leg. The branch predictor is capable of learning this pattern after a few iterations, and is able to do much better guesses about the flow, reducing the number of branch misses, thus increasing the overall performance.

Well, pointing specific issues like this is usually hard, even for a simple code like the example above. How could we be sure that the the program is hitting enough branch mispredictions to affect performance? In fact, there are always many things that could be the cause of slowness, even for a slightly more complex program.

Perf_events is an interface in the Linux kernel and a userspace tool to sample hardware and software performance counters. It allows, among many other things, to query the CPU register for the statistics of the branch predictor, i.e. the number of prediction hits and misses of a given application.

The userspace tool, known as the perf command, is available in the usual channels of common distros. In Debian, for instance, you can install it with:

sudo apt install linux-perf

We’ll dig deeper into the perf tool later on another post, but for now, let’s use the, perf record and perf annotate commands, which allow tracing the program and annotating the source code with the time spent on each instruction, and the perf stat command, which allows to run a program and display statistics about it:

At first, we can instruct perf to instrument the program and trace its execution:

[krisman@dilma bm]$ perf record ./branch-miss.unsorted
[ perf record: Woken up 19 times to write data ]
[ perf record: Captured and wrote 4.649 MB perf.data (121346 samples) ]

The perf record will execute the program passed as parameter and collect performance information into a new perf.data file. This file can then be passed to other perf commands. In this case, we pass it to the perf annotate command, which crawls over each address in the program and prints the number of samples that was collected while the program was executing each instruction. Instructions with a higher number of samples indicates that the program spent more time in that region, indicating that it is hot code, and a good part of the program to try to optimize. Notice that, for modern processors, the exact position is an estimation, so this information must be used with care. As a rule of thumb, one should be looking for hot regions, instead of single hot instructions.

Below is the output of perf annotate, when analyzing the function above. The output is truncated to display only the interesting parts.

[krisman@dilma bm]$ perf annotate

	:
	:      int rand_partsum()
	:      {
   0.00 :        74e:   push   %rbp
   0.00 :        74f:   mov    %rsp,%rbp
   0.00 :        752:   push   %rbx
   0.00 :        753:   sub    $0x38,%rsp
   0.00 :        757:   mov    %rsp,%rax
   0.00 :        75a:   mov    %rax,%rbx

   [...] 

   0.00 :        7ce:   mov    $0x0,%edi
   0.00 :        7d3:   callq  5d0 <time@plt>
   0.00 :        7d8:   mov    %eax,%edi
   0.00 :        7da:   callq  5c0 <srand@plt>
	:              for (i = 0; i < n; i++)
   0.00 :        7df:   movl   $0x0,-0x14(%rbp)
   0.00 :        7e6:   jmp    804 <main+0xb6>
	:                      vec[i] = rand()%n;
   0.00 :        7e8:   callq  5e0 <rand@plt>
   0.00 :        7ed:   cltd   
   0.00 :        7ee:   idivl  -0x24(%rbp)
   0.00 :        7f1:   mov    %edx,%ecx
   0.00 :        7f3:   mov    -0x38(%rbp),%rax
   0.00 :        7f7:   mov    -0x14(%rbp),%edx
   0.00 :        7fa:   movslq %edx,%rdx
   0.00 :        7fd:   mov    %ecx,(%rax,%rdx,4)
	:              for (i = 0; i < n; i++)
   0.00 :        800:   addl   $0x1,-0x14(%rbp)
   0.00 :        804:   mov    -0x14(%rbp),%eax
   0.00 :        807:   cmp    -0x24(%rbp),%eax
   0.00 :        80a:   jl     7e8 <main+0x9a>

   [...]

	 :              for (k = 0; k < 1000000; k++)
    0.00 :        80c:   movl   $0x0,-0x18(%rbp)
    0.00 :        813:   jmp    85e <main+0x110>
	 :                      for (i = 0; i < n; i++)
    0.01 :        815:   movl   $0x0,-0x14(%rbp)
    0.00 :        81c:   jmp    852 <main+0x104>
	 :                              if (vec[i] > n/2)
    0.20 :        81e:   mov    -0x38(%rbp),%rax
    6.47 :        822:   mov    -0x14(%rbp),%edx
    1.94 :        825:   movslq %edx,%rdx
   26.86 :        828:   mov    (%rax,%rdx,4),%edx
    0.08 :        82b:   mov    -0x24(%rbp),%eax
    1.46 :        82e:   mov    %eax,%ecx
    0.62 :        830:   shr    $0x1f,%ecx
    3.82 :        833:   add    %ecx,%eax
    0.06 :        835:   sar    %eax
    0.70 :        837:   cmp    %eax,%edx
    0.42 :        839:   jle    84e <main+0x100>
	 :                                      sum += vec[i];
    9.15 :        83b:   mov    -0x38(%rbp),%rax
    5.91 :        83f:   mov    -0x14(%rbp),%edx
    0.26 :        842:   movslq %edx,%rdx
    5.87 :        845:   mov    (%rax,%rdx,4),%eax
    2.09 :        848:   cltq
    9.31 :        84a:   add    %rax,-0x20(%rbp)
	 :                      for (i = 0; i < n; i++)
   16.66 :        84e:   addl   $0x1,-0x14(%rbp)
    6.46 :        852:   mov    -0x14(%rbp),%eax
    0.00 :        855:   cmp    -0x24(%rbp),%eax
    1.63 :        858:   jl     81e <main+0xd0>
	 :              for (k = 0; k < 1000000; k++)

   [...]

The first thing to notice is that the perf command tries to interleave C code with the Assembly code. This feature requires compiling the test program with -g3 to include debug information.

The number before the ‘:’ is the percentage of samples collected while the program was executing each instruction. Once again, this is not an exact information, so you should be looking for hot regions, and not specific instructions.

The first and second hunk are the function prologue, which was executed only once, and the vector initialization. According to the profiling data, there is little point in attempting to optimize them, because the execution practically didn’t spend any time on it. The third hunk is the second loop, where it spent almost all the execution time. Since that loop is where most of our samples where collected, we can assume that it is a hot region, which we can try to optimize. Also, notice that most of the samples were collected around that if leg. This is another indication that we should look into that specific code.

To find out what might be causing the slowness, we can use the perf stat command, which prints a bunch of performance counters information for the entire program. Let’s take a look at its output.

[krisman@dilma bm]$ perf stat ./branch-miss.unsorted

 Performance counter stats for './branch-miss.unsorted:

    29876.773720  task-clock (msec) #    1.000 CPUs utilized
	      25  context-switches  #    0.001 K/sec
	       0  cpu-migrations    #    0.000 K/sec
	      49  page-faults       #    0.002 K/sec
  86,685,961,134  cycles            #    2.901 GHz
  90,235,794,558  instructions      #    1.04  insn per cycle
  10,007,460,614  branches          #  334.958 M/sec
   1,605,231,778  branch-misses     #   16.04% of all branches

   29.878469405 seconds time elapsed

Perf stat will dynamically profile the program passed in the command line and report back a number of statistics about the entire execution. In this case, let’s look at the 3 last lines in the output. The first one gives the rate of instructions executed per CPU cycle; the second line, the total number of branches executed; and the third, the percentage of those branches that resulted in a branch miss and pipeline flush.

Perf is even nice enough to put important or unexpected results in red. In this case, the last line, Branch-Misses, was unexpectedly high, thus it was displayed in red in this test.

And now, let’s profile the pre-sorted version. Look at the number of branch misses:

[krisman@dilma bm]$ perf stat ./branch-miss.sorted

 Performance counter stats for './branch-miss.sorted:

    14003.066457  task-clock (msec) #    0.999 CPUs utilized
	     175  context-switches  #    0.012 K/sec
	       4  cpu-migrations    #    0.000 K/sec
	      56  page-faults       #    0.004 K/sec
  40,178,067,584  cycles            #    2.869 GHz
  89,689,982,680  instructions      #    2.23  insn per cycle
  10,006,420,927  branches          #  714.588 M/sec
       2,275,488  branch-misses     #    0.02% of all branches

  14.020689833 seconds time elapsed

It went down from over 16% to just 0.02% of the total branches! This is very impressive and is likely to explain the reduction in execution time. Another interesting value is the number of instructions per cycle, which more than doubled. This happens because, once we reduced the number of stalls, we make better use of the pipeline, obtaining a better instruction throughput.

Wrapping up

As demonstrated by the example above, figuring out the root cause of a program slowness is not always easy. In fact, it gets more complicated every time a new processor comes out with a bunch of shiny new optimizations.

Despite being a short example code, the branch misprediction case is still quite non-trivial for anyone not familiar with how the branch prediction mechanism works. In fact, if we just look at the algorithm, we could have concluded that adding a sort algorithm would just add more overhead to the algorithm. Thus, this example gives us a high-level view of how helpful profiling tools really are. By using just one of the several features provided by the perf tool, we were able to draw major conclusions about the program being examined.

Keynote: Creative Approaches To Diversity – Katharina Borchert, Chief Innovation Officer, Mozilla

https://www.youtube.com/watch?v=Szm8x5nbezw?list=PLbzoR-pLrL6rm2vBxfJAsySspk2FLj4fM

Lack of diversity may be stunting projects’ growth potential, said Mozilla’s Katharina Borchert at Open Source Leadership Summit.